Skip to content

Add azd env get-value #4080

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

Merged
merged 5 commits into from
Jul 9, 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
104 changes: 104 additions & 0 deletions cli/azd/cmd/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ func envActions(root *actions.ActionDescriptor) *actions.ActionDescriptor {
DefaultFormat: output.EnvVarsFormat,
})

group.Add("get-value", &actions.ActionDescriptorOptions{
Command: newEnvGetValueCmd(),
FlagsResolver: newEnvGetValueFlags,
ActionResolver: newEnvGetValueAction,
})

return group
}

Expand Down Expand Up @@ -592,6 +598,104 @@ func (eg *envGetValuesAction) Run(ctx context.Context) (*actions.ActionResult, e
return nil, eg.formatter.Format(env.Dotenv(), eg.writer, nil)
}

func newEnvGetValueFlags(cmd *cobra.Command, global *internal.GlobalCommandOptions) *envGetValueFlags {
flags := &envGetValueFlags{}
flags.Bind(cmd.Flags(), global)

return flags
}

func newEnvGetValueCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "get-value <keyName>",
Short: "Get specific environment value.",
}
cmd.Args = cobra.MaximumNArgs(1)

return cmd
}

type envGetValueFlags struct {
internal.EnvFlag
global *internal.GlobalCommandOptions
}

func (eg *envGetValueFlags) Bind(local *pflag.FlagSet, global *internal.GlobalCommandOptions) {
eg.EnvFlag.Bind(local, global)
eg.global = global
}

type envGetValueAction struct {
azdCtx *azdcontext.AzdContext
console input.Console
envManager environment.Manager
writer io.Writer
flags *envGetValueFlags
args []string
}

func newEnvGetValueAction(
azdCtx *azdcontext.AzdContext,
envManager environment.Manager,
console input.Console,
writer io.Writer,
flags *envGetValueFlags,
args []string,

) actions.Action {
return &envGetValueAction{
azdCtx: azdCtx,
console: console,
envManager: envManager,
writer: writer,
flags: flags,
args: args,
}
}

func (eg *envGetValueAction) Run(ctx context.Context) (*actions.ActionResult, error) {
if len(eg.args) < 1 {
return nil, fmt.Errorf("no key name provided")
}

keyName := eg.args[0]

name, err := eg.azdCtx.GetDefaultEnvironmentName()
if err != nil {
return nil, err
}
// Note: if there is not an environment yet, GetDefaultEnvironmentName() returns empty string (not error)
// and later, when envManager.Get() is called with the empty string, azd returns an error.
// But if there is already an environment (default to be selected), azd must honor the --environment flag
// over the default environment.
if eg.flags.EnvironmentName != "" {
name = eg.flags.EnvironmentName
}
env, err := eg.envManager.Get(ctx, name)
if errors.Is(err, environment.ErrNotFound) {
return nil, fmt.Errorf(
`environment '%s' does not exist. You can create it with "azd env new %s"`,
name,
name,
)
} else if err != nil {
return nil, fmt.Errorf("ensuring environment exists: %w", err)
}

values := env.Dotenv()
keyValue, exists := values[keyName]
if !exists {
return nil, fmt.Errorf("key '%s' not found in the environment values", keyName)
}

// Directly write the key value to the writer
if _, err := fmt.Fprintln(eg.writer, keyValue); err != nil {
return nil, fmt.Errorf("writing key value: %w", err)
}

return nil, nil
}

func getCmdEnvHelpDescription(*cobra.Command) string {
return generateCmdHelpDescription(
"Manage your application environments. With this command group, you can create a new environment or get, set,"+
Expand Down
19 changes: 19 additions & 0 deletions cli/azd/cmd/testdata/TestUsage-azd-env-get-value.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

Get specific environment value.

Usage
azd env get-value <keyName> [flags]

Flags
--docs : Opens the documentation for azd env get-value in your web browser.
-e, --environment string : The name of the environment to use.
-h, --help : Gets help for get-value.

Global Flags
-C, --cwd string : Sets the current working directory.
--debug : Enables debugging and diagnostics logging.
--no-prompt : Accepts the default value instead of prompting, or it fails if there is no default.

Find a bug? Want to let us know how we're doing? Fill out this brief survey: https://aka.ms/azure-dev/hats.


1 change: 1 addition & 0 deletions cli/azd/cmd/testdata/TestUsage-azd-env.snap
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Usage
azd env [command]

Available Commands
get-value : Get specific environment value.
get-values : Get all environment values.
list : List environments.
new : Create a new environment and set it as the default.
Expand Down
53 changes: 53 additions & 0 deletions cli/azd/test/functional/env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,59 @@ func Test_CLI_Env_Values_MultipleEnvironments(t *testing.T) {
require.Equal(t, values["envName2"], envName2)
}

func Test_CLI_Env_GetValue(t *testing.T) {
ctx, cancel := newTestContext(t)
defer cancel()

dir := tempDirWithDiagnostics(t)
t.Logf("DIR: %s", dir)

cli := azdcli.NewCLI(t)
cli.WorkingDirectory = dir

err := copySample(dir, "storage")
require.NoError(t, err, "failed expanding sample")

// Create an environment
envName := randomEnvName()
envNew(ctx, t, cli, envName, false)

// Set key1
envSetValue(ctx, t, cli, "key1", "value1")

// Get key1 value
value := envGetValue(ctx, t, cli, "key1")
require.Equal(t, "value1", value)

// Set key2
envSetValue(ctx, t, cli, "key2", "value2")

// Get key2 value
value = envGetValue(ctx, t, cli, "key2")
require.Equal(t, "value2", value)

// Modify key1
envSetValue(ctx, t, cli, "key1", "modified1")

// Get modified key1 value
value = envGetValue(ctx, t, cli, "key1")
require.Equal(t, "modified1", value)

// Test non-existent key
res, err := cli.RunCommand(ctx, "env", "get-value", "non_existent_key")
require.Error(t, err)
require.Contains(t, res.Stdout, "key 'non_existent_key' not found in the environment values")
}

func envGetValue(ctx context.Context, t *testing.T, cli *azdcli.CLI, key string) string {
args := []string{"env", "get-value", key}

result, err := cli.RunCommand(ctx, args...)
require.NoError(t, err)

return strings.TrimSpace(result.Stdout)
}

func requireIsDefault(t *testing.T, list []contracts.EnvListEnvironment, envName string) {
for _, env := range list {
if env.Name == envName {
Expand Down
Loading