Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

* add environment alias for migrating legacy clusters #23

Merged
merged 7 commits into from
Nov 26, 2024
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
10 changes: 8 additions & 2 deletions charts/Feature.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ values:
template: |
{{ .Env.tenant_domain | quote }}

clusterAlias:
displayName: Cluster aliases
Muni10 marked this conversation as resolved.
Show resolved Hide resolved
description: Each entry must be colon separeted key:value cluster aliases (e.g. dev:dev-gcp)
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 Expand Up @@ -91,7 +97,7 @@ values:
gcp.billingAccount:
displayName: Billing account
computed:
template: '{{ .Env.billing_account | quote }}'
template: "{{ .Env.billing_account | quote }}"

gcp.clusters:
displayName: Cluster information
Expand All @@ -113,7 +119,7 @@ values:
gcp.workloadIdentityPoolName:
displayName: Google workload identity pool name
computed:
template: '{{ .Env.nais_identity_pool_name | quote }}'
template: "{{ .Env.nais_identity_pool_name | quote }}"

grafana.endpoint:
displayName: Grafana API endpoint
Expand Down
2 changes: 2 additions & 0 deletions charts/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ spec:
value: {{ .Values.naisAPI.target }}
- name: LISTEN_ADDRESS
value: :3005
- name: CLUSTER_ALIAS
value: {{ .Values.clusterAlias | join "," | quote }}
- name: TENANT_DOMAIN
value: {{ .Values.tenantDomain }}
- name: TENANT_NAME
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: []
Copy link
Contributor

@thokra-nav thokra-nav Nov 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skal denne brukes noe sted? Mangler endringer i template fil isåfall

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Den skal settes i fasit når vi gjør endringer i fbm migreringen. Men kunne hatt med en kommentar der.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skjønner hva du mente nå ja, det hadde jeg glemt.

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
39 changes: 31 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,18 @@ 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) {
if clusterAlias == nil {
clusterAlias = make(map[string]string)
}
r := &googleGcpReconciler{
Muni10 marked this conversation as resolved.
Show resolved Hide resolved
billingAccount: billingAccount,
clusters: clusters,
cnrmRoleName: cnrmRoleName,
tenantDomain: tenantDomain,
tenantName: tenantName,
flags: flags,
clusterAlias: clusterAlias,
}

for _, opt := range opts {
Expand Down Expand Up @@ -136,20 +141,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 +235,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