package internal import ( "bytes" "context" "fmt" "html/template" log "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" ) var CILIUM_GROUP_VERSION = schema.GroupVersion{ Group: "cilium.io", Version: "v2alpha1", } var IP_POOL_TEMPLATE = ` { "apiVersion": "cilium.io/v2alpha1", "kind": "CiliumLoadBalancerIPPool", "metadata": { "name": "{{ .Name }}", "annotations": { "argocd.argoproj.io/tracking-id": "cilium-lb:cilium.io/CiliumLoadBalancerIPPool:kube-system/covidnetes-pool", "managed-by": "canada-kaktus" } }, "spec": { "blocks": [ {{- range $i, $ip := .IPs }} {{- if $i}},{{ end }} { "cidr": "{{ $ip }}/32" } {{- end }} ], "disabled": false } } ` type CrdConfig struct { Name string IPs []string } func RecreateIPPoolCrd(cfg *Config, name string, ips []string) error { routeclient, err := createRestClient() if err != nil { return fmt.Errorf("error creating REST Client: %v", err.Error()) } body, err := generateIpPool(name, ips) if err != nil { return fmt.Errorf("error generating CRD: %v", err.Error()) } res := routeclient.Put(). Resource("ciliumloadbalancerippools"). Name(name). Body([]byte(body)). Do(context.TODO()) var status int res.StatusCode(&status) if status < 200 || status >= 400 { return fmt.Errorf("failed to post CRD to kube api: %v", res.Error()) } raw, rawErr := res.Raw() log.WithFields(log.Fields{ "Caller": "RecreateIPPoolCrd", }).Infof("Response from k8s api server: %s", string(raw)) if rawErr != nil { log.WithFields(log.Fields{ "Caller": "RecreateIPPoolCrd", }).Warnf("Could not get raw response from k8s api server: %v", rawErr) } return nil } func createRestClient() (*rest.RESTClient, error) { k8s_config, err := rest.InClusterConfig() if err != nil { return nil, fmt.Errorf("could not create in cluster k8s config: %v", err) } k8s_config.APIPath = "/apis" k8s_config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() k8s_config.GroupVersion = &CILIUM_GROUP_VERSION routeclient, err := rest.RESTClientFor(k8s_config) if err != nil { return nil, fmt.Errorf("could not create k8s client: %v", err) } return routeclient, nil } func generateIpPool(name string, ips []string) (string, error) { config := CrdConfig{ Name: name, IPs: ips, } tmpl, err := template.New("ippool").Parse(IP_POOL_TEMPLATE) if err != nil { return "", fmt.Errorf("errors in ippool template: %s", err.Error()) } var buf bytes.Buffer err = tmpl.Execute(&buf, &config) if err != nil { return "", fmt.Errorf("could not render ippool template: %s", err.Error()) } return buf.String(), nil } // func RegisterCiliumCrd() error { // SchemeBuilder := &apiSchema.Builder{GroupVersion: CILIUM_GROUP_VERSION} // err := SchemeBuilder.AddToScheme(scheme.Scheme) // if err != nil { // return fmt.Errorf("could not register cilium crd: %v", err.Error()) // } // return nil // }