From f9a436599a263cfc75e4b20f08d336b276d1f4fa Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 17 Oct 2018 10:40:38 +0100 Subject: [PATCH] client/llb: factor out `State.WithImageConfig` from `Image`. Currently if a caller wants an `Image` (with config applied) and the corresponding config (e.g. to use a base image and tailor the config to return as `exptypes.ExporterImageConfigKey` in the build result) then they have to `ResolveImageConfig` and then `llb.Image(..., llb.WithMetaResolver)`, which ends up resolving the config twice. Pulling this code out allows them to instead to the `config := ResolveImageConfig()` once and to then do `llb.Image(...).WithImageConfig(config)`. This is only really necessary if you want to run things in the image context (and thus want the config applied) as part of tailoring the config before returning the image and config. If you aren't running things on that `Image` as part of the build then it doesn't matter if the config isn't applied to the `Image` and `ResolveImageConfig` + `Image(...)` (without a metaresolver) is fine. Signed-off-by: Ian Campbell --- client/llb/source.go | 25 +++---------------------- client/llb/state.go | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/client/llb/source.go b/client/llb/source.go index ef03b19f..52d40be8 100644 --- a/client/llb/source.go +++ b/client/llb/source.go @@ -126,30 +126,11 @@ func Image(ref string, opts ...ImageOption) State { if err != nil { src.err = err } else { - var img struct { - Config struct { - Env []string `json:"Env,omitempty"` - WorkingDir string `json:"WorkingDir,omitempty"` - User string `json:"User,omitempty"` - } `json:"config,omitempty"` - } - if err := json.Unmarshal(dt, &img); err != nil { - src.err = err - } else { - st := NewState(src.Output()) - for _, env := range img.Config.Env { - parts := strings.SplitN(env, "=", 2) - if len(parts[0]) > 0 { - var v string - if len(parts) > 1 { - v = parts[1] - } - st = st.AddEnv(parts[0], v) - } - } - st = st.Dir(img.Config.WorkingDir) + st, err := NewState(src.Output()).WithImageConfig(dt) + if err == nil { return st } + src.err = err } } return NewState(src.Output()) diff --git a/client/llb/state.go b/client/llb/state.go index 15639fd3..24e3949b 100644 --- a/client/llb/state.go +++ b/client/llb/state.go @@ -2,8 +2,10 @@ package llb import ( "context" + "encoding/json" "fmt" "net" + "strings" "github.com/containerd/containerd/platforms" "github.com/moby/buildkit/identity" @@ -171,6 +173,31 @@ func (s State) WithOutput(o Output) State { return s } +func (s State) WithImageConfig(c []byte) (State, error) { + var img struct { + Config struct { + Env []string `json:"Env,omitempty"` + WorkingDir string `json:"WorkingDir,omitempty"` + User string `json:"User,omitempty"` + } `json:"config,omitempty"` + } + if err := json.Unmarshal(c, &img); err != nil { + return State{}, err + } + for _, env := range img.Config.Env { + parts := strings.SplitN(env, "=", 2) + if len(parts[0]) > 0 { + var v string + if len(parts) > 1 { + v = parts[1] + } + s = s.AddEnv(parts[0], v) + } + } + s = s.Dir(img.Config.WorkingDir) + return s, nil +} + func (s State) Run(ro ...RunOption) ExecState { ei := &ExecInfo{State: s} if p := s.GetPlatform(); p != nil {