/
exec.go
141 lines (122 loc) · 5.55 KB
/
exec.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package exec
import (
"context"
"fmt"
"github.com/kurtosis-tech/kurtosis/api/golang/engine/kurtosis_engine_rpc_api_bindings"
"github.com/kurtosis-tech/kurtosis/api/golang/engine/lib/kurtosis_context"
"github.com/kurtosis-tech/kurtosis/cli/cli/command_framework/highlevel/enclave_id_arg"
"github.com/kurtosis-tech/kurtosis/cli/cli/command_framework/highlevel/engine_consuming_kurtosis_command"
"github.com/kurtosis-tech/kurtosis/cli/cli/command_framework/highlevel/service_identifier_arg"
"github.com/kurtosis-tech/kurtosis/cli/cli/command_framework/lowlevel/args"
"github.com/kurtosis-tech/kurtosis/cli/cli/command_framework/lowlevel/flags"
"github.com/kurtosis-tech/kurtosis/cli/cli/command_str_consts"
"github.com/kurtosis-tech/kurtosis/cli/cli/out"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/enclave"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
metrics_client "github.com/kurtosis-tech/metrics-library/golang/lib/client"
"github.com/kurtosis-tech/stacktrace"
)
const (
enclaveIdentifierArgKey = "enclave"
isEnclaveIdArgOptional = false
isEnclaveIdArgGreedy = false
serviceIdentifierArgKey = "service"
isServiceGuidArgOptional = false
isServiceGuidArgGreedy = false
execCommandArgKey = "command"
isExecCommandArgOptional = false
isExecCommandArgGreedy = false
kurtosisBackendCtxKey = "kurtosis-backend"
engineClientCtxKey = "engine-client"
binShCommand = "sh"
binShCommandFlag = "-c"
)
var ServiceShellCmd = &engine_consuming_kurtosis_command.EngineConsumingKurtosisCommand{
CommandStr: command_str_consts.ServiceExecCmdStr,
ShortDescription: "Executes a command in a service",
LongDescription: "Execute a command in a service. Note if the command being run is multiple words you should wrap it in quotes",
KurtosisBackendContextKey: kurtosisBackendCtxKey,
EngineClientContextKey: engineClientCtxKey,
Flags: []*flags.FlagConfig{},
Args: []*args.ArgConfig{
enclave_id_arg.NewEnclaveIdentifierArg(
enclaveIdentifierArgKey,
engineClientCtxKey,
isEnclaveIdArgOptional,
isEnclaveIdArgGreedy,
),
service_identifier_arg.NewServiceIdentifierArg(
serviceIdentifierArgKey,
enclaveIdentifierArgKey,
isServiceGuidArgOptional,
isServiceGuidArgGreedy,
),
{
Key: execCommandArgKey,
IsOptional: isExecCommandArgOptional,
IsGreedy: isExecCommandArgGreedy,
},
},
RunFunc: run,
}
func run(
ctx context.Context,
kurtosisBackend backend_interface.KurtosisBackend,
_ kurtosis_engine_rpc_api_bindings.EngineServiceClient,
_ metrics_client.MetricsClient,
flags *flags.ParsedFlags,
args *args.ParsedArgs,
) error {
enclaveIdentifier, err := args.GetNonGreedyArg(enclaveIdentifierArgKey)
if err != nil {
return stacktrace.Propagate(err, "An error occurred getting the enclave identifier using arg key '%v'", enclaveIdentifierArgKey)
}
serviceIdentifier, err := args.GetNonGreedyArg(serviceIdentifierArgKey)
if err != nil {
return stacktrace.Propagate(err, "An error occurred getting the service identifier using arg key '%v'", serviceIdentifierArgKey)
}
execCommandToRun, err := args.GetNonGreedyArg(execCommandArgKey)
if err != nil {
return stacktrace.Propagate(err, "An error occurred getting the exec command using arg key '%v'", execCommandArgKey)
}
kurtosisCtx, err := kurtosis_context.NewKurtosisContextFromLocalEngine()
if err != nil {
return stacktrace.Propagate(err, "An error occurred connecting to the local Kurtosis engine")
}
enclaveCtx, err := kurtosisCtx.GetEnclaveContext(ctx, enclaveIdentifier)
if err != nil {
return stacktrace.Propagate(err, "An error occurred while getting enclave context for enclave with identifier '%v' exists", enclaveIdentifier)
}
enclaveUuid := enclave.EnclaveUUID(enclaveCtx.GetEnclaveUuid())
serviceCtx, err := enclaveCtx.GetServiceContext(serviceIdentifier)
if err != nil {
return stacktrace.Propagate(err, "An error occurred while getting service context for service with identifier '%v'", serviceIdentifier)
}
serviceUuid := service.ServiceUUID(serviceCtx.GetServiceUUID())
results, resultErrors, err := kurtosisBackend.RunUserServiceExecCommands(ctx, enclaveUuid, map[service.ServiceUUID][]string{
serviceUuid: {
binShCommand,
binShCommandFlag,
execCommandToRun,
},
})
if err != nil {
return stacktrace.Propagate(err, "An error occurred executing command '%v' in user service with UUID '%v' in enclave '%v'",
execCommandToRun, serviceUuid, enclaveIdentifier)
}
if err, found := resultErrors[serviceUuid]; found {
return stacktrace.Propagate(err, "An error occurred executing command '%v' in user service with UUID '%v' in enclave '%v'",
execCommandToRun, serviceUuid, enclaveIdentifier)
}
successResult, found := results[serviceUuid]
if !found {
return stacktrace.NewError("The status of the command execution for '%s' in user service with UUID '%s' in enclave '%s' is unknown."+
" It wasn't returned neither as a success nor a failure. This is a bug in Kurtosis.", execCommandToRun, serviceUuid, enclaveIdentifier)
}
if successResult.GetExitCode() != 0 {
return stacktrace.NewError("The command was successfully executed but returned a non-zero exit code: '%d'. Output was:\n%v", successResult.GetExitCode(), successResult.GetOutput())
}
out.PrintOutLn(fmt.Sprintf("The command was successfully executed and returned '%d'. Output was:\n%v", successResult.GetExitCode(), successResult.GetOutput()))
return nil
}