Skip to content

Commit

Permalink
* add environment alias for migrating legacy clusters
Browse files Browse the repository at this point in the history
* add new parameter for feature - clusteralias
* add config parameter
* add handling of environments in reconciler for gcp
* add environment alias to reconciler test

Co-authored-by: Roger Bjørnstad <[email protected]>
Co-authored-by: Vegar Sechmann Molvig <[email protected]>
  • Loading branch information
3 people committed Nov 26, 2024
1 parent c5e2e48 commit bf88de5
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 15 deletions.
5 changes: 5 additions & 0 deletions charts/Feature.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ values:
template: |
{{ .Env.tenant_domain | quote }}
clusterAlias:
displayName: Cluster aliases
config:
type: string_array

reconcilersToEnable:
displayName: Reconcilers to enable
description: Comma separated list of reconcilers to enable. Changing this value after the reconciler has been registered will not have any effect.
Expand Down
1 change: 1 addition & 0 deletions charts/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ logLevel: info
logFormat: json
googleManagementProjectID: # mapped in fasit
tenantDomain: # mapped in fasit
clusterAlias: []
reconcilersToEnable: "google:gcp:project,google:workspace-admin,nais:namespace,nais:deploy,google:gcp:gar,google:gcp:cdn,grafana"
fasit:
tenant:
Expand Down
3 changes: 3 additions & 0 deletions internal/cmd/reconciler/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ type Config struct {
// TenantName The name of the tenant.
TenantName string `env:"TENANT_NAME,default=example"`

// ClusterAlias The cluster alias for legacy migration
ClusterAlias map[string]string `env:"CLUSTER_ALIAS"`

// Reconcilers to enable the first time it is registered (one time only) in the NAIS API
// If you later would like do enable/disable a reconciler, you can do so through the Console
ReconcilersToEnable []string `env:"RECONCILERS_TO_ENABLE"`
Expand Down
2 changes: 1 addition & 1 deletion internal/cmd/reconciler/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func run(ctx context.Context, cfg *config.Config, log logrus.FieldLogger) error
}
log.WithField("duration", time.Since(start).String()).Debug("Created NAIS deploy reconciler")

googleGcpReconciler, err := google_gcp_reconciler.New(ctx, cfg.GCP.Clusters, cfg.GCP.ServiceAccountEmail, cfg.TenantDomain, cfg.TenantName, cfg.GCP.CnrmRole, cfg.GCP.BillingAccount, cfg.FeatureFlags)
googleGcpReconciler, err := google_gcp_reconciler.New(ctx, cfg.GCP.Clusters, cfg.GCP.ServiceAccountEmail, cfg.TenantDomain, cfg.TenantName, cfg.GCP.CnrmRole, cfg.GCP.BillingAccount, cfg.ClusterAlias, cfg.FeatureFlags)
if err != nil {
return fmt.Errorf("error when creating Google GCP reconciler: %w", err)
}
Expand Down
36 changes: 28 additions & 8 deletions internal/reconcilers/google/gcp/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type googleGcpReconciler struct {
tenantDomain string
tenantName string
flags config.FeatureFlags
clusterAlias map[string]string
}

type OptFunc func(*googleGcpReconciler)
Expand All @@ -70,14 +71,15 @@ func WithGcpServices(gcpServices *GcpServices) OptFunc {
}
}

