Skip to content

Commit 00f25e1

Browse files
jongioMenghua1
authored andcommitted
Add azd env get-value (#4080)
* Test aks * Add get-value * Undo aks string * Remove formatter * Add tests
1 parent fb357c0 commit 00f25e1

File tree

4 files changed

+177
-0
lines changed

4 files changed

+177
-0
lines changed

cli/azd/cmd/env.go

+104
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ func envActions(root *actions.ActionDescriptor) *actions.ActionDescriptor {
7979
DefaultFormat: output.EnvVarsFormat,
8080
})
8181

82+
group.Add("get-value", &actions.ActionDescriptorOptions{
83+
Command: newEnvGetValueCmd(),
84+
FlagsResolver: newEnvGetValueFlags,
85+
ActionResolver: newEnvGetValueAction,
86+
})
87+
8288
return group
8389
}
8490

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

601+
func newEnvGetValueFlags(cmd *cobra.Command, global *internal.GlobalCommandOptions) *envGetValueFlags {
602+
flags := &envGetValueFlags{}
603+
flags.Bind(cmd.Flags(), global)
604+
605+
return flags
606+
}
607+
608+
func newEnvGetValueCmd() *cobra.Command {
609+
cmd := &cobra.Command{
610+
Use: "get-value <keyName>",
611+
Short: "Get specific environment value.",
612+
}
613+
cmd.Args = cobra.MaximumNArgs(1)
614+
615+
return cmd
616+
}
617+
618+
type envGetValueFlags struct {
619+
internal.EnvFlag
620+
global *internal.GlobalCommandOptions
621+
}
622+
623+
func (eg *envGetValueFlags) Bind(local *pflag.FlagSet, global *internal.GlobalCommandOptions) {
624+
eg.EnvFlag.Bind(local, global)
625+
eg.global = global
626+
}
627+
628+
type envGetValueAction struct {
629+
azdCtx *azdcontext.AzdContext
630+
console input.Console
631+
envManager environment.Manager
632+
writer io.Writer
633+
flags *envGetValueFlags
634+
args []string
635+
}
636+
637+
func newEnvGetValueAction(
638+
azdCtx *azdcontext.AzdContext,
639+
envManager environment.Manager,
640+
console input.Console,
641+
writer io.Writer,
642+
flags *envGetValueFlags,
643+
args []string,
644+
645+
) actions.Action {
646+
return &envGetValueAction{
647+
azdCtx: azdCtx,
648+
console: console,
649+
envManager: envManager,
650+
writer: writer,
651+
flags: flags,
652+
args: args,
653+
}
654+
}
655+
656+
func (eg *envGetValueAction) Run(ctx context.Context) (*actions.ActionResult, error) {
657+
if len(eg.args) < 1 {
658+
return nil, fmt.Errorf("no key name provided")
659+
}
660+
661+
keyName := eg.args[0]
662+
663+
name, err := eg.azdCtx.GetDefaultEnvironmentName()
664+
if err != nil {
665+
return nil, err
666+
}
667+
// Note: if there is not an environment yet, GetDefaultEnvironmentName() returns empty string (not error)
668+
// and later, when envManager.Get() is called with the empty string, azd returns an error.
669+
// But if there is already an environment (default to be selected), azd must honor the --environment flag
670+
// over the default environment.
671+
if eg.flags.EnvironmentName != "" {
672+
name = eg.flags.EnvironmentName
673+
}
674+
env, err := eg.envManager.Get(ctx, name)
675+
if errors.Is(err, environment.ErrNotFound) {
676+
return nil, fmt.Errorf(
677+
`environment '%s' does not exist. You can create it with "azd env new %s"`,
678+
name,
679+
name,
680+
)
681+
} else if err != nil {
682+
return nil, fmt.Errorf("ensuring environment exists: %w", err)
683+
}
684+
685+
values := env.Dotenv()
686+
keyValue, exists := values[keyName]
687+
if !exists {
688+
return nil, fmt.Errorf("key '%s' not found in the environment values", keyName)
689+
}
690+
691+
// Directly write the key value to the writer
692+
if _, err := fmt.Fprintln(eg.writer, keyValue); err != nil {
693+
return nil, fmt.Errorf("writing key value: %w", err)
694+
}
695+
696+
return nil, nil
697+
}
698+
595699
func getCmdEnvHelpDescription(*cobra.Command) string {
596700
return generateCmdHelpDescription(
597701
"Manage your application environments. With this command group, you can create a new environment or get, set,"+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
Get specific environment value.
3+
4+
Usage
5+
azd env get-value <keyName> [flags]
6+
7+
Flags
8+
--docs : Opens the documentation for azd env get-value in your web browser.
9+
-e, --environment string : The name of the environment to use.
10+
-h, --help : Gets help for get-value.
11+
12+
Global Flags
13+
-C, --cwd string : Sets the current working directory.
14+
--debug : Enables debugging and diagnostics logging.
15+
--no-prompt : Accepts the default value instead of prompting, or it fails if there is no default.
16+
17+
Find a bug? Want to let us know how we're doing? Fill out this brief survey: https://aka.ms/azure-dev/hats.
18+
19+

cli/azd/cmd/testdata/TestUsage-azd-env.snap

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Usage
1010
azd env [command]
1111

1212
Available Commands
13+
get-value : Get specific environment value.
1314
get-values : Get all environment values.
1415
list : List environments.
1516
new : Create a new environment and set it as the default.

cli/azd/test/functional/env_test.go

+53
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,59 @@ func Test_CLI_Env_Values_MultipleEnvironments(t *testing.T) {
260260
require.Equal(t, values["envName2"], envName2)
261261
}
262262

263+
func Test_CLI_Env_GetValue(t *testing.T) {
264+
ctx, cancel := newTestContext(t)
265+
defer cancel()
266+
267+
dir := tempDirWithDiagnostics(t)
268+
t.Logf("DIR: %s", dir)
269+
270+
cli := azdcli.NewCLI(t)
271+
cli.WorkingDirectory = dir
272+
273+
err := copySample(dir, "storage")
274+
require.NoError(t, err, "failed expanding sample")
275+
276+
// Create an environment
277+
envName := randomEnvName()
278+
envNew(ctx, t, cli, envName, false)
279+
280+
// Set key1
281+
envSetValue(ctx, t, cli, "key1", "value1")
282+
283+
// Get key1 value
284+
value := envGetValue(ctx, t, cli, "key1")
285+
require.Equal(t, "value1", value)
286+
287+
// Set key2
288+
envSetValue(ctx, t, cli, "key2", "value2")
289+
290+
// Get key2 value
291+
value = envGetValue(ctx, t, cli, "key2")
292+
require.Equal(t, "value2", value)
293+
294+
// Modify key1
295+
envSetValue(ctx, t, cli, "key1", "modified1")
296+
297+
// Get modified key1 value
298+
value = envGetValue(ctx, t, cli, "key1")
299+
require.Equal(t, "modified1", value)
300+
301+
// Test non-existent key
302+
res, err := cli.RunCommand(ctx, "env", "get-value", "non_existent_key")
303+
require.Error(t, err)
304+
require.Contains(t, res.Stdout, "key 'non_existent_key' not found in the environment values")
305+
}
306+
307+
func envGetValue(ctx context.Context, t *testing.T, cli *azdcli.CLI, key string) string {
308+
args := []string{"env", "get-value", key}
309+
310+
result, err := cli.RunCommand(ctx, args...)
311+
require.NoError(t, err)
312+
313+
return strings.TrimSpace(result.Stdout)
314+
}
315+
263316
func requireIsDefault(t *testing.T, list []contracts.EnvListEnvironment, envName string) {
264317
for _, env := range list {
265318
if env.Name == envName {

0 commit comments

Comments
 (0)