diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 4065d5d..43cc576 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -15,7 +15,7 @@ jobs: - name: Install Go uses: actions/setup-go@v2 with: - go-version: "1.19" + go-version: "1.21" - name: go fmt run: make fmt @@ -37,7 +37,7 @@ jobs: - name: Install Go uses: actions/setup-go@v2 with: - go-version: "1.19" + go-version: "1.21" - name: Run tests run: make test @@ -53,7 +53,7 @@ jobs: - name: Install Go uses: actions/setup-go@v2 with: - go-version: "1.19" + go-version: "1.21" - name: Try build run: make diff --git a/Makefile b/Makefile index ce51fcb..16e820d 100644 --- a/Makefile +++ b/Makefile @@ -117,7 +117,7 @@ docker-push-manifest: ## Push the fat manifest docker image. .PHONY: lint lint: golangci-lint ## Lint the codebase - $(GOLANGCI_LINT) run -v --go=1.19 --timeout 3m0s + $(GOLANGCI_LINT) run -v --go=1.21 --timeout 3m0s ##@ Deployment @@ -145,7 +145,7 @@ undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/confi GOLANGCI_LINT = $(shell pwd)/bin/golangci-lint .PHONY: golangci-lint golangci-lint: ## Download golangci-lint locally if necessary. - $(call go-get-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint@v1.50.1) + $(call go-get-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint@v1.57.2) CONTROLLER_GEN = $(shell pwd)/bin/controller-gen .PHONY: controller-gen diff --git a/controllers/configs.go b/controllers/configs.go index 855ae49..12e0776 100644 --- a/controllers/configs.go +++ b/controllers/configs.go @@ -9,6 +9,7 @@ import ( "crypto/x509/pkix" "encoding/base64" "encoding/pem" + "fmt" "math/big" "net" "strings" @@ -20,6 +21,7 @@ import ( "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apiserver/pkg/storage/names" @@ -37,7 +39,7 @@ apiVersion: v1 clusters: - cluster: certificate-authority-data: - server: https://:6443 + server: https://: name: microk8s-cluster contexts: - context: @@ -75,62 +77,53 @@ func newDialer() *connrotation.Dialer { // kubeconfigForCluster will fetch a kubeconfig secret based on cluster name/namespace, // use it to create a clientset, and return it. func (r *MicroK8sControlPlaneReconciler) kubeconfigForCluster(ctx context.Context, cluster client.ObjectKey) (*kubernetesClient, error) { - kubeconfigSecret := &corev1.Secret{} + secret := &corev1.Secret{} // See if the kubeconfig exists. If not create it. - secrets := &corev1.SecretList{} - err := r.Client.List(ctx, secrets) - if err != nil { + err := r.Client.Get(ctx, types.NamespacedName{ + Namespace: cluster.Namespace, + Name: fmt.Sprintf("%s-kubeconfig", cluster.Name), + }, secret) + switch { + case err == nil: + return clientFromKubeconfig(secret.Data["value"]) + case apierrors.IsNotFound(err): + default: return nil, err } - found := false - for _, s := range secrets.Items { - if s.Name == cluster.Name+"-kubeconfig" { - found = true - } - } - c := &clusterv1.Cluster{} - err = r.Client.Get(ctx, cluster, c) - if err != nil { + if err := r.Client.Get(ctx, cluster, c); err != nil { return nil, err } - if !found && c.Spec.ControlPlaneEndpoint.IsValid() { - kubeconfig, err := r.genarateKubeconfig(ctx, cluster, c.Spec.ControlPlaneEndpoint.Host) - if err != nil { - return nil, err - } - configsecret := &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: cluster.Namespace, - Name: cluster.Name + "-kubeconfig", - Labels: map[string]string{ - clusterv1.ClusterLabelName: cluster.Name, - }, - }, - Data: map[string][]byte{ - "value": []byte(*kubeconfig), - }, - } - err = r.Client.Create(ctx, configsecret) - if err != nil { - return nil, err - } + if !c.Spec.ControlPlaneEndpoint.IsValid() { + return nil, fmt.Errorf("ControlPlaneEndpoint is not set yet, cannot generate kubeconfig yet") } - err = r.Client.Get(ctx, - types.NamespacedName{ + kubeconfig, err := r.generateKubeconfig(ctx, cluster, c.Spec.ControlPlaneEndpoint.Host, c.Spec.ControlPlaneEndpoint.Port) + if err != nil { + return nil, err + } + secret = &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ Namespace: cluster.Namespace, Name: cluster.Name + "-kubeconfig", + Labels: map[string]string{ + clusterv1.ClusterLabelName: cluster.Name, + }, }, - kubeconfigSecret, - ) - if err != nil { + Data: map[string][]byte{ + "value": []byte(*kubeconfig), + }, + } + if err := r.Client.Create(ctx, secret); err != nil { return nil, err } + return clientFromKubeconfig([]byte(*kubeconfig)) +} - config, err := clientcmd.RESTConfigFromKubeConfig(kubeconfigSecret.Data["value"]) +func clientFromKubeconfig(kubeconfigBytes []byte) (*kubernetesClient, error) { + config, err := clientcmd.RESTConfigFromKubeConfig(kubeconfigBytes) if err != nil { return nil, err } @@ -148,8 +141,7 @@ func (r *MicroK8sControlPlaneReconciler) kubeconfigForCluster(ctx context.Contex dialer: dialer, }, nil } - -func (r *MicroK8sControlPlaneReconciler) genarateKubeconfig(ctx context.Context, cluster client.ObjectKey, host string) (kubeconfig *string, err error) { +func (r *MicroK8sControlPlaneReconciler) generateKubeconfig(ctx context.Context, cluster client.ObjectKey, host string, port int32) (kubeconfig *string, err error) { // Get the secret with the CA readCASecret := &corev1.Secret{} err = r.Client.Get(ctx, @@ -228,7 +220,13 @@ func (r *MicroK8sControlPlaneReconciler) genarateKubeconfig(ctx context.Context, return nil, err } + // handle unset port value + if port == 0 { + port = 6443 + } + config := strings.Replace(templateConfig, "", host, -1) + config = strings.Replace(config, "", fmt.Sprintf("%d", port), -1) config = strings.Replace(config, "", base64.StdEncoding.EncodeToString(readCASecret.Data["crt"]), -1) config = strings.Replace(config, "", base64.StdEncoding.EncodeToString(certPEM.Bytes()), -1) config = strings.Replace(config, "", base64.StdEncoding.EncodeToString(keyPEM.Bytes()), -1)