func New(ctx context.Context, clusters gcp.Clusters, serviceAccountEmail, tenantDomain, tenantName, cnrmRoleName, billingAccount string, flags config.FeatureFlags, opts ...OptFunc) (reconcilers.Reconciler, error) {
func New(ctx context.Context, clusters gcp.Clusters, serviceAccountEmail, tenantDomain, tenantName, cnrmRoleName, billingAccount string, clusterAlias map[string]string, flags config.FeatureFlags, opts ...OptFunc) (reconcilers.Reconciler, error) {
r := &googleGcpReconciler{
billingAccount: billingAccount,
clusters: clusters,
cnrmRoleName: cnrmRoleName,
tenantDomain: tenantDomain,
tenantName: tenantName,
flags: flags,
clusterAlias: clusterAlias,
}

for _, opt := range opts {
Expand Down Expand Up @@ -136,20 +138,33 @@ func (r *googleGcpReconciler) Reconcile(ctx context.Context, client *apiclient.A
continue
}

if _, isAlias := r.clusterAlias[env.EnvironmentName]; isAlias {
continue
}

projectID := GenerateProjectID(r.tenantDomain, env.EnvironmentName, naisTeam.Slug)
log.WithField("project_id", projectID).Debugf("generated GCP project ID")
teamProject, err := r.getOrCreateProject(ctx, client, projectID, env, cluster.TeamsFolderID, naisTeam)
if err != nil {
return fmt.Errorf("get or create a GCP project %q for team %q in environment %q: %w", projectID, naisTeam.Slug, env.EnvironmentName, err)
}

_, err = client.Teams().SetTeamEnvironmentExternalReferences(ctx, &protoapi.SetTeamEnvironmentExternalReferencesRequest{
Slug: naisTeam.Slug,
EnvironmentName: env.EnvironmentName,
GcpProjectId: &teamProject.ProjectId,
})
if err != nil {
return fmt.Errorf("set GCP project ID for team %q in environment %q: %w", naisTeam.Slug, env.EnvironmentName, err)
envList := []string{env.EnvironmentName}
for alias, original := range r.clusterAlias {
if original == env.EnvironmentName {
envList = append(envList, alias)
}
}

for _, envName := range envList {
_, err = client.Teams().SetTeamEnvironmentExternalReferences(ctx, &protoapi.SetTeamEnvironmentExternalReferencesRequest{
Slug: naisTeam.Slug,
EnvironmentName: envName,
GcpProjectId: &teamProject.ProjectId,
})
if err != nil {
return fmt.Errorf("set GCP project ID for team %q in environment %q: %w", naisTeam.Slug, envName, err)
}
}

labels := map[string]string{
Expand Down Expand Up @@ -217,6 +232,11 @@ func (r *googleGcpReconciler) Delete(ctx context.Context, client *apiclient.APIC
continue
}

if _, isAlias := r.clusterAlias[env.EnvironmentName]; isAlias {
log.Infof("skipping alias environment %q", env.EnvironmentName)
continue
}

projectID := *env.GcpProjectId

log := log.WithField("gcp_project_id", projectID).WithField("environment", env.EnvironmentName)
Expand Down
22 changes: 16 additions & 6 deletions internal/reconcilers/google/gcp/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ var (
Slug: teamSlug,
}
ctx = context.Background()

aliasList = map[string]string{"prodalias": env}
)

func TestReconcile(t *testing.T) {
Expand All @@ -68,7 +70,7 @@ func TestReconcile(t *testing.T) {
Return(nil, fmt.Errorf("some error")).
Once()

reconcilers, err := google_gcp_reconciler.New(ctx, clusters, clusterProjectID, tenantDomain, tenantName, cnrmRoleName, billingAccount, config.FeatureFlags{}, google_gcp_reconciler.WithGcpServices(&google_gcp_reconciler.GcpServices{}))
reconcilers, err := google_gcp_reconciler.New(ctx, clusters, clusterProjectID, tenantDomain, tenantName, cnrmRoleName, billingAccount, aliasList, config.FeatureFlags{}, google_gcp_reconciler.WithGcpServices(&google_gcp_reconciler.GcpServices{}))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand All @@ -82,7 +84,7 @@ func TestReconcile(t *testing.T) {
log, _ := logrustest.NewNullLogger()

apiClient, _ := apiclient.NewMockClient(t)
reconcilers, err := google_gcp_reconciler.New(ctx, clusters, clusterProjectID, tenantDomain, tenantName, cnrmRoleName, billingAccount, config.FeatureFlags{}, google_gcp_reconciler.WithGcpServices(&google_gcp_reconciler.GcpServices{}))
reconcilers, err := google_gcp_reconciler.New(ctx, clusters, clusterProjectID, tenantDomain, tenantName, cnrmRoleName, billingAccount, aliasList, config.FeatureFlags{}, google_gcp_reconciler.WithGcpServices(&google_gcp_reconciler.GcpServices{}))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand All @@ -96,7 +98,7 @@ func TestReconcile(t *testing.T) {
log, _ := logrustest.NewNullLogger()

apiClient, _ := apiclient.NewMockClient(t)
reconcilers, err := google_gcp_reconciler.New(ctx, gcp.Clusters{}, clusterProjectID, tenantDomain, tenantName, cnrmRoleName, billingAccount, config.FeatureFlags{}, google_gcp_reconciler.WithGcpServices(&google_gcp_reconciler.GcpServices{}))
reconcilers, err := google_gcp_reconciler.New(ctx, gcp.Clusters{}, clusterProjectID, tenantDomain, tenantName, cnrmRoleName, billingAccount, aliasList, config.FeatureFlags{}, google_gcp_reconciler.WithGcpServices(&google_gcp_reconciler.GcpServices{}))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand Down Expand Up @@ -141,6 +143,14 @@ func TestReconcile(t *testing.T) {
}).
Return(&protoapi.SetTeamEnvironmentExternalReferencesResponse{}, nil).
Once()
mockServer.Teams.EXPECT().
SetTeamEnvironmentExternalReferences(mock.Anything, &protoapi.SetTeamEnvironmentExternalReferencesRequest{
Slug: teamSlug,
EnvironmentName: "prodalias",
GcpProjectId: &expectedTeamProjectID,
}).
Return(&protoapi.SetTeamEnvironmentExternalReferencesResponse{}, nil).
Once()

srv := test.HttpServerWithHandlers(t, []http.HandlerFunc{
// create project request
Expand Down Expand Up @@ -503,7 +513,7 @@ func TestReconcile(t *testing.T) {
ProjectsRolesService: iamService.Projects.Roles,
}

reconcilers, err := google_gcp_reconciler.New(ctx, clusters, clusterProjectID, tenantDomain, tenantName, cnrmRoleName, billingAccount, flags, google_gcp_reconciler.WithGcpServices(gcpServices))
reconcilers, err := google_gcp_reconciler.New(ctx, clusters, clusterProjectID, tenantDomain, tenantName, cnrmRoleName, billingAccount, aliasList, flags, google_gcp_reconciler.WithGcpServices(gcpServices))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand All @@ -523,7 +533,7 @@ func TestDelete(t *testing.T) {
Environments(mock.Anything, &protoapi.ListTeamEnvironmentsRequest{Slug: teamSlug, Limit: 100}).
Return(nil, fmt.Errorf("some error")).
Once()
reconcilers, err := google_gcp_reconciler.New(ctx, clusters, clusterProjectID, tenantDomain, tenantName, cnrmRoleName, billingAccount, config.FeatureFlags{}, google_gcp_reconciler.WithGcpServices(&google_gcp_reconciler.GcpServices{}))
reconcilers, err := google_gcp_reconciler.New(ctx, clusters, clusterProjectID, tenantDomain, tenantName, cnrmRoleName, billingAccount, aliasList, config.FeatureFlags{}, google_gcp_reconciler.WithGcpServices(&google_gcp_reconciler.GcpServices{}))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand All @@ -547,7 +557,7 @@ func TestDelete(t *testing.T) {
}, nil).
Once()

reconcilers, err := google_gcp_reconciler.New(ctx, clusters, clusterProjectID, tenantDomain, tenantName, cnrmRoleName, billingAccount, config.FeatureFlags{}, google_gcp_reconciler.WithGcpServices(&google_gcp_reconciler.GcpServices{}))
reconcilers, err := google_gcp_reconciler.New(ctx, clusters, clusterProjectID, tenantDomain, tenantName, cnrmRoleName, billingAccount, aliasList, config.FeatureFlags{}, google_gcp_reconciler.WithGcpServices(&google_gcp_reconciler.GcpServices{}))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand Down

0 comments on commit bf88de5

Please sign in to comment.