cert-manager-webhook-sthome/pkg/dns/update.go

102 lines
2.3 KiB
Go

package dns
import (
"bytes"
"fmt"
"io"
"os/exec"
"sync"
"github.com/stuurmcp/cert-manager-webhook-sthome/pkg/util"
"k8s.io/klog/v2"
)
const (
nsupdateCmd = "nsupdate"
ttl = "7200"
)
type output struct {
buf *bytes.Buffer
lines []string
*sync.Mutex
}
func AddTxtRecord(nameservers []string, domain string, fulldomain string, recordvalue string) error {
return processTXT("add", nameservers, domain, fulldomain, recordvalue)
}
func DeleteTxtRecord(nameservers []string, domain string, fulldomain string, recordvalue string) error {
return processTXT("delete", nameservers, domain, fulldomain, recordvalue)
}
func processTXT(action string, nameservers []string, domain string, fulldomain string, recordvalue string) error {
for _, ns := range nameservers {
klog.Infof("======= ns: %s =======", ns)
zone := extractDomainName(domain)
nsucmd := " gsstsig\n server " + ns + "\n zone " + zone + "\n class IN\n update " + action + " " + fulldomain + " " + ttl + " TXT " + recordvalue + "\n send\n"
out, err := nsupdate(nsucmd)
if err != nil {
return err
}
for _, line := range out.lines {
klog.Infof(line)
}
}
return nil
}
func newOutput() *output {
return &output{
buf: &bytes.Buffer{},
lines: []string{},
Mutex: &sync.Mutex{},
}
}
func (rw *output) Write(p []byte) (int, error) {
rw.Lock()
defer rw.Unlock()
return rw.buf.Write(p)
}
func nsupdate(nsucmd string) (*output, error) {
klog.Infof("nsupdate\n%s", nsucmd) // for debugging
cmd := exec.Command(nsupdateCmd)
stdout := newOutput()
cmd.Stdout = stdout
stdinR, stdinW := io.Pipe()
stderrR, stderrW := io.Pipe()
cmd.Stdin = stdinR
cmd.Stderr = stderrW
err := cmd.Start()
if err != nil {
return stdout, fmt.Errorf("could not start %s command: %v", nsupdateCmd, err)
}
go func() {
io.WriteString(stdinW, nsucmd)
stdinW.Close()
}()
errBuf := new(bytes.Buffer)
go func() {
io.Copy(errBuf, stderrR)
stderrR.Close()
}()
err = cmd.Wait()
if err != nil {
return stdout, fmt.Errorf("%s did not run successfully: %v stderr: %s", nsupdateCmd, err, errBuf.String())
}
return stdout, nil
}
func extractDomainName(zone string) string {
authZone, err := util.FindZoneByFqdn(zone, util.RecursiveNameservers)
if err != nil {
klog.Errorf("could not get zone by fqdn %v", err)
return zone
}
return util.UnFqdn(authZone)
}