internal/pkg/cli/env_list.go (119 lines of code) (raw):
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package cli
import (
"encoding/json"
"fmt"
"io"
"os"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ssm"
"github.com/aws/copilot-cli/internal/pkg/aws/identity"
"github.com/aws/copilot-cli/internal/pkg/aws/sessions"
"github.com/aws/copilot-cli/internal/pkg/config"
"github.com/aws/copilot-cli/internal/pkg/term/prompt"
"github.com/aws/copilot-cli/internal/pkg/term/selector"
"github.com/spf13/cobra"
)
const (
envListAppNamePrompt = "Which application is the environment in?"
envListAppNameHelper = "An application is a collection of related services."
)
type listEnvVars struct {
appName string
shouldOutputJSON bool
}
type listEnvOpts struct {
listEnvVars
store store
prompt prompter
sel configSelector
w io.Writer
}
func newListEnvOpts(vars listEnvVars) (*listEnvOpts, error) {
sessProvider := sessions.ImmutableProvider(sessions.UserAgentExtras("env ls"))
defaultSess, err := sessProvider.Default()
if err != nil {
return nil, err
}
store := config.NewSSMStore(identity.New(defaultSess), ssm.New(defaultSess), aws.StringValue(defaultSess.Config.Region))
prompter := prompt.New()
return &listEnvOpts{
listEnvVars: vars,
store: store,
sel: selector.NewConfigSelector(prompter, store),
prompt: prompter,
w: os.Stdout,
}, nil
}
// Ask asks for fields that are required but not passed in.
func (o *listEnvOpts) Ask() error {
if o.appName != "" {
return nil
}
app, err := o.sel.Application(envListAppNamePrompt, envListAppNameHelper)
if err != nil {
return fmt.Errorf("select application: %w", err)
}
o.appName = app
return nil
}
// Execute lists the environments through the prompt.
func (o *listEnvOpts) Execute() error {
// Ensure the application actually exists before we try to list its environments.
if _, err := o.store.GetApplication(o.appName); err != nil {
return err
}
envs, err := o.store.ListEnvironments(o.appName)
if err != nil {
return err
}
var out string
if o.shouldOutputJSON {
data, err := o.jsonOutput(envs)
if err != nil {
return err
}
out = data
} else {
out = o.humanOutput(envs)
}
fmt.Fprint(o.w, out)
return nil
}
func (o *listEnvOpts) humanOutput(envs []*config.Environment) string {
b := &strings.Builder{}
for _, env := range envs {
fmt.Fprintln(b, env.Name)
}
return b.String()
}
func (o *listEnvOpts) jsonOutput(envs []*config.Environment) (string, error) {
type serializedEnvs struct {
Environments []*config.Environment `json:"environments"`
}
b, err := json.Marshal(serializedEnvs{Environments: envs})
if err != nil {
return "", fmt.Errorf("marshal environments: %w", err)
}
return fmt.Sprintf("%s\n", b), nil
}
// buildEnvListCmd builds the command for listing environments in an application.
func buildEnvListCmd() *cobra.Command {
vars := listEnvVars{}
cmd := &cobra.Command{
Use: "ls",
Short: "Lists all the environments in an application.",
Example: `
Lists all the environments for the frontend application.
/code $ copilot env ls -a frontend`,
RunE: runCmdE(func(cmd *cobra.Command, args []string) error {
opts, err := newListEnvOpts(vars)
if err != nil {
return err
}
if err := opts.Ask(); err != nil {
return err
}
return opts.Execute()
}),
}
cmd.Flags().StringVarP(&vars.appName, appFlag, appFlagShort, tryReadingAppName(), appFlagDescription)
cmd.Flags().BoolVar(&vars.shouldOutputJSON, jsonFlag, false, jsonFlagDescription)
return cmd
}