MCPcopy
hub / github.com/argoproj/argo-workflows / NewEmissaryCommand

Function NewEmissaryCommand

cmd/argoexec/commands/emissary.go:40–277  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

38)
39
40func NewEmissaryCommand() *cobra.Command {
41 return &cobra.Command{
42 Use: "emissary",
43 SilenceUsage: true, // this prevents confusing usage message being printed when we SIGTERM
44 RunE: func(cmd *cobra.Command, args []string) error {
45 exitCode := 64
46 ctx := cmd.Context()
47 logger := logging.RequireLoggerFromContext(ctx)
48
49 defer func() {
50 err := os.WriteFile(varRunArgo+"/ctr/"+containerName+"/exitcode", []byte(strconv.Itoa(exitCode)), 0o644)
51 if err != nil {
52 logger.WithError(err).Error(ctx, "failed to write exit code")
53 }
54 }()
55
56 osspecific.AllowGrantingAccessToEveryone()
57
58 // Dir permission set to rwxrwxrwx, so that non-root wait container can also write kill signal to the folder.
59 // Note it's important varRunArgo+"/ctr/" folder is writable by all, because multiple containers may want to
60 // write to it with different users.
61 // This also indicates we've started.
62 if err := os.MkdirAll(varRunArgo+"/ctr/"+containerName, 0o777); err != nil {
63 return fmt.Errorf("failed to create ctr directory: %w", err)
64 }
65
66 name, args := args[0], args[1:]
67
68 // Check if args were offloaded to a file (for large args that exceed exec limit)
69 if argsFile := os.Getenv(common.EnvVarContainerArgsFile); argsFile != "" {
70 logger.WithField("argsFile", argsFile).Info(ctx, "Reading container args from file")
71 argsData, err := os.ReadFile(argsFile)
72 if err != nil {
73 return fmt.Errorf("failed to read container args file %s: %w", argsFile, err)
74 }
75 var fileArgs []string
76 if err := json.Unmarshal(argsData, &fileArgs); err != nil {
77 return fmt.Errorf("failed to unmarshal container args: %w", err)
78 }
79 args = append(args, fileArgs...)
80 logger.WithField("count", len(fileArgs)).Info(ctx, "Loaded container args from file")
81
82 // Check for a large args and offload to file if needed
83 // This avoids the exec() "argument list too long" error
84 // Downstream programs should support @filename for parsing large args
85 for i := 0; i < len(args); i++ {
86 if len(args[i]) > common.MaxEnvVarLen {
87 filePath := fmt.Sprintf("/tmp/argo_arg_%d.txt", i)
88 if err := os.WriteFile(filePath, []byte(args[i]), 0o644); err != nil {
89 return fmt.Errorf("failed to write large arg %d to file: %w", i, err)
90 }
91 logger.WithFields(logging.Fields{
92 "argIndex": i,
93 "size": len(args[i]),
94 "filePath": filePath,
95 }).Info(ctx, "Offloaded large argument to file. Downstream program must support @filename syntax")
96 args[i] = "@" + filePath
97 }

Callers 3

runFunction · 0.85
runFunction · 0.85
NewRootCommandFunction · 0.85

Calls 15

RequireLoggerFromContextFunction · 0.92
NewExitErrFunction · 0.92
CanIgnoreSignalFunction · 0.92
KillFunction · 0.92
NewFunction · 0.92
WaitFunction · 0.92
startCommandFunction · 0.85
cancelFunction · 0.85
startFileSignalHandlerFunction · 0.85
saveParameterFunction · 0.85

Tested by 2

runFunction · 0.68
runFunction · 0.68