diff --git a/api/client/env_groups.go b/api/client/env_groups.go index 07557f36f1..090a1c08f7 100644 --- a/api/client/env_groups.go +++ b/api/client/env_groups.go @@ -31,6 +31,7 @@ type UpdateEnvGroupInput struct { EnvGroupName string Variables map[string]string Secrets map[string]string + Deletions environment_groups.EnvVariableDeletions } // UpdateEnvGroup creates or updates an environment group with the provided variables @@ -42,6 +43,7 @@ func (c *Client) UpdateEnvGroup( Name: inp.EnvGroupName, Variables: inp.Variables, SecretVariables: inp.Secrets, + Deletions: inp.Deletions, } return c.postRequest( diff --git a/api/client/porter_app.go b/api/client/porter_app.go index 32dfad4718..1c5f9bf09b 100644 --- a/api/client/porter_app.go +++ b/api/client/porter_app.go @@ -215,6 +215,7 @@ type UpdateAppInput struct { Exact bool Variables map[string]string Secrets map[string]string + Deletions porter_app.Deletions } // UpdateApp updates a porter app @@ -239,6 +240,7 @@ func (c *Client) UpdateApp( Exact: inp.Exact, Variables: inp.Variables, Secrets: inp.Secrets, + Deletions: inp.Deletions, } err := c.postRequest( diff --git a/api/server/handlers/environment_groups/create.go b/api/server/handlers/environment_groups/create.go index 8dfd220092..096892bdd0 100644 --- a/api/server/handlers/environment_groups/create.go +++ b/api/server/handlers/environment_groups/create.go @@ -33,6 +33,14 @@ func NewUpdateEnvironmentGroupHandler( } } +// EnvVariableDeletions is the set of keys to delete from the environment group +type EnvVariableDeletions struct { + // Variables is a set of variable keys to delete from the environment group + Variables []string `json:"variables"` + // Secrets is a set of secret variable keys to delete from the environment group + Secrets []string `json:"secrets"` +} + type UpdateEnvironmentGroupRequest struct { // Name of the env group to create or update Name string `json:"name"` @@ -51,6 +59,9 @@ type UpdateEnvironmentGroupRequest struct { // IsEnvOverride is a flag to determine if provided variables should override or merge with existing variables IsEnvOverride bool `json:"is_env_override"` + + // Deletions is a set of keys to delete from the environment group + Deletions EnvVariableDeletions `json:"deletions"` } type UpdateEnvironmentGroupResponse struct { // Name of the env group to create or update @@ -105,6 +116,10 @@ func (c *UpdateEnvironmentGroupHandler) ServeHTTP(w http.ResponseWriter, r *http Normal: request.Variables, Secret: request.SecretVariables, }, + EnvVariableDeletions: &porterv1.EnvVariableDeletions{ + Variables: request.Deletions.Variables, + Secrets: request.Deletions.Secrets, + }, IsEnvOverride: request.IsEnvOverride, })) if err != nil { diff --git a/api/server/handlers/porter_app/update_app.go b/api/server/handlers/porter_app/update_app.go index 4cacc2d800..5ac515031a 100644 --- a/api/server/handlers/porter_app/update_app.go +++ b/api/server/handlers/porter_app/update_app.go @@ -43,13 +43,21 @@ type ServiceDeletions struct { IngressAnnotationKeys []string `json:"ingress_annotation_keys"` } +// EnvVariableDeletions is the set of keys to delete from the environment group +type EnvVariableDeletions struct { + // Variables is a set of variable keys to delete from the environment group + Variables []string `json:"variables"` + // Secrets is a set of secret variable keys to delete from the environment group + Secrets []string `json:"secrets"` +} + // Deletions are the names of services and env variables to delete type Deletions struct { - ServiceNames []string `json:"service_names"` - Predeploy []string `json:"predeploy"` - EnvVariableNames []string `json:"env_variable_names"` - EnvGroupNames []string `json:"env_group_names"` - ServiceDeletions map[string]ServiceDeletions `json:"service_deletions"` + ServiceNames []string `json:"service_names"` + Predeploy []string `json:"predeploy"` + EnvGroupNames []string `json:"env_group_names"` + ServiceDeletions map[string]ServiceDeletions `json:"service_deletions"` + EnvVariableDeletions EnvVariableDeletions `json:"env_variable_deletions"` } // UpdateAppRequest is the request object for the POST /apps/update endpoint @@ -284,9 +292,12 @@ func (c *UpdateAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { Deletions: &porterv1.Deletions{ ServiceNames: request.Deletions.ServiceNames, PredeployNames: request.Deletions.Predeploy, - EnvVariableNames: request.Deletions.EnvVariableNames, EnvGroupNames: request.Deletions.EnvGroupNames, ServiceDeletions: serviceDeletions, + EnvVariableDeletions: &porterv1.EnvVariableDeletions{ + Variables: request.Deletions.EnvVariableDeletions.Variables, + Secrets: request.Deletions.EnvVariableDeletions.Secrets, + }, }, AppOverrides: overrides, CommitSha: request.CommitSHA, diff --git a/cli/cmd/commands/env.go b/cli/cmd/commands/env.go index 085733f8b8..82b805e638 100644 --- a/cli/cmd/commands/env.go +++ b/cli/cmd/commands/env.go @@ -7,6 +7,8 @@ import ( "github.com/fatih/color" api "github.com/porter-dev/porter/api/client" + "github.com/porter-dev/porter/api/server/handlers/environment_groups" + "github.com/porter-dev/porter/api/server/handlers/porter_app" "github.com/porter-dev/porter/api/types" "github.com/porter-dev/porter/cli/cmd/config" "github.com/spf13/cobra" @@ -23,6 +25,11 @@ type envVariables struct { Secrets map[string]string `json:"secrets"` } +type envVariableDeletions struct { + Variables []string `json:"variables"` + Secrets []string `json:"secrets"` +} + func registerCommand_Env(cliConf config.CLIConfig) *cobra.Command { envCmd := &cobra.Command{ Use: "env", @@ -207,7 +214,60 @@ func setEnv(ctx context.Context, user *types.GetAuthenticatedUserResponse, clien } func unsetEnv(ctx context.Context, user *types.GetAuthenticatedUserResponse, client api.Client, cliConf config.CLIConfig, featureFlags config.FeatureFlags, cmd *cobra.Command, args []string) error { - fmt.Println("This command is not supported for your project. Contact support@porter.run for more information.") + var envVarDeletions envVariableDeletions + + variables, err := cmd.Flags().GetStringSlice("variables") + if err != nil { + return fmt.Errorf("could not get variables: %w", err) + } + + secrets, err := cmd.Flags().GetStringSlice("secrets") + if err != nil { + return fmt.Errorf("could not get secrets: %w", err) + } + + envVarDeletions = envVariableDeletions{ + Variables: variables, + Secrets: secrets, + } + + if appName != "" { + color.New(color.FgGreen).Printf("Unsetting environment variables for app %s...\n", appName) // nolint:errcheck,gosec + + _, err := client.UpdateApp(ctx, api.UpdateAppInput{ + ProjectID: cliConf.Project, + ClusterID: cliConf.Cluster, + Name: appName, + DeploymentTargetName: deploymentTargetName, + Deletions: porter_app.Deletions{ + EnvVariableDeletions: porter_app.EnvVariableDeletions{ + Variables: envVarDeletions.Variables, + Secrets: envVarDeletions.Secrets, + }, + }, + }) + if err != nil { + return fmt.Errorf("could not unset app env variables: %w", err) + } + } + + if envGroupName != "" { + color.New(color.FgGreen).Printf("Unsetting environment variables for environment group %s...\n", envGroupName) // nolint:errcheck,gosec + + err := client.UpdateEnvGroup(ctx, api.UpdateEnvGroupInput{ + ProjectID: cliConf.Project, + ClusterID: cliConf.Cluster, + EnvGroupName: envGroupName, + Deletions: environment_groups.EnvVariableDeletions{ + Variables: envVarDeletions.Variables, + Secrets: envVarDeletions.Secrets, + }, + }) + if err != nil { + return fmt.Errorf("could not unset env group env variables: %w", err) + } + } + return nil } diff --git a/go.mod b/go.mod index 0f1d94fabe..e25c31432c 100644 --- a/go.mod +++ b/go.mod @@ -83,7 +83,7 @@ require ( github.com/matryer/is v1.4.0 github.com/nats-io/nats.go v1.24.0 github.com/open-policy-agent/opa v0.44.0 - github.com/porter-dev/api-contracts v0.2.120 + github.com/porter-dev/api-contracts v0.2.122 github.com/riandyrn/otelchi v0.5.1 github.com/santhosh-tekuri/jsonschema/v5 v5.0.1 github.com/stefanmcshane/helm v0.0.0-20221213002717-88a4a2c6e77d diff --git a/go.sum b/go.sum index 1e48af6b61..a68ae67d34 100644 --- a/go.sum +++ b/go.sum @@ -1523,8 +1523,8 @@ github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polyfloyd/go-errorlint v0.0.0-20210722154253-910bb7978349/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= -github.com/porter-dev/api-contracts v0.2.120 h1:0PgDKwq9879NsTTvObtVxFVQI8rL7B0OA1i91+zfzs0= -github.com/porter-dev/api-contracts v0.2.120/go.mod h1:fX6JmP5QuzxDLvqP3evFOTXjI4dHxsG0+VKNTjImZU8= +github.com/porter-dev/api-contracts v0.2.122 h1:Qy7SZzcXSvIuUGq6MB99qt8eTwtMQzlqZQMdCxE8ZCs= +github.com/porter-dev/api-contracts v0.2.122/go.mod h1:fX6JmP5QuzxDLvqP3evFOTXjI4dHxsG0+VKNTjImZU8= github.com/porter-dev/switchboard v0.0.3 h1:dBuYkiVLa5Ce7059d6qTe9a1C2XEORFEanhbtV92R+M= github.com/porter-dev/switchboard v0.0.3/go.mod h1:xSPzqSFMQ6OSbp42fhCi4AbGbQbsm6nRvOkrblFeXU4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=