From 4ddbbfec63248d83146e5d663a0f823cc2a6092a Mon Sep 17 00:00:00 2001 From: shreddedbacon Date: Tue, 2 May 2023 10:49:56 +1000 Subject: [PATCH 1/3] feat: support being able to force rotate robot account credentials --- controllers/v1beta1/build_helpers.go | 24 ++-- .../v1beta1/harborcredential_controller.go | 83 ++++++++++++++ controllers/v1beta1/predicates.go | 46 ++++++++ internal/harbor/harbor21x.go | 58 +++++----- internal/harbor/harbor22x.go | 81 +++++++------ internal/harbor/harbor_credentialrotation.go | 108 +++++++++--------- internal/harbor/harbor_helpers.go | 73 ++++++++---- main.go | 15 +++ 8 files changed, 337 insertions(+), 151 deletions(-) create mode 100644 controllers/v1beta1/harborcredential_controller.go diff --git a/controllers/v1beta1/build_helpers.go b/controllers/v1beta1/build_helpers.go index a92e7d4b..c2f29bda 100644 --- a/controllers/v1beta1/build_helpers.go +++ b/controllers/v1beta1/build_helpers.go @@ -218,7 +218,8 @@ func (r *LagoonBuildReconciler) getOrCreateNamespace(ctx context.Context, namesp hProject, lagoonBuild.Spec.Project.Environment, ns, - lagoonHarbor.RobotAccountExpiry) + lagoonHarbor.RobotAccountExpiry, + false) if err != nil { return fmt.Errorf("Error creating harbor robot account: %v", err) } @@ -233,21 +234,20 @@ func (r *LagoonBuildReconciler) getOrCreateNamespace(ctx context.Context, namesp hProject, lagoonBuild.Spec.Project.Environment, ns, - time.Now().Add(lagoonHarbor.RobotAccountExpiry).Unix()) + time.Now().Add(lagoonHarbor.RobotAccountExpiry).Unix(), + false) if err != nil { return fmt.Errorf("Error creating harbor robot account: %v", err) } } - if robotCreds != nil { - // if we have robotcredentials to create, do that here - if err := harbor.UpsertHarborSecret(ctx, - r.Client, - ns, - "lagoon-internal-registry-secret", - lagoonHarbor.Hostname, - robotCreds); err != nil { - return fmt.Errorf("Error upserting harbor robot account secret: %v", err) - } + // if we have robotcredentials to create, do that here + _, err = lagoonHarbor.UpsertHarborSecret(ctx, + r.Client, + ns, + "lagoon-internal-registry-secret", + robotCreds) + if err != nil { + return fmt.Errorf("Error upserting harbor robot account secret: %v", err) } } return nil diff --git a/controllers/v1beta1/harborcredential_controller.go b/controllers/v1beta1/harborcredential_controller.go new file mode 100644 index 00000000..7ca07f92 --- /dev/null +++ b/controllers/v1beta1/harborcredential_controller.go @@ -0,0 +1,83 @@ +package v1beta1 + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/go-logr/logr" + "github.com/uselagoon/remote-controller/internal/harbor" + "github.com/uselagoon/remote-controller/internal/helpers" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + corev1 "k8s.io/api/core/v1" +) + +// HarborCredentialReconciler reconciles a namespace object +type HarborCredentialReconciler struct { + client.Client + Log logr.Logger + Scheme *runtime.Scheme + LFFHarborEnabled bool + Harbor harbor.Harbor + ControllerNamespace string +} + +// all the things +// +kubebuilder:rbac:groups=*,resources=*,verbs=* + +func (r *HarborCredentialReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + opLog := r.Log.WithValues("harbor", req.NamespacedName) + + var harborSecret corev1.Secret + if err := r.Get(ctx, req.NamespacedName, &harborSecret); err != nil { + return ctrl.Result{}, helpers.IgnoreNotFound(err) + } + + // check if the credentials need to be force rotated + value, ok := harborSecret.ObjectMeta.Labels["harbor.lagoon.sh/force-rotate"] + if ok && value == "true" { + opLog.Info(fmt.Sprintf("Rotating harbor credentials for namespace %s", harborSecret.ObjectMeta.Namespace)) + lagoonHarbor, err := harbor.New(r.Harbor) + if err != nil { + return ctrl.Result{}, fmt.Errorf("Error creating harbor client, check your harbor configuration. Error was: %v", err) + } + var ns corev1.Namespace + if err := r.Get(ctx, types.NamespacedName{Name: harborSecret.ObjectMeta.Namespace}, &ns); err != nil { + return ctrl.Result{}, helpers.IgnoreNotFound(err) + } + rotated, err := lagoonHarbor.RotateRobotCredential(ctx, r.Client, ns, true) + if err != nil { + // @TODO: resource unknown + return ctrl.Result{}, fmt.Errorf("Error was: %v", err) + } + if rotated { + opLog.Info(fmt.Sprintf("Robot credentials rotated for %s", ns.ObjectMeta.Name)) + } + mergePatch, _ := json.Marshal(map[string]interface{}{ + "metadata": map[string]interface{}{ + "labels": map[string]interface{}{ + "harbor.lagoon.sh/force-rotate": nil, + }, + }, + }) + if err := r.Patch(ctx, &harborSecret, client.RawPatch(types.MergePatchType, mergePatch)); err != nil { + return ctrl.Result{}, fmt.Errorf("There was an error patching the harbor secret. Error was: %v", err) + } + } + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the watch on the namespace resource with an event filter (see controller_predicates.go) +func (r *HarborCredentialReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&corev1.Secret{}). + WithEventFilter(SecretPredicates{ + ControllerNamespace: r.ControllerNamespace, + }). + Complete(r) +} diff --git a/controllers/v1beta1/predicates.go b/controllers/v1beta1/predicates.go index afb99a03..e46b6d26 100644 --- a/controllers/v1beta1/predicates.go +++ b/controllers/v1beta1/predicates.go @@ -225,3 +225,49 @@ func (t TaskPredicates) Generic(e event.GenericEvent) bool { } return false } + +// SecretPredicates defines the funcs for predicates +type SecretPredicates struct { + predicate.Funcs + ControllerNamespace string +} + +// Create is used when a creation event is received by the controller. +func (n SecretPredicates) Create(e event.CreateEvent) bool { + if controller, ok := e.Object.GetLabels()["lagoon.sh/controller"]; ok { + if controller == n.ControllerNamespace { + return true + } + } + return false +} + +// Delete is used when a deletion event is received by the controller. +func (n SecretPredicates) Delete(e event.DeleteEvent) bool { + if controller, ok := e.Object.GetLabels()["lagoon.sh/controller"]; ok { + if controller == n.ControllerNamespace { + return true + } + } + return false +} + +// Update is used when an update event is received by the controller. +func (n SecretPredicates) Update(e event.UpdateEvent) bool { + if controller, ok := e.ObjectOld.GetLabels()["lagoon.sh/controller"]; ok { + if controller == n.ControllerNamespace { + return true + } + } + return false +} + +// Generic is used when any other event is received by the controller. +func (n SecretPredicates) Generic(e event.GenericEvent) bool { + if controller, ok := e.Object.GetLabels()["lagoon.sh/controller"]; ok { + if controller == n.ControllerNamespace { + return true + } + } + return false +} diff --git a/internal/harbor/harbor21x.go b/internal/harbor/harbor21x.go index c6c6d864..d80063a5 100644 --- a/internal/harbor/harbor21x.go +++ b/internal/harbor/harbor21x.go @@ -125,6 +125,7 @@ func (h *Harbor) CreateOrRefreshRobot(ctx context.Context, project *harborclientv3model.Project, environmentName, namespace string, expiry int64, + force bool, ) (*helpers.RegistryCredentials, error) { // create a cluster specific robot account name @@ -169,7 +170,7 @@ func (h *Harbor) CreateOrRefreshRobot(ctx context.Context, for _, robot := range robots { if h.matchRobotAccount(robot.Name, project.Name, environmentName) { exists = true - if forceRecreate { + if forceRecreate || force { // if the secret doesn't exist in kubernetes, then force re-creation of the robot // account is required, as there isn't a way to get the credentials after // robot accounts are created @@ -237,32 +238,37 @@ func (h *Harbor) CreateOrRefreshRobot(ctx context.Context, if !exists || deleted { // if it doesn't exist, or was deleted // create a new robot account - token, err := h.ClientV3.AddProjectRobot( - ctx, - project, - &harborclientv3legacy.RobotAccountCreate{ - Name: robotName, - Description: fmt.Sprintf("Robot account created in %s", h.LagoonTargetName), - ExpiresAt: expiry, - Access: []*harborclientv3legacy.RobotAccountAccess{ - {Action: "push", Resource: fmt.Sprintf("/project/%d/repository", project.ProjectID)}, - {Action: "pull", Resource: fmt.Sprintf("/project/%d/repository", project.ProjectID)}, - }, - }, - ) - if err != nil { - h.Log.Info(fmt.Sprintf("Error adding project %s robot account %s", project.Name, robotName)) - return nil, err - } - // then craft and return the harbor credential secret - harborRegistryCredentials := makeHarborSecret( - robotAccountCredential{ - Token: token, - Name: h.addPrefix(robotName), - }, - ) h.Log.Info(fmt.Sprintf("Created robot account %s", h.addPrefix(robotName))) - return &harborRegistryCredentials, nil + return h.CreateRobotAccount(ctx, robotName, project, expiry) } return nil, err } + +func (h *Harbor) CreateRobotAccount(ctx context.Context, robotName string, project *harborclientv3model.Project, expiryDays int64) (*helpers.RegistryCredentials, error) { + token, err := h.ClientV3.AddProjectRobot( + ctx, + project, + &harborclientv3legacy.RobotAccountCreate{ + Name: robotName, + Description: fmt.Sprintf("Robot account created in %s", h.LagoonTargetName), + ExpiresAt: expiryDays, + Access: []*harborclientv3legacy.RobotAccountAccess{ + {Action: "push", Resource: fmt.Sprintf("/project/%d/repository", project.ProjectID)}, + {Action: "pull", Resource: fmt.Sprintf("/project/%d/repository", project.ProjectID)}, + }, + }, + ) + if err != nil { + h.Log.Info(fmt.Sprintf("Error adding project %s robot account %s", project.Name, robotName)) + return nil, err + } + // then craft and return the harbor credential secret + harborRegistryCredentials := makeHarborSecret( + robotAccountCredential{ + Token: token, + Name: h.addPrefix(robotName), + }, + ) + h.Log.Info(fmt.Sprintf("Created robot account %s", h.addPrefix(robotName))) + return &harborRegistryCredentials, nil +} diff --git a/internal/harbor/harbor22x.go b/internal/harbor/harbor22x.go index 4eaa869b..8eefe38a 100644 --- a/internal/harbor/harbor22x.go +++ b/internal/harbor/harbor22x.go @@ -129,6 +129,7 @@ func (h *Harbor) CreateOrRefreshRobotV2(ctx context.Context, project *harborclientv5model.Project, environmentName, namespace string, expiry time.Duration, + force bool, ) (*helpers.RegistryCredentials, error) { // create a cluster specific robot account name @@ -197,7 +198,7 @@ func (h *Harbor) CreateOrRefreshRobotV2(ctx context.Context, if h.matchRobotAccountV2(robot.Name, project.Name, environmentName) && robot.Editable { // if it is a new robot account, follow through here exists = true - if forceRecreate { + if forceRecreate || force { // if the secret doesn't exist in kubernetes, then force re-creation of the robot // account is required, as there isn't a way to get the credentials after // robot accounts are created @@ -265,43 +266,7 @@ func (h *Harbor) CreateOrRefreshRobotV2(ctx context.Context, if !exists || deleted { // if it doesn't exist, or was deleted // create a new robot account - robotf := harborclientv5model.RobotCreate{ - Level: "project", - Name: robotName, - Duration: expiryDays, - Permissions: []*harborclientv5model.RobotPermission{ - { - Kind: "project", - Namespace: project.Name, - Access: []*harborclientv5model.Access{ - { - Action: "push", - Resource: "repository", - }, - { - Action: "pull", - Resource: "repository", - }, - }, - }, - }, - Disable: false, - Description: fmt.Sprintf("Robot account created in %s", h.LagoonTargetName), - } - token, err := h.ClientV5.NewRobotAccount(ctx, &robotf) - if err != nil { - h.Log.Info(fmt.Sprintf("Error adding project %s robot account %s", project.Name, h.addPrefixV2(project.Name, environmentName))) - return nil, err - } - // then craft and return the harbor credential secret - harborRegistryCredentials := makeHarborSecret( - robotAccountCredential{ - Token: token.Secret, - Name: token.Name, - }, - ) - h.Log.Info(fmt.Sprintf("Created robot account %s", token.Name)) - return &harborRegistryCredentials, nil + return h.CreateRobotAccountV2(ctx, robotName, environmentName, project.Name, expiryDays) } return nil, err } @@ -348,3 +313,43 @@ func (h *Harbor) ListRepositories(ctx context.Context, projectName string, pageN } return listRepositories } + +func (h *Harbor) CreateRobotAccountV2(ctx context.Context, robotName, environmentName, projectName string, expiryDays int64) (*helpers.RegistryCredentials, error) { + robotf := harborclientv5model.RobotCreate{ + Level: "project", + Name: robotName, + Duration: expiryDays, + Permissions: []*harborclientv5model.RobotPermission{ + { + Kind: "project", + Namespace: projectName, + Access: []*harborclientv5model.Access{ + { + Action: "push", + Resource: "repository", + }, + { + Action: "pull", + Resource: "repository", + }, + }, + }, + }, + Disable: false, + Description: fmt.Sprintf("Robot account created in %s", h.LagoonTargetName), + } + token, err := h.ClientV5.NewRobotAccount(ctx, &robotf) + if err != nil { + h.Log.Info(fmt.Sprintf("Error adding project %s robot account %s", projectName, h.addPrefixV2(projectName, environmentName))) + return nil, err + } + // then craft and return the harbor credential secret + harborRegistryCredentials := makeHarborSecret( + robotAccountCredential{ + Token: token.Secret, + Name: token.Name, + }, + ) + h.Log.Info(fmt.Sprintf("Created robot account %s", token.Name)) + return &harborRegistryCredentials, nil +} diff --git a/internal/harbor/harbor_credentialrotation.go b/internal/harbor/harbor_credentialrotation.go index 18e8cc05..5256e316 100644 --- a/internal/harbor/harbor_credentialrotation.go +++ b/internal/harbor/harbor_credentialrotation.go @@ -71,63 +71,12 @@ func (h *Harbor) RotateRobotCredentials(ctx context.Context, cl client.Client) { } } if !runningBuilds { - // only continue if there isn't any running builds - robotCreds := &helpers.RegistryCredentials{} - curVer, err := h.GetHarborVersion(ctx) + rotated, err := h.RotateRobotCredential(ctx, cl, ns, false) if err != nil { - // @TODO: resource unknown - opLog.Error(err, "error checking harbor version") + opLog.Error(err, "error") continue } - if h.UseV2Functions(curVer) { - hProject, err := h.CreateProjectV2(ctx, ns.Labels["lagoon.sh/project"]) - if err != nil { - // @TODO: resource unknown - opLog.Error(err, "error getting or creating project") - break - } - time.Sleep(1 * time.Second) // wait 1 seconds - robotCreds, err = h.CreateOrRefreshRobotV2(ctx, - cl, - hProject, - ns.Labels["lagoon.sh/environment"], - ns.ObjectMeta.Name, - h.RobotAccountExpiry) - if err != nil { - opLog.Error(err, "error getting or creating robot account") - continue - } - } else { - hProject, err := h.CreateProject(ctx, ns.Labels["lagoon.sh/project"]) - if err != nil { - // @TODO: resource unknown - opLog.Error(err, "error getting or creating project") - continue - } - time.Sleep(1 * time.Second) // wait 1 seconds - robotCreds, err = h.CreateOrRefreshRobot(ctx, - cl, - hProject, - ns.Labels["lagoon.sh/environment"], - ns.ObjectMeta.Name, - time.Now().Add(h.RobotAccountExpiry).Unix()) - if err != nil { - opLog.Error(err, "error getting or creating robot account") - continue - } - } - time.Sleep(1 * time.Second) // wait 1 seconds - if robotCreds != nil { - // if we have robotcredentials to create, do that here - if err := UpsertHarborSecret(ctx, - cl, - ns.ObjectMeta.Name, - "lagoon-internal-registry-secret", //secret name in kubernetes - h.Hostname, - robotCreds); err != nil { - opLog.Error(err, "error creating or updating robot account credentials") - continue - } + if rotated { opLog.Info(fmt.Sprintf("Robot credentials rotated for %s", ns.ObjectMeta.Name)) } } else { @@ -135,3 +84,54 @@ func (h *Harbor) RotateRobotCredentials(ctx context.Context, cl client.Client) { } } } + +// rotate a specific namespaces robot credential +func (h *Harbor) RotateRobotCredential(ctx context.Context, cl client.Client, ns corev1.Namespace, force bool) (bool, error) { + // only continue if there isn't any running builds + robotCreds := &helpers.RegistryCredentials{} + curVer, err := h.GetHarborVersion(ctx) + if err != nil { + return false, fmt.Errorf("error checking harbor version: %v", err) + } + if h.UseV2Functions(curVer) { + hProject, err := h.CreateProjectV2(ctx, ns.Labels["lagoon.sh/project"]) + if err != nil { + return false, fmt.Errorf("error getting or creating project: %v", err) + } + time.Sleep(1 * time.Second) // wait 1 seconds + robotCreds, err = h.CreateOrRefreshRobotV2(ctx, + cl, + hProject, + ns.Labels["lagoon.sh/environment"], + ns.ObjectMeta.Name, + h.RobotAccountExpiry, + force) + if err != nil { + return false, fmt.Errorf("error getting or creating robot account: %v", err) + } + } else { + hProject, err := h.CreateProject(ctx, ns.Labels["lagoon.sh/project"]) + if err != nil { + return false, fmt.Errorf("error getting or creating project: %v", err) + } + time.Sleep(1 * time.Second) // wait 1 seconds + robotCreds, err = h.CreateOrRefreshRobot(ctx, + cl, + hProject, + ns.Labels["lagoon.sh/environment"], + ns.ObjectMeta.Name, + time.Now().Add(h.RobotAccountExpiry).Unix(), + force) + if err != nil { + return false, fmt.Errorf("error getting or creating robot account: %v", err) + } + } + time.Sleep(1 * time.Second) // wait 1 seconds + + // if we have robotcredentials to create, do that here + return h.UpsertHarborSecret(ctx, + cl, + ns.ObjectMeta.Name, + "lagoon-internal-registry-secret", //secret name in kubernetes + robotCreds) +} diff --git a/internal/harbor/harbor_helpers.go b/internal/harbor/harbor_helpers.go index 3d054f07..2292786f 100644 --- a/internal/harbor/harbor_helpers.go +++ b/internal/harbor/harbor_helpers.go @@ -104,7 +104,7 @@ func makeHarborSecret(credentials robotAccountCredential) helpers.RegistryCreden } // UpsertHarborSecret will create or update the secret in kubernetes. -func UpsertHarborSecret(ctx context.Context, cl client.Client, ns, name, baseURL string, registryCreds *helpers.RegistryCredentials) error { +func (h *Harbor) UpsertHarborSecret(ctx context.Context, cl client.Client, ns, name string, registryCreds *helpers.RegistryCredentials) (bool, error) { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Namespace: ns, @@ -120,31 +120,62 @@ func UpsertHarborSecret(ctx context.Context, cl client.Client, ns, name, baseURL Name: name, }, secret) if err != nil { - // if the secret doesn't exist - // create it - dcj.Registries[baseURL] = *registryCreds + // if registryCreds are provided, and the secret doesn't exist + // then create the secret + if registryCreds != nil { + dcj.Registries[h.Hostname] = *registryCreds + dcjBytes, _ := json.Marshal(dcj) + secret.Data = map[string][]byte{ + corev1.DockerConfigJsonKey: []byte(dcjBytes), + } + secret.ObjectMeta.Labels = map[string]string{ + "lagoon.sh/controller": h.ControllerNamespace, + } + err := cl.Create(ctx, secret) + if err != nil { + return false, fmt.Errorf("could not create secret %s/%s: %s", secret.ObjectMeta.Namespace, secret.ObjectMeta.Name, err.Error()) + } + // return true that the credential was created + return true, nil + } + return false, nil + } + // if registryCreds are provided, and the secret exists, then update the secret + // with the provided credentials + if registryCreds != nil { + json.Unmarshal([]byte(secret.Data[corev1.DockerConfigJsonKey]), &dcj) + // add or update the credential + dcj.Registries[h.Hostname] = *registryCreds dcjBytes, _ := json.Marshal(dcj) secret.Data = map[string][]byte{ corev1.DockerConfigJsonKey: []byte(dcjBytes), } - err := cl.Create(ctx, secret) + // add the controller label if it doesn't exist + if _, ok := secret.ObjectMeta.Labels["lagoon.sh/controller"]; !ok { + if secret.ObjectMeta.Labels == nil { + secret.ObjectMeta.Labels = map[string]string{} + } + secret.ObjectMeta.Labels["lagoon.sh/controller"] = h.ControllerNamespace + } + err = cl.Update(ctx, secret) if err != nil { - return fmt.Errorf("could not create secret %s/%s: %s", secret.ObjectMeta.Namespace, secret.ObjectMeta.Name, err.Error()) + return false, fmt.Errorf("could not update secret: %s/%s", secret.ObjectMeta.Namespace, secret.ObjectMeta.Name) + } + return true, nil + } else { + // if the secret doesn't have the controller label, patch it it + if _, ok := secret.ObjectMeta.Labels["lagoon.sh/controller"]; !ok { + mergePatch, _ := json.Marshal(map[string]interface{}{ + "metadata": map[string]interface{}{ + "labels": map[string]interface{}{ + "lagoon.sh/controller": h.ControllerNamespace, + }, + }, + }) + if err := cl.Patch(ctx, secret, client.RawPatch(types.MergePatchType, mergePatch)); err != nil { + return false, fmt.Errorf("could not update secret: %s/%s", secret.ObjectMeta.Namespace, secret.ObjectMeta.Name) + } } - return nil - } - // if the secret exists - // update the secret with the new credentials - json.Unmarshal([]byte(secret.Data[corev1.DockerConfigJsonKey]), &dcj) - // add or update the credential - dcj.Registries[baseURL] = *registryCreds - dcjBytes, _ := json.Marshal(dcj) - secret.Data = map[string][]byte{ - corev1.DockerConfigJsonKey: []byte(dcjBytes), - } - err = cl.Update(ctx, secret) - if err != nil { - return fmt.Errorf("could not update secret: %s/%s", secret.ObjectMeta.Namespace, secret.ObjectMeta.Name) } - return nil + return false, nil } diff --git a/main.go b/main.go index 70526e5f..5f0ec69f 100644 --- a/main.go +++ b/main.go @@ -827,6 +827,21 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "LagoonTask") os.Exit(1) } + + // for now the namespace reconciler only needs to run if harbor is enabled so that we can watch the namespace for rotation label events + if lffHarborEnabled { + if err = (&lagoonv1beta1ctrl.HarborCredentialReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("v1beta1").WithName("HarborCredentialReconciler"), + Scheme: mgr.GetScheme(), + LFFHarborEnabled: lffHarborEnabled, + ControllerNamespace: controllerNamespace, + Harbor: harborConfig, + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "HarborCredentialReconciler") + os.Exit(1) + } + } // +kubebuilder:scaffold:builder setupLog.Info("starting lagoon metrics server") From f9b240a0514a7c0fc9ab97f97083edb4c544c939 Mon Sep 17 00:00:00 2001 From: shreddedbacon Date: Wed, 3 May 2023 19:06:25 +1000 Subject: [PATCH 2/3] chore: add harbor label --- controllers/v1beta1/predicates.go | 24 ++++++++++++++++++++---- internal/harbor/harbor_helpers.go | 7 +++++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/controllers/v1beta1/predicates.go b/controllers/v1beta1/predicates.go index e46b6d26..589dfb2e 100644 --- a/controllers/v1beta1/predicates.go +++ b/controllers/v1beta1/predicates.go @@ -236,7 +236,11 @@ type SecretPredicates struct { func (n SecretPredicates) Create(e event.CreateEvent) bool { if controller, ok := e.Object.GetLabels()["lagoon.sh/controller"]; ok { if controller == n.ControllerNamespace { - return true + if val, ok := e.Object.GetLabels()["lagoon.sh/harbor-credential"]; ok { + if val == "true" { + return true + } + } } } return false @@ -246,7 +250,11 @@ func (n SecretPredicates) Create(e event.CreateEvent) bool { func (n SecretPredicates) Delete(e event.DeleteEvent) bool { if controller, ok := e.Object.GetLabels()["lagoon.sh/controller"]; ok { if controller == n.ControllerNamespace { - return true + if val, ok := e.Object.GetLabels()["lagoon.sh/harbor-credential"]; ok { + if val == "true" { + return true + } + } } } return false @@ -256,7 +264,11 @@ func (n SecretPredicates) Delete(e event.DeleteEvent) bool { func (n SecretPredicates) Update(e event.UpdateEvent) bool { if controller, ok := e.ObjectOld.GetLabels()["lagoon.sh/controller"]; ok { if controller == n.ControllerNamespace { - return true + if val, ok := e.ObjectOld.GetLabels()["lagoon.sh/harbor-credential"]; ok { + if val == "true" { + return true + } + } } } return false @@ -266,7 +278,11 @@ func (n SecretPredicates) Update(e event.UpdateEvent) bool { func (n SecretPredicates) Generic(e event.GenericEvent) bool { if controller, ok := e.Object.GetLabels()["lagoon.sh/controller"]; ok { if controller == n.ControllerNamespace { - return true + if val, ok := e.Object.GetLabels()["lagoon.sh/harbor-credential"]; ok { + if val == "true" { + return true + } + } } } return false diff --git a/internal/harbor/harbor_helpers.go b/internal/harbor/harbor_helpers.go index 2292786f..01f21f55 100644 --- a/internal/harbor/harbor_helpers.go +++ b/internal/harbor/harbor_helpers.go @@ -129,7 +129,8 @@ func (h *Harbor) UpsertHarborSecret(ctx context.Context, cl client.Client, ns, n corev1.DockerConfigJsonKey: []byte(dcjBytes), } secret.ObjectMeta.Labels = map[string]string{ - "lagoon.sh/controller": h.ControllerNamespace, + "lagoon.sh/controller": h.ControllerNamespace, + "lagoon.sh/harbor-credential": "true", } err := cl.Create(ctx, secret) if err != nil { @@ -156,6 +157,7 @@ func (h *Harbor) UpsertHarborSecret(ctx context.Context, cl client.Client, ns, n secret.ObjectMeta.Labels = map[string]string{} } secret.ObjectMeta.Labels["lagoon.sh/controller"] = h.ControllerNamespace + secret.ObjectMeta.Labels["lagoon.sh/harbor-credential"] = "true" } err = cl.Update(ctx, secret) if err != nil { @@ -168,7 +170,8 @@ func (h *Harbor) UpsertHarborSecret(ctx context.Context, cl client.Client, ns, n mergePatch, _ := json.Marshal(map[string]interface{}{ "metadata": map[string]interface{}{ "labels": map[string]interface{}{ - "lagoon.sh/controller": h.ControllerNamespace, + "lagoon.sh/controller": h.ControllerNamespace, + "lagoon.sh/harbor-credential": "true", }, }, }) From 55cae15ca6f833094b9c74aaf916767e890e1b4c Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 8 May 2023 10:03:13 +1000 Subject: [PATCH 3/3] chore: don't need to work on deleted secrets --- controllers/v1beta1/predicates.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/controllers/v1beta1/predicates.go b/controllers/v1beta1/predicates.go index 589dfb2e..77aa324a 100644 --- a/controllers/v1beta1/predicates.go +++ b/controllers/v1beta1/predicates.go @@ -248,15 +248,6 @@ func (n SecretPredicates) Create(e event.CreateEvent) bool { // Delete is used when a deletion event is received by the controller. func (n SecretPredicates) Delete(e event.DeleteEvent) bool { - if controller, ok := e.Object.GetLabels()["lagoon.sh/controller"]; ok { - if controller == n.ControllerNamespace { - if val, ok := e.Object.GetLabels()["lagoon.sh/harbor-credential"]; ok { - if val == "true" { - return true - } - } - } - } return false }