@@ -5,87 +5,88 @@ package commands
5
5
6
6
import (
7
7
"context"
8
- "flag"
9
8
"fmt"
10
- "io"
11
9
"os"
12
10
"os/exec"
13
11
"strings"
14
12
15
- "github.com/google/subcommands"
16
- "github.com/shoenig/envy/internal/keyring"
17
- "github.com/shoenig/envy/internal/output"
18
13
"github.com/shoenig/envy/internal/safe"
19
14
"github.com/shoenig/envy/internal/setup"
15
+ "noxide.lol/go/babycli"
20
16
)
21
17
22
- const (
23
- execCmdName = "exec"
24
- execCmdSynopsis = "Run command with environment variables from namespace."
25
- execCmdUsage = "exec [namespace] [command] <args, ...>"
26
-
27
- flagInsulate = "insulate"
28
- )
29
-
30
- func NewExecCmd (t * setup.Tool ) subcommands.Command {
31
- return & execCmd {
32
- writer : t .Writer ,
33
- ring : t .Ring ,
34
- box : t .Box ,
35
- execInputStd : os .Stdin ,
36
- execOutputStd : os .Stdout ,
37
- execOutputErr : os .Stderr ,
18
+ func newExecCmd (tool * setup.Tool ) * babycli.Component {
19
+ return & babycli.Component {
20
+ Name : "exec" ,
21
+ Help : "run a command using environment variables from profile" ,
22
+ Flags : babycli.Flags {
23
+ {
24
+ Type : babycli .BooleanFlag ,
25
+ Long : "insulate" ,
26
+ Short : "i" ,
27
+ Help : "disable child process from inheriting parent environment variables" ,
28
+ Default : & babycli.Default {
29
+ Value : false ,
30
+ Show : false ,
31
+ },
32
+ },
33
+ },
34
+ Function : func (c * babycli.Component ) babycli.Code {
35
+ if c .Nargs () < 2 {
36
+ tool .Writer .Errorf ("must specify profile and command argument(s)" )
37
+ return babycli .Failure
38
+ }
39
+
40
+ args := c .Arguments ()
41
+ p , err := tool .Box .Get (args [0 ])
42
+ if err != nil {
43
+ tool .Writer .Errorf ("unable to read profile: %v" , err )
44
+ return babycli .Failure
45
+ }
46
+
47
+ insulate := c .GetBool ("insulate" )
48
+ argVars , command , args := splitArgs (args [1 :])
49
+ cmd := newCmd (tool , p , insulate , argVars , command , args )
50
+
51
+ if err := cmd .Run (); err != nil {
52
+ tool .Writer .Errorf ("failed to exec: %v" , err )
53
+ return babycli .Failure
54
+ }
55
+
56
+ return babycli .Success
57
+ },
38
58
}
39
59
}
40
-
41
- type execCmd struct {
42
- writer output.Writer
43
- ring keyring.Ring
44
- box safe.Box
45
- execInputStd io.Reader
46
- execOutputStd io.Writer
47
- execOutputErr io.Writer
48
- }
49
-
50
- func (wc execCmd ) Name () string {
51
- return execCmdName
52
- }
53
-
54
- func (wc execCmd ) Synopsis () string {
55
- return execCmdSynopsis
56
- }
57
-
58
- func (wc execCmd ) Usage () string {
59
- return execCmdUsage
60
- }
61
-
62
- func (wc execCmd ) SetFlags (fs * flag.FlagSet ) {
63
- // no flags when running command through exec
64
- _ = fs .Bool (flagInsulate , false , "insulate will run command without passing through environment" )
65
- }
66
-
67
- func (wc execCmd ) Execute (_ context.Context , fs * flag.FlagSet , _ ... interface {}) subcommands.ExitStatus {
68
- insulate := fsBool (fs , flagInsulate )
69
-
70
- if len (fs .Args ()) < 2 {
71
- wc .writer .Errorf ("expected namespace and command argument(s)" )
72
- return subcommands .ExitUsageError
60
+ func env (tool * setup.Tool , ns * safe.Namespace , environment []string ) []string {
61
+ for key , value := range ns .Content {
62
+ secret := tool .Ring .Decrypt (value ).Unveil ()
63
+ environment = append (environment , fmt .Sprintf (
64
+ "%s=%s" , key , secret ,
65
+ ))
73
66
}
67
+ return environment
68
+ }
74
69
75
- ns , err := wc .box .Get (fs .Arg (0 ))
76
- if err != nil {
77
- wc .writer .Errorf ("could not retrieve namespace: %v" , err )
78
- return subcommands .ExitUsageError
70
+ func envContext (insulate bool ) []string {
71
+ if insulate {
72
+ return nil
79
73
}
74
+ return os .Environ ()
75
+ }
80
76
81
- argVars , command , args := splitArgs (fs .Args ()[1 :])
82
- cmd := wc .newCmd (ns , insulate , argVars , command , args )
83
- if err := cmd .Run (); err != nil {
84
- wc .writer .Errorf ("failed to exec: %v" , err )
85
- return subcommands .ExitFailure
86
- }
77
+ func newCmd (tool * setup.Tool , ns * safe.Namespace , insulate bool , argVars []string , command string , args []string ) * exec.Cmd {
78
+ ctx := context .Background ()
79
+ cmd := exec .CommandContext (ctx , command , args ... )
87
80
88
- return subcommands .ExitSuccess
81
+ // Environment variables are injected in the following order:
82
+ // 1. OS variables if insulate is false
83
+ // 2. envy namespace vars
84
+ // 3. Variables in input args
85
+ cmd .Env = append (env (tool , ns , envContext (insulate )), argVars ... )
86
+ cmd .Stdout = os .Stdout
87
+ cmd .Stderr = os .Stderr
88
+ cmd .Stdin = os .Stdin
89
+ return cmd
89
90
}
90
91
91
92
// splitArgs will split the list of flag.Args() into:
@@ -123,35 +124,3 @@ func splitArgs(flagArgs []string) (argVars []string, command string, commandArgs
123
124
124
125
return argVars , command , commandArgs
125
126
}
126
-
127
- func (wc execCmd ) newCmd (ns * safe.Namespace , insulate bool , argVars []string , command string , args []string ) * exec.Cmd {
128
- ctx := context .Background ()
129
- cmd := exec .CommandContext (ctx , command , args ... )
130
-
131
- // Environment variables are injected in the following order:
132
- // 1. OS variables if insulate is false
133
- // 2. envy namespace vars
134
- // 3. Variables in input args
135
- cmd .Env = append (wc .env (ns , envContext (insulate )), argVars ... )
136
- cmd .Stdout = wc .execOutputStd
137
- cmd .Stderr = wc .execOutputErr
138
- cmd .Stdin = wc .execInputStd
139
- return cmd
140
- }
141
-
142
- func envContext (insulate bool ) []string {
143
- if insulate {
144
- return nil
145
- }
146
- return os .Environ ()
147
- }
148
-
149
- func (wc execCmd ) env (ns * safe.Namespace , environment []string ) []string {
150
- for key , value := range ns .Content {
151
- secret := wc .ring .Decrypt (value ).Unveil ()
152
- environment = append (environment , fmt .Sprintf (
153
- "%s=%s" , key , secret ,
154
- ))
155
- }
156
- return environment
157
- }
0 commit comments