From 966c4d4e14e9bb72b8e0257e948750d8b31ab27e Mon Sep 17 00:00:00 2001 From: Justin Chadwell Date: Tue, 20 Sep 2022 16:23:18 +0100 Subject: [PATCH] invoke: load defaults from image config If user does not specify image certain container parameters, we can load them from the exporter metadata. Additionally, we introduce a new "default" value for the --invoke flag, that keeps all of the default parameters (since cobra does not have an easy way of accepting an optional flag argument). Signed-off-by: Justin Chadwell --- build/build.go | 69 ++++++++++++++++++++++++++++++++++++++--------- commands/build.go | 25 +++++++---------- 2 files changed, 67 insertions(+), 27 deletions(-) diff --git a/build/build.go b/build/build.go index 5030de4d..bf3cdab5 100644 --- a/build/build.go +++ b/build/build.go @@ -640,14 +640,17 @@ func toSolveOpt(ctx context.Context, di DriverInfo, multiDriver bool, opt Option // ContainerConfig is configuration for a container to run. type ContainerConfig struct { ResultCtx *ResultContext - Args []string - Env []string - User string - Cwd string - Tty bool - Stdin io.ReadCloser - Stdout io.WriteCloser - Stderr io.WriteCloser + + Stdin io.ReadCloser + Stdout io.WriteCloser + Stderr io.WriteCloser + Tty bool + + Entrypoint []string + Cmd []string + Env []string + User *string + Cwd *string } // ResultContext is a build result with the client that built it. @@ -703,11 +706,53 @@ func Invoke(ctx context.Context, cfg ContainerConfig) error { } defer ctr.Release(context.TODO()) + imgData := res.Metadata[exptypes.ExporterImageConfigKey] + var img *specs.Image + if len(imgData) > 0 { + img = &specs.Image{} + if err := json.Unmarshal(imgData, img); err != nil { + fmt.Println(err) + return nil, err + } + } + + user := "" + if cfg.User != nil { + user = *cfg.User + } else if img != nil { + user = img.Config.User + } + + cwd := "" + if cfg.Cwd != nil { + cwd = *cfg.Cwd + } else if img != nil { + cwd = img.Config.WorkingDir + } + + env := []string{} + if img != nil { + env = append(env, img.Config.Env...) + } + env = append(env, cfg.Env...) + + args := []string{} + if cfg.Entrypoint != nil { + args = append(args, cfg.Entrypoint...) + } else if img != nil { + args = append(args, img.Config.Entrypoint...) + } + if cfg.Cmd != nil { + args = append(args, cfg.Cmd...) + } else if img != nil { + args = append(args, img.Config.Cmd...) + } + proc, err := ctr.Start(ctx, gateway.StartRequest{ - Args: cfg.Args, - Env: cfg.Env, - User: cfg.User, - Cwd: cfg.Cwd, + Args: args, + Env: env, + User: user, + Cwd: cwd, Tty: cfg.Tty, Stdin: cfg.Stdin, Stdout: cfg.Stdout, diff --git a/commands/build.go b/commands/build.go index 6145d445..83d9806c 100644 --- a/commands/build.go +++ b/commands/build.go @@ -326,18 +326,20 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]bu } func parseInvokeConfig(invoke string) (cfg build.ContainerConfig, err error) { + cfg.Tty = true + if invoke == "default" { + return cfg, nil + } + csvReader := csv.NewReader(strings.NewReader(invoke)) fields, err := csvReader.Read() if err != nil { return cfg, err } - cfg.Tty = true if len(fields) == 1 && !strings.Contains(fields[0], "=") { - cfg.Args = []string{fields[0]} + cfg.Cmd = []string{fields[0]} return cfg, nil } - var entrypoint string - var args []string for _, field := range fields { parts := strings.SplitN(field, "=", 2) if len(parts) != 2 { @@ -347,15 +349,15 @@ func parseInvokeConfig(invoke string) (cfg build.ContainerConfig, err error) { value := parts[1] switch key { case "args": - args = append(args, value) // TODO: support JSON + cfg.Cmd = append(cfg.Cmd, value) // TODO: support JSON case "entrypoint": - entrypoint = value // TODO: support JSON + cfg.Entrypoint = append(cfg.Entrypoint, value) // TODO: support JSON case "env": cfg.Env = append(cfg.Env, value) case "user": - cfg.User = value + cfg.User = &value case "cwd": - cfg.Cwd = value + cfg.Cwd = &value case "tty": cfg.Tty, err = strconv.ParseBool(value) if err != nil { @@ -365,13 +367,6 @@ func parseInvokeConfig(invoke string) (cfg build.ContainerConfig, err error) { return cfg, errors.Errorf("unknown key %q", key) } } - cfg.Args = args - if entrypoint != "" { - cfg.Args = append([]string{entrypoint}, cfg.Args...) - } - if len(cfg.Args) == 0 { - cfg.Args = []string{"sh"} - } return cfg, nil }