diff --git a/api/server/handlers/environment_groups/create.go b/api/server/handlers/environment_groups/create.go index 5d0c748f30..ad9114e8ed 100644 --- a/api/server/handlers/environment_groups/create.go +++ b/api/server/handlers/environment_groups/create.go @@ -87,7 +87,7 @@ func (c *UpdateEnvironmentGroupHandler) ServeHTTP(w http.ResponseWriter, r *http CreatedAtUTC: time.Now().UTC(), } - err = environment_groups.CreateOrUpdateBaseEnvironmentGroup(ctx, agent, envGroup) + err = environment_groups.CreateOrUpdateBaseEnvironmentGroup(ctx, agent, envGroup, nil) if err != nil { err := telemetry.Error(ctx, span, err, "unable to create or update environment group") c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError)) diff --git a/api/server/handlers/porter_app/parse.go b/api/server/handlers/porter_app/parse.go index 21b5db1e1f..ac8f0511a3 100644 --- a/api/server/handlers/porter_app/parse.go +++ b/api/server/handlers/porter_app/parse.go @@ -369,7 +369,7 @@ func syncEnvironmentGroupToNamespaceIfLabelsExist(ctx context.Context, agent *ku TargetNamespace: targetNamespace, } - syncedEnvironment, err := environment_groups.SyncLatestVersionToNamespace(ctx, agent, inp) + syncedEnvironment, err := environment_groups.SyncLatestVersionToNamespace(ctx, agent, inp, nil) if err != nil { return fmt.Errorf("error syncing environment group: %w", err) } diff --git a/api/server/handlers/porter_app/update_app_environment_group.go b/api/server/handlers/porter_app/update_app_environment_group.go index 9166b53aed..d76b54a6b9 100644 --- a/api/server/handlers/porter_app/update_app_environment_group.go +++ b/api/server/handlers/porter_app/update_app_environment_group.go @@ -43,6 +43,15 @@ func NewUpdateAppEnvironmentHandler( } } +const ( + // LabelKey_AppName is the label key for the app name + LabelKey_AppName = "porter.run/app-name" + // LabelKey_DeploymentTargetID is the label key for the deployment target id + LabelKey_DeploymentTargetID = "porter.run/deployment-target-id" + // LabelKey_PorterManaged is the label key signifying the resource is managed by porter + LabelKey_PorterManaged = "porter.run/managed" +) + // UpdateAppEnvironmentRequest represents the accepted fields on a request to the /apps/{porter_app_name}/environment-group endpoint type UpdateAppEnvironmentRequest struct { DeploymentTargetID string `json:"deployment_target_id"` @@ -217,7 +226,14 @@ func (c *UpdateAppEnvironmentHandler) ServeHTTP(w http.ResponseWriter, r *http.R CreatedAtUTC: time.Now().UTC(), } - err = environment_groups.CreateOrUpdateBaseEnvironmentGroup(ctx, agent, envGroup) + additionalEnvGroupLabels := map[string]string{ + LabelKey_AppName: appName, + LabelKey_DeploymentTargetID: request.DeploymentTargetID, + environment_groups.LabelKey_DefaultAppEnvironment: "true", + LabelKey_PorterManaged: "true", + } + + err = environment_groups.CreateOrUpdateBaseEnvironmentGroup(ctx, agent, envGroup, additionalEnvGroupLabels) if err != nil { err := telemetry.Error(ctx, span, err, "unable to create or update base environment group") c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError)) @@ -229,7 +245,7 @@ func (c *UpdateAppEnvironmentHandler) ServeHTTP(w http.ResponseWriter, r *http.R TargetNamespace: namespace, } - syncedEnvironment, err := environment_groups.SyncLatestVersionToNamespace(ctx, agent, inp) + syncedEnvironment, err := environment_groups.SyncLatestVersionToNamespace(ctx, agent, inp, additionalEnvGroupLabels) if err != nil { err := telemetry.Error(ctx, span, err, "unable to create or update synced environment group") c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError)) diff --git a/internal/kubernetes/environment_groups/create.go b/internal/kubernetes/environment_groups/create.go index 706a3a8fd8..6fc5462c23 100644 --- a/internal/kubernetes/environment_groups/create.go +++ b/internal/kubernetes/environment_groups/create.go @@ -17,7 +17,7 @@ import ( // If no existing environmentGroup exists by this name, a new one will be created as version 1, denoted by the label "porter.run/environment-group-version: 1". // If an environmentGroup already exists by this name, a new version will be created, and the label will be updated to reflect the new version. // Providing the Version field to this function will be ignored in order to not accidentally overwrite versions -func CreateOrUpdateBaseEnvironmentGroup(ctx context.Context, a *kubernetes.Agent, environmentGroup EnvironmentGroup) error { +func CreateOrUpdateBaseEnvironmentGroup(ctx context.Context, a *kubernetes.Agent, environmentGroup EnvironmentGroup, additionalLabels map[string]string) error { ctx, span := telemetry.NewSpan(ctx, "create-environment-group") defer span.End() telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "environment-group", Value: environmentGroup.Name}) @@ -67,7 +67,7 @@ func CreateOrUpdateBaseEnvironmentGroup(ctx context.Context, a *kubernetes.Agent CreatedAtUTC: environmentGroup.CreatedAtUTC, } - err = createVersionedEnvironmentGroupInNamespace(ctx, a, newEnvironmentGroup, Namespace_EnvironmentGroups) + err = createVersionedEnvironmentGroupInNamespace(ctx, a, newEnvironmentGroup, Namespace_EnvironmentGroups, additionalLabels) if err != nil { return telemetry.Error(ctx, span, err, "unable to create new versioned environment group") } @@ -78,7 +78,7 @@ func CreateOrUpdateBaseEnvironmentGroup(ctx context.Context, a *kubernetes.Agent // createEnvironmentGroupInTargetNamespace creates a new environment group in the target namespace. If you want to create a new base environment group, use CreateOrUpdateBaseEnvironmentGroup instead. // This should only be used for sync from a base environment to a target environment. // If the target namespace does not exist, it will be created for you. -func createEnvironmentGroupInTargetNamespace(ctx context.Context, a *kubernetes.Agent, namespace string, environmentGroup EnvironmentGroup) (string, error) { +func createEnvironmentGroupInTargetNamespace(ctx context.Context, a *kubernetes.Agent, namespace string, environmentGroup EnvironmentGroup, additionalLabels map[string]string) (string, error) { ctx, span := telemetry.NewSpan(ctx, "create-environment-group-in-target") defer span.End() telemetry.WithAttributes(span, @@ -111,7 +111,7 @@ func createEnvironmentGroupInTargetNamespace(ctx context.Context, a *kubernetes. } telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "environment-group-namespace", Value: namespace}) - err = createVersionedEnvironmentGroupInNamespace(ctx, a, environmentGroup, namespace) + err = createVersionedEnvironmentGroupInNamespace(ctx, a, environmentGroup, namespace, additionalLabels) if err != nil { return configMapName, telemetry.Error(ctx, span, err, "error creating environment group clone in target namespace") } @@ -120,7 +120,7 @@ func createEnvironmentGroupInTargetNamespace(ctx context.Context, a *kubernetes. } // createVersionedEnvironmentGroupInNamespace creates a new environment group in the target namespace. This is used to keep the configmap and secret version for an environment variable in sync -func createVersionedEnvironmentGroupInNamespace(ctx context.Context, a *kubernetes.Agent, environmentGroup EnvironmentGroup, targetNamespace string) error { +func createVersionedEnvironmentGroupInNamespace(ctx context.Context, a *kubernetes.Agent, environmentGroup EnvironmentGroup, targetNamespace string, additionalLabels map[string]string) error { ctx, span := telemetry.NewSpan(ctx, "create-environment-group-on-cluster") defer span.End() @@ -135,6 +135,10 @@ func createVersionedEnvironmentGroupInNamespace(ctx context.Context, a *kubernet }, Data: environmentGroup.Variables, } + for k, v := range additionalLabels { + configMap.Labels[k] = v + } + err := createConfigMapWithVersion(ctx, a, configMap, environmentGroup.Version) if err != nil { return telemetry.Error(ctx, span, err, "unable to create new environment group variables version") diff --git a/internal/kubernetes/environment_groups/list.go b/internal/kubernetes/environment_groups/list.go index 47415343bd..f66ef74ad7 100644 --- a/internal/kubernetes/environment_groups/list.go +++ b/internal/kubernetes/environment_groups/list.go @@ -17,6 +17,8 @@ const ( LabelKey_EnvironmentGroupVersion = "porter.run/environment-group-version" LabelKey_EnvironmentGroupName = "porter.run/environment-group-name" + LabelKey_DefaultAppEnvironment = "porter.run/default-app-environment" + // Namespace_EnvironmentGroups is the base namespace for storing all environment groups. // The configmaps and secrets here should be considered the source's of truth for a given version Namespace_EnvironmentGroups = "porter-env-group" @@ -37,9 +39,10 @@ type EnvironmentGroup struct { } type environmentGroupOptions struct { - namespace string - environmentGroupLabelName string - environmentGroupLabelVersion int + namespace string + environmentGroupLabelName string + environmentGroupLabelVersion int + includeDefaultAppEnvironmentGroups bool } // EnvironmentGroupOption is a function that modifies ListEnvironmentGroups @@ -66,6 +69,13 @@ func WithEnvironmentGroupVersion(version int) EnvironmentGroupOption { } } +// WithDefaultAppEnvironmentGroup includes default app environment groups in the list +func WithDefaultAppEnvironmentGroup() EnvironmentGroupOption { + return func(opts *environmentGroupOptions) { + opts.includeDefaultAppEnvironmentGroups = true + } +} + // listEnvironmentGroups returns all environment groups stored in the provided namespace. If none is set, it will use the namespace "porter-env-group". // This method returns all secret values, which should never be returned out of this package. If you are trying to get the environment group values to return to the user, // use the exported ListEnvironmentGroups instead. @@ -123,6 +133,13 @@ func listEnvironmentGroups(ctx context.Context, a *kubernetes.Agent, listOpts .. continue // invalid version label as it should be an int, not an environment group } + if !opts.includeDefaultAppEnvironmentGroups { + value := cm.Labels[LabelKey_DefaultAppEnvironment] + if value == "true" { + continue // do not include default app environment groups + } + } + if _, ok := envGroupSet[cm.Name]; !ok { envGroupSet[cm.Name] = EnvironmentGroup{} } @@ -148,6 +165,14 @@ func listEnvironmentGroups(ctx context.Context, a *kubernetes.Agent, listOpts .. if err != nil { continue // invalid version label as it should be an int, not an environment group } + + if !opts.includeDefaultAppEnvironmentGroups { + value, ok := secret.Labels[LabelKey_DefaultAppEnvironment] + if ok && value == "true" { + continue // do not include default app environment groups + } + } + if _, ok := envGroupSet[secret.Name]; !ok { envGroupSet[secret.Name] = EnvironmentGroup{} } diff --git a/internal/kubernetes/environment_groups/sync.go b/internal/kubernetes/environment_groups/sync.go index 9a6e72ae13..f717ce252e 100644 --- a/internal/kubernetes/environment_groups/sync.go +++ b/internal/kubernetes/environment_groups/sync.go @@ -26,7 +26,7 @@ type SyncLatestVersionToNamespaceOutput struct { // SyncLatestVersionToNamespace gets the latest version of a given environment group, and makes a copy of it in the target // namespace. If the versions match, no changes will be made. In either case, the name of an environment group in the target namespace will be returned // unless an error has occurred. -func SyncLatestVersionToNamespace(ctx context.Context, a *kubernetes.Agent, inp SyncLatestVersionToNamespaceInput) (SyncLatestVersionToNamespaceOutput, error) { +func SyncLatestVersionToNamespace(ctx context.Context, a *kubernetes.Agent, inp SyncLatestVersionToNamespaceInput, additionalLabels map[string]string) (SyncLatestVersionToNamespaceOutput, error) { ctx, span := telemetry.NewSpan(ctx, "sync-env-group-version-to-namespace") defer span.End() @@ -65,7 +65,7 @@ func SyncLatestVersionToNamespace(ctx context.Context, a *kubernetes.Agent, inp }, nil } - targetConfigmapName, err := createEnvironmentGroupInTargetNamespace(ctx, a, inp.TargetNamespace, baseEnvironmentGroup) + targetConfigmapName, err := createEnvironmentGroupInTargetNamespace(ctx, a, inp.TargetNamespace, baseEnvironmentGroup, additionalLabels) if err != nil { return output, telemetry.Error(ctx, span, err, "unable to create environment group in target namespace") }