package internal import ( "bytes" "context" "errors" "fmt" "html/template" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" ) var CRD_TEMPLATE = ` { "apiVersion": "externaldns.k8s.io/v1alpha1", "kind": "DNSEndpoint", "metadata": { "name": "{{ .Name }}", "annotations": { "external.dns/provider": "cf" } }, "spec": { "endpoints": [ { "dnsName": "mail", "recordTTL": 180, "recordType": "A", "targets": [ {{ range .IPs -}} "{{ . }}", {{ end -}} ] } ] } } ` type CrdConfig struct { Name string IPs []string } func RecreateDnsCrd(cfg *Config, name string, ips []string) error { routeclient, err := createRestClient() if err != nil { return errors.New(fmt.Sprintf("Error creating REST Client: %v", err.Error())) } body, err := generateCrd(name, ips) if err != nil { return errors.New(fmt.Sprintf("Error generating CRD: %v", err.Error())) } decode := scheme.Codecs.UniversalDeserializer().Decode obj, _, err := decode([]byte(body), nil, nil) if err != nil { return errors.New(fmt.Sprintf("Could not deserialize CRD: %v", err.Error())) } res := routeclient.Post(). Namespace(cfg.Namespace). Resource("routes"). Body(&obj). Do(context.TODO()) var status int res.StatusCode(&status) if status >= 200 && status <= 400 { return errors.New(fmt.Sprintf("Failed to post CRD to kube api: %v", res.Error().Error())) } return nil } func createRestClient() (*rest.RESTClient, error) { k8s_config, err := rest.InClusterConfig() if err != nil { return nil, errors.New(fmt.Sprintf("Could not create in cluster k8s config: %v", err)) } k8s_config.APIPath = "/apis" k8s_config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() routeclient, err := rest.RESTClientFor(k8s_config) if err != nil { return nil, errors.New(fmt.Sprintf("Could not create k8s client: %v", err)) } return routeclient, nil } func generateCrd(name string, ips []string) (string, error) { config := CrdConfig{ Name: name, IPs: ips, } tmpl, err := template.New("crd").Parse(CRD_TEMPLATE) if err != nil { return "", errors.New(fmt.Sprintf("Errors in crd template: %s", err.Error())) } var buf bytes.Buffer err = tmpl.Execute(&buf, &config) if err != nil { return "", errors.New(fmt.Sprintf("Could not render crd template: %s", err.Error())) } return buf.String(), nil }