From 91d2a2d64a0add7acddfe4c5794e9d1632f97029 Mon Sep 17 00:00:00 2001 From: Sean Yeh <109418+seanyeh@users.noreply.github.com> Date: Wed, 5 Feb 2025 11:45:07 -0600 Subject: [PATCH] Separate open environment from rotate --- cmd/esc/cli/client/client.go | 24 ++++----------- cmd/esc/cli/client/client_test.go | 14 ++------- cmd/esc/cli/env_rotate.go | 51 ++++--------------------------- 3 files changed, 15 insertions(+), 74 deletions(-) diff --git a/cmd/esc/cli/client/client.go b/cmd/esc/cli/client/client.go index 131af482..ccaf1158 100644 --- a/cmd/esc/cli/client/client.go +++ b/cmd/esc/cli/client/client.go @@ -157,19 +157,13 @@ type Client interface { // RotateEnvironment will rotate credentials in an environment. // If rotationPaths is non-empty, will only rotate credentials at those paths. - // It also evaluates the environment projectName/envName in org orgName and returns the ID of the opened - // environment. The opened environment will be available for the indicated duration, after which it - // will expire. - // - // If the environment contains errors, the open will fail with diagnostics. RotateEnvironment( ctx context.Context, orgName string, projectName string, envName string, - duration time.Duration, rotationPaths []string, - ) (string, []EnvironmentDiagnostic, error) + ) ([]EnvironmentDiagnostic, error) // CheckYAMLEnvironment checks the given environment YAML for errors within the context of org orgName. // @@ -637,9 +631,8 @@ func (pc *client) RotateEnvironment( orgName string, projectName string, envName string, - duration time.Duration, rotationPaths []string, -) (string, []EnvironmentDiagnostic, error) { +) ([]EnvironmentDiagnostic, error) { path := fmt.Sprintf("/api/esc/environments/%v/%v/%v/rotate", orgName, projectName, envName) reqObj := struct { @@ -648,26 +641,21 @@ func (pc *client) RotateEnvironment( Paths: rotationPaths, } - queryObj := struct { - Duration string `url:"duration"` - }{ - Duration: duration.String(), - } var resp struct { ID string `json:"id"` } var errResp EnvironmentErrorResponse - err := pc.restCallWithOptions(ctx, http.MethodPost, path, queryObj, reqObj, &resp, httpCallOptions{ + err := pc.restCallWithOptions(ctx, http.MethodPost, path, nil, reqObj, &resp, httpCallOptions{ ErrorResponse: &errResp, }) if err != nil { var diags *EnvironmentErrorResponse if errors.As(err, &diags) && diags.Code == http.StatusBadRequest && len(diags.Diagnostics) != 0 { - return "", diags.Diagnostics, nil + return diags.Diagnostics, nil } - return "", nil, err + return nil, err } - return resp.ID, nil, nil + return nil, nil } func (pc *client) CheckYAMLEnvironment( diff --git a/cmd/esc/cli/client/client_test.go b/cmd/esc/cli/client/client_test.go index d0fdb0f0..e90438e8 100644 --- a/cmd/esc/cli/client/client_test.go +++ b/cmd/esc/cli/client/client_test.go @@ -507,24 +507,16 @@ func TestOpenEnvironment(t *testing.T) { func TestRotateEnvironment(t *testing.T) { rotationPaths := []string{"a.b", "c"} t.Run("OK", func(t *testing.T) { - const expectedID = "open-id" - duration := 2 * time.Hour expectedBody := "{\"Paths\":[\"a.b\",\"c\"]}" client := newTestClient(t, http.MethodPost, "/api/esc/environments/test-org/test-project/test-env/rotate", func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, duration.String(), r.URL.Query().Get("duration")) - body, err := io.ReadAll(r.Body) require.NoError(t, err) assert.Equal(t, expectedBody, string(body)) - - err = json.NewEncoder(w).Encode(map[string]any{"id": expectedID}) - require.NoError(t, err) }) - id, diags, err := client.RotateEnvironment(context.Background(), "test-org", "test-project", "test-env", duration, rotationPaths) + diags, err := client.RotateEnvironment(context.Background(), "test-org", "test-project", "test-env", rotationPaths) require.NoError(t, err) - assert.Equal(t, expectedID, id) assert.Empty(t, diags) }) @@ -559,7 +551,7 @@ func TestRotateEnvironment(t *testing.T) { require.NoError(t, err) }) - _, diags, err := client.RotateEnvironment(context.Background(), "test-org", "test-project", "test-env", 2*time.Hour, rotationPaths) + diags, err := client.RotateEnvironment(context.Background(), "test-org", "test-project", "test-env", rotationPaths) require.NoError(t, err) assert.Equal(t, expected, diags) }) @@ -575,7 +567,7 @@ func TestRotateEnvironment(t *testing.T) { require.NoError(t, err) }) - _, _, err := client.RotateEnvironment(context.Background(), "test-org", "test-project", "test-env", 2*time.Hour, rotationPaths) + _, err := client.RotateEnvironment(context.Background(), "test-org", "test-project", "test-env", rotationPaths) assert.ErrorContains(t, err, "not found") }) } diff --git a/cmd/esc/cli/env_rotate.go b/cmd/esc/cli/env_rotate.go index 5ea43980..c2e6e5f9 100644 --- a/cmd/esc/cli/env_rotate.go +++ b/cmd/esc/cli/env_rotate.go @@ -5,27 +5,18 @@ package cli import ( "context" "fmt" - "time" - "github.com/pulumi/esc" - "github.com/pulumi/esc/cmd/esc/cli/client" "github.com/pulumi/pulumi/sdk/v3/go/common/resource" "github.com/spf13/cobra" ) func newEnvRotateCmd(envcmd *envCommand) *cobra.Command { - var duration time.Duration - var format string - cmd := &cobra.Command{ Use: "rotate [/][/] [path(s) to rotate]", - Short: "Rotate secrets and open the environment", - Long: "Rotate secrets and open the environment\n" + - "\n" + - "Optionally accepts any number of Property Paths as additional arguments. If given any paths, will only rotate secrets at those paths.\n" + + Short: "Rotate secrets in an environment", + Long: "Rotate secrets in an environment\n" + "\n" + - "This command opens the environment with the given name. The result is written to\n" + - "stdout as JSON.\n", + "Optionally accepts any number of Property Paths as additional arguments. If given any paths, will only rotate secrets at those paths.\n", SilenceUsage: true, Hidden: true, RunE: func(cmd *cobra.Command, args []string) error { @@ -53,14 +44,7 @@ func newEnvRotateCmd(envcmd *envCommand) *cobra.Command { rotationPaths = append(rotationPaths, arg) } - switch format { - case "detailed", "json", "yaml", "string", "dotenv", "shell": - // OK - default: - return fmt.Errorf("unknown output format %q", format) - } - - env, diags, err := envcmd.rotateEnvironment(ctx, ref, duration, rotationPaths) + diags, err := envcmd.esc.client.RotateEnvironment(ctx, ref.orgName, ref.projectName, ref.envName, rotationPaths) if err != nil { return err } @@ -68,33 +52,10 @@ func newEnvRotateCmd(envcmd *envCommand) *cobra.Command { return envcmd.writePropertyEnvironmentDiagnostics(envcmd.esc.stderr, diags) } - return envcmd.renderValue(envcmd.esc.stdout, env, resource.PropertyPath{}, format, false, true) + fmt.Fprintf(envcmd.esc.stdout, "Environment '%s' rotated.\n", args[0]) + return nil }, } - cmd.Flags().DurationVarP( - &duration, "lifetime", "l", 2*time.Hour, - "the lifetime of the opened environment in the form HhMm (e.g. 2h, 1h30m, 15m)") - cmd.Flags().StringVarP( - &format, "format", "f", "json", - "the output format to use. May be 'dotenv', 'json', 'yaml', 'detailed', or 'shell'") - return cmd } - -func (env *envCommand) rotateEnvironment( - ctx context.Context, - ref environmentRef, - duration time.Duration, - rotationPaths []string, -) (*esc.Environment, []client.EnvironmentDiagnostic, error) { - envID, diags, err := env.esc.client.RotateEnvironment(ctx, ref.orgName, ref.projectName, ref.envName, duration, rotationPaths) - if err != nil { - return nil, nil, err - } - if len(diags) != 0 { - return nil, diags, err - } - open, err := env.esc.client.GetOpenEnvironmentWithProject(ctx, ref.orgName, ref.projectName, ref.envName, envID) - return open, nil, err -}