controllers/clustersecret/clustersecret_controller.go (113 lines of code) (raw):

package clustersecret import ( "context" "encoding/json" "fmt" corev1 "k8s.io/api/core/v1" k8sErrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" "github.com/epam/edp-cd-pipeline-operator/v2/pkg/multiclusterclient" ) const ( // nolint:gosec // Cluster secret label. integrationSecretTypeLabel = "app.edp.epam.com/secret-type" integrationSecretTypeLabelVal = "cluster" ) type ReconcileClusterSecret struct { client client.Client } func NewReconcileClusterSecret(k8sClient client.Client) *ReconcileClusterSecret { return &ReconcileClusterSecret{client: k8sClient} } func (r *ReconcileClusterSecret) SetupWithManager(mgr ctrl.Manager) error { p := predicate.Funcs{ CreateFunc: func(event event.CreateEvent) bool { return hasClusterSecretLabelLabel(event.Object) }, DeleteFunc: func(deleteEvent event.DeleteEvent) bool { return false }, UpdateFunc: func(updateEvent event.UpdateEvent) bool { return hasClusterSecretLabelLabel(updateEvent.ObjectNew) }, GenericFunc: func(genericEvent event.GenericEvent) bool { return hasClusterSecretLabelLabel(genericEvent.Object) }, } err := ctrl.NewControllerManagedBy(mgr). For(&corev1.Secret{}, builder.WithPredicates(p)). Complete(r) if err != nil { return fmt.Errorf("failed to build ClusterSecret controller: %w", err) } return nil } //+kubebuilder:rbac:groups="",namespace=placeholder,resources=secrets,verbs=get;list;watch;update;patch;create // Reconcile process secrets with app.edp.epam.com/secret-type: cluster label. func (r *ReconcileClusterSecret) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { secret := &corev1.Secret{} if err := r.client.Get(ctx, request.NamespacedName, secret); err != nil { if k8sErrors.IsNotFound(err) { return reconcile.Result{}, nil } return reconcile.Result{}, fmt.Errorf("failed to get Secret: %w", err) } if err := r.createArgoCDClusterSecret(ctx, secret); err != nil { return reconcile.Result{}, err } return reconcile.Result{}, nil } func (r *ReconcileClusterSecret) createArgoCDClusterSecret(ctx context.Context, secret *corev1.Secret) error { log := ctrl.LoggerFrom(ctx) log.Info("Start creating ArgoCD cluster secret") restConf, err := multiclusterclient.ClusterSecretToRestConfig(secret) if err != nil { return fmt.Errorf("failed to convert cluster secret to rest config: %w", err) } argoClusterSecret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-argocd-cluster", secret.Name), Namespace: secret.Namespace, }, } var res controllerutil.OperationResult if res, err = controllerutil.CreateOrUpdate(ctx, r.client, argoClusterSecret, func() error { argoClusterConf := &ClusterConfig{} argoClusterConf.BearerToken = restConf.BearerToken argoClusterConf.CAData = restConf.TLSClientConfig.CAData argoClusterConf.Insecure = restConf.TLSClientConfig.Insecure var rawConf json.RawMessage if rawConf, err = json.Marshal(argoClusterConf); err != nil { return fmt.Errorf("failed to marshal cluster config: %w", err) } addClusterLabel(argoClusterSecret) argoClusterSecret.Data = map[string][]byte{ "name": []byte(secret.Name), "server": []byte(restConf.Host), "config": rawConf, } if err = controllerutil.SetControllerReference(secret, argoClusterSecret, r.client.Scheme()); err != nil { return fmt.Errorf("failed to set controller reference: %w", err) } return nil }); err != nil { return fmt.Errorf("failed to create/update or update ArgoCD cluster secret: %w", err) } log.Info(fmt.Sprintf("ArgoCD cluster secret has been %s", res)) return nil } func hasClusterSecretLabelLabel(object client.Object) bool { return object.GetLabels()[integrationSecretTypeLabel] == integrationSecretTypeLabelVal } func addClusterLabel(argoClusterSecret *corev1.Secret) { labels := argoClusterSecret.GetLabels() if labels == nil { labels = make(map[string]string, 1) } labels[argoCDClusterLabel] = argoCDClusterLabelVal argoClusterSecret.SetLabels(labels) }