Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ When an `ArgocdUser` is deleted, the operator automatically cleans up:
|----------|-------------|
| `PUBLIC_REPOS` | Comma-separated list of public repositories available to all projects |
| `CLUSTER_ADMIN_TEAMS` | Comma-separated list of teams with cluster-admin privileges |
| `USER_ARGOCD_NAMESPACE` | Namespace holding the managed AppProjects and the argocd static-user ConfigMap/Secret. Also scopes the manager's Secret/ConfigMap informer caches. Defaults to `user-argocd`. |

## Instructions

Expand Down
4 changes: 2 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ func main() {
Cache: cache.Options{
ByObject: map[client.Object]cache.ByObject{
&corev1.Secret{}: {
Namespaces: map[string]cache.Config{"user-argocd": {}},
Namespaces: map[string]cache.Config{controller.UserArgocdNS: {}},
},
&corev1.ConfigMap{}: {
Namespaces: map[string]cache.Config{"user-argocd": {}},
Namespaces: map[string]cache.Config{controller.UserArgocdNS: {}},
},
},
},
Expand Down
5 changes: 5 additions & 0 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ spec:
env:
- name: GODEBUG
value: multipathtcp=0
# Namespace holding the managed AppProjects and argocd static-user
# ConfigMap/Secret (also scopes the Secret/ConfigMap caches).
# Defaults to user-argocd if unset; set here to make it explicit.
- name: USER_ARGOCD_NAMESPACE
value: user-argocd
envFrom:
- configMapRef:
name: public-repos
Expand Down
18 changes: 9 additions & 9 deletions internal/controller/argocduser_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ func (r *ArgocdUserReconciler) reconcileAppProject(ctx context.Context, argocdus

// Check if AppProject does not exist and create a new one
found := &argov1alpha1.AppProject{}
err := r.Get(ctx, types.NamespacedName{Name: appProjectName, Namespace: userArgocdNS}, found)
err := r.Get(ctx, types.NamespacedName{Name: appProjectName, Namespace: UserArgocdNS}, found)
if err != nil {
if errors.IsNotFound(err) {
logger.Info("Creating the AppProject", "AppProject", appProjectName)
Expand Down Expand Up @@ -434,7 +434,7 @@ func (r *ArgocdUserReconciler) UpdateUserArgocdConfig(ctx context.Context, argoc
accountKey := "accounts." + argocduser.Name + "-" + roleName + "-ci"
expectedValue := "apiKey,login"
configMap := &corev1.ConfigMap{}
err := r.Get(ctx, types.NamespacedName{Name: userArgocdStaticUserCM, Namespace: userArgocdNS}, configMap)
err := r.Get(ctx, types.NamespacedName{Name: userArgocdStaticUserCM, Namespace: UserArgocdNS}, configMap)
if err != nil {
if errors.IsNotFound(err) {
logger.Error(err, "Argocd ConfigMap not found", "ConfigMap", userArgocdStaticUserCM)
Expand Down Expand Up @@ -480,7 +480,7 @@ func (r *ArgocdUserReconciler) UpdateUserArgocdConfig(ctx context.Context, argoc
}

secret := &corev1.Secret{}
if err = r.Get(ctx, types.NamespacedName{Name: userArgocdSecret, Namespace: userArgocdNS}, secret); err != nil {
if err = r.Get(ctx, types.NamespacedName{Name: userArgocdSecret, Namespace: UserArgocdNS}, secret); err != nil {
if errors.IsNotFound(err) {
logger.Error(err, "Argocd Secret not found", "Secret", userArgocdSecret)
return err
Expand Down Expand Up @@ -584,7 +584,7 @@ func (r *ArgocdUserReconciler) cleanupResources(ctx context.Context, argocduser
func (r *ArgocdUserReconciler) deleteAppProject(ctx context.Context, name string) error {
logger := log.FromContext(ctx)
appProj := &argov1alpha1.AppProject{}
err := r.Get(ctx, types.NamespacedName{Name: name, Namespace: userArgocdNS}, appProj)
err := r.Get(ctx, types.NamespacedName{Name: name, Namespace: UserArgocdNS}, appProj)
if err != nil {
if errors.IsNotFound(err) {
// AppProj doesn't exist, nothing to clean up
Expand Down Expand Up @@ -613,7 +613,7 @@ func (r *ArgocdUserReconciler) deleteAppProject(ctx context.Context, name string
func (r *ArgocdUserReconciler) removeConfigMapEntries(ctx context.Context, name string) error {
logger := log.FromContext(ctx)
configMap := &corev1.ConfigMap{}
err := r.Get(ctx, types.NamespacedName{Name: userArgocdStaticUserCM, Namespace: userArgocdNS}, configMap)
err := r.Get(ctx, types.NamespacedName{Name: userArgocdStaticUserCM, Namespace: UserArgocdNS}, configMap)
if err != nil {
if errors.IsNotFound(err) {
// ConfigMap doesn't exist, nothing to clean up
Expand All @@ -639,7 +639,7 @@ func (r *ArgocdUserReconciler) removeConfigMapEntries(ctx context.Context, name
func (r *ArgocdUserReconciler) removeSecretEntries(ctx context.Context, name string) error {
logger := log.FromContext(ctx)
secret := &corev1.Secret{}
err := r.Get(ctx, types.NamespacedName{Name: userArgocdSecret, Namespace: userArgocdNS}, secret)
err := r.Get(ctx, types.NamespacedName{Name: userArgocdSecret, Namespace: UserArgocdNS}, secret)
if err != nil {
if errors.IsNotFound(err) {
return nil
Expand Down Expand Up @@ -671,7 +671,7 @@ func (r *ArgocdUserReconciler) SetupWithManager(mgr ctrl.Manager) error {
Watches(
&corev1.ConfigMap{},
handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, obj client.Object) []reconcile.Request {
if obj.GetNamespace() != userArgocdNS || obj.GetName() != userArgocdStaticUserCM {
if obj.GetNamespace() != UserArgocdNS || obj.GetName() != userArgocdStaticUserCM {
return nil
}
argocdUserList := &argocduserv1alpha1.ArgocdUserList{}
Expand All @@ -692,7 +692,7 @@ func (r *ArgocdUserReconciler) SetupWithManager(mgr ctrl.Manager) error {
Watches(
&corev1.Secret{},
handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, obj client.Object) []reconcile.Request {
if obj.GetNamespace() != userArgocdNS || obj.GetName() != userArgocdSecret {
if obj.GetNamespace() != UserArgocdNS || obj.GetName() != userArgocdSecret {
return nil
}
argocdUserList := &argocduserv1alpha1.ArgocdUserList{}
Expand All @@ -717,7 +717,7 @@ func (r *ArgocdUserReconciler) SetupWithManager(mgr ctrl.Manager) error {
appProjName := obj.GetName()

// Only watch AppProjects in the user-argocd namespace
if obj.GetNamespace() != userArgocdNS {
if obj.GetNamespace() != UserArgocdNS {
return nil
}

Expand Down
20 changes: 18 additions & 2 deletions internal/controller/common_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ func mustUnsetenv(t *testing.T, key string) {
}
}

func TestUserArgocdNamespace(t *testing.T) {
t.Run("defaults when unset", func(t *testing.T) {
t.Setenv("USER_ARGOCD_NAMESPACE", "")
if got := userArgocdNamespace(); got != defaultUserArgocdNS {
t.Errorf("expected default %q, got %q", defaultUserArgocdNS, got)
}
})

t.Run("honors env override", func(t *testing.T) {
t.Setenv("USER_ARGOCD_NAMESPACE", "custom-argocd")
if got := userArgocdNamespace(); got != "custom-argocd" {
t.Errorf("expected %q, got %q", "custom-argocd", got)
}
})
}

func setupAppProjTest(t *testing.T) func() *SafeNsCache {
t.Helper()
origCache := NamespaceCache
Expand Down Expand Up @@ -248,8 +264,8 @@ func TestCreateAppProjStructure(t *testing.T) {
if proj.Name != "my-team" {
t.Errorf("expected name 'my-team', got %q", proj.Name)
}
if proj.Namespace != userArgocdNS {
t.Errorf("expected namespace %q, got %q", userArgocdNS, proj.Namespace)
if proj.Namespace != UserArgocdNS {
t.Errorf("expected namespace %q, got %q", UserArgocdNS, proj.Namespace)
}
if len(proj.Spec.Roles) != 3 {
t.Fatalf("expected 3 roles, got %d", len(proj.Spec.Roles))
Expand Down
19 changes: 17 additions & 2 deletions internal/controller/controller_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
)

const (
userArgocdNS = "user-argocd"
defaultUserArgocdNS = "user-argocd"
userArgocdStaticUserCM = "argocd-cm"
userArgocdSecret = "argocd-secret"
argocdUserFinalizer = "argocd.snappcloud.io/finalizer"
Expand All @@ -33,6 +33,21 @@ const (
SourceLabel = "argocd.snappcloud.io/source"
)

// UserArgocdNS is the namespace holding the AppProjects and the argocd
// static-user ConfigMap/Secret this operator manages. Configurable via the
// USER_ARGOCD_NAMESPACE env var; defaults to "user-argocd". It is also used to
// scope the manager's Secret/ConfigMap informer caches (see cmd/main.go).
var UserArgocdNS = userArgocdNamespace()

// userArgocdNamespace resolves the managed namespace from USER_ARGOCD_NAMESPACE,
// falling back to defaultUserArgocdNS when the env var is empty or unset.
func userArgocdNamespace() string {
if ns := os.Getenv("USER_ARGOCD_NAMESPACE"); ns != "" {
return ns
}
return defaultUserArgocdNS
}

var NamespaceCache = &SafeNsCache{
lock: sync.RWMutex{},
projects: nil,
Expand Down Expand Up @@ -113,7 +128,7 @@ func createAppProj(team string) *argov1alpha1.AppProject {
appProj := &argov1alpha1.AppProject{
ObjectMeta: metav1.ObjectMeta{
Name: team,
Namespace: userArgocdNS,
Namespace: UserArgocdNS,
},
Spec: argov1alpha1.AppProjectSpec{
SourceRepos: repo_list,
Expand Down
4 changes: 2 additions & 2 deletions internal/controller/namespace_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ func (c *SafeNsCache) InitOrPass(r *NamespaceReconciler, ctx context.Context) er
c.sources = make(map[string]nameset.Nameset[string])

if err := r.List(ctx, appProjList,
&client.ListOptions{Namespace: userArgocdNS},
&client.ListOptions{Namespace: UserArgocdNS},
); err != nil {
c.initErr = err
return
Expand Down Expand Up @@ -339,7 +339,7 @@ func (r *NamespaceReconciler) reconcileAppProject(ctx context.Context, logger lo

// Check if AppProject does not exist and create a new one
found := &argov1alpha1.AppProject{}
if err := r.Get(ctx, types.NamespacedName{Name: team, Namespace: userArgocdNS}, found); err != nil {
if err := r.Get(ctx, types.NamespacedName{Name: team, Namespace: UserArgocdNS}, found); err != nil {
if errors.IsNotFound(err) {
logger.Info("AppProject not found, skipping update (will be created by ArgocdUser)", "AppProject", team)
return nil
Expand Down