package internal import ( "bytes" "context" "errors" "fmt" "html/template" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" ) 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" } }, "spec": { "blocks": [ {{- range $i, $ip := .IPs }} {{- if $i}},{{ end }} { "cidr": "{{ $ip }}" } {{- 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 errors.New(fmt.Sprintf("Error creating REST Client: %v", err.Error())) } body, err := generateIpPool(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(). 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 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 "", errors.New(fmt.Sprintf("Errors in ippool template: %s", err.Error())) } var buf bytes.Buffer err = tmpl.Execute(&buf, &config) if err != nil { return "", errors.New(fmt.Sprintf("Could not render ippool template: %s", err.Error())) } return buf.String(), nil }