diff --git a/bake/bake.go b/bake/bake.go index 8322edbb3ae..6f72fb88f07 100644 --- a/bake/bake.go +++ b/bake/bake.go @@ -194,7 +194,7 @@ func ListTargets(files []File) ([]string, error) { return dedupSlice(targets), nil } -func ReadTargets(ctx context.Context, files []File, targets, overrides []string, defaults map[string]string) (map[string]*Target, map[string]*Group, error) { +func ReadTargets(ctx context.Context, files []File, targets, overrides []string, defaults map[string]string, ent *EntitlementConf) (map[string]*Target, map[string]*Group, error) { c, _, err := ParseFiles(files, defaults) if err != nil { return nil, nil, err @@ -213,7 +213,7 @@ func ReadTargets(ctx context.Context, files []File, targets, overrides []string, for _, target := range targets { ts, gs := c.ResolveGroup(target) for _, tname := range ts { - t, err := c.ResolveTarget(tname, o) + t, err := c.ResolveTarget(tname, o, ent) if err != nil { return nil, nil, err } @@ -245,7 +245,7 @@ func ReadTargets(ctx context.Context, files []File, targets, overrides []string, } for name, t := range m { - if err := c.loadLinks(name, t, m, o, nil); err != nil { + if err := c.loadLinks(name, t, m, o, nil, ent); err != nil { return nil, nil, err } } @@ -477,7 +477,7 @@ func (c Config) expandTargets(pattern string) ([]string, error) { return names, nil } -func (c Config) loadLinks(name string, t *Target, m map[string]*Target, o map[string]map[string]Override, visited []string) error { +func (c Config) loadLinks(name string, t *Target, m map[string]*Target, o map[string]map[string]Override, visited []string, ent *EntitlementConf) error { visited = append(visited, name) for _, v := range t.Contexts { if strings.HasPrefix(v, "target:") { @@ -493,7 +493,7 @@ func (c Config) loadLinks(name string, t *Target, m map[string]*Target, o map[st t2, ok := m[target] if !ok { var err error - t2, err = c.ResolveTarget(target, o) + t2, err = c.ResolveTarget(target, o, ent) if err != nil { return err } @@ -503,7 +503,7 @@ func (c Config) loadLinks(name string, t *Target, m map[string]*Target, o map[st t2.linked = true m[target] = t2 } - if err := c.loadLinks(target, t2, m, o, visited); err != nil { + if err := c.loadLinks(target, t2, m, o, visited, ent); err != nil { return err } @@ -630,8 +630,8 @@ func (c Config) group(name string, visited map[string]visit) ([]string, []string return targets, groups } -func (c Config) ResolveTarget(name string, overrides map[string]map[string]Override) (*Target, error) { - t, err := c.target(name, map[string]*Target{}, overrides) +func (c Config) ResolveTarget(name string, overrides map[string]map[string]Override, ent *EntitlementConf) (*Target, error) { + t, err := c.target(name, map[string]*Target{}, overrides, ent) if err != nil { return nil, err } @@ -647,7 +647,7 @@ func (c Config) ResolveTarget(name string, overrides map[string]map[string]Overr return t, nil } -func (c Config) target(name string, visited map[string]*Target, overrides map[string]map[string]Override) (*Target, error) { +func (c Config) target(name string, visited map[string]*Target, overrides map[string]map[string]Override, ent *EntitlementConf) (*Target, error) { if t, ok := visited[name]; ok { return t, nil } @@ -664,7 +664,7 @@ func (c Config) target(name string, visited map[string]*Target, overrides map[st } tt := &Target{} for _, name := range t.Inherits { - t, err := c.target(name, visited, overrides) + t, err := c.target(name, visited, overrides, ent) if err != nil { return nil, err } @@ -676,7 +676,7 @@ func (c Config) target(name string, visited map[string]*Target, overrides map[st m.Merge(tt) m.Merge(t) tt = m - if err := tt.AddOverrides(overrides[name]); err != nil { + if err := tt.AddOverrides(overrides[name], ent); err != nil { return nil, err } tt.normalize() @@ -859,7 +859,7 @@ func (t *Target) Merge(t2 *Target) { t.Inherits = append(t.Inherits, t2.Inherits...) } -func (t *Target) AddOverrides(overrides map[string]Override) error { +func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementConf) error { for key, o := range overrides { value := o.Value keys := strings.SplitN(key, ".", 2) @@ -900,12 +900,26 @@ func (t *Target) AddOverrides(overrides map[string]Override) error { return err } t.CacheFrom = cacheFrom + for _, c := range t.CacheFrom { + if c.Type == "local" { + if v, ok := c.Attrs["src"]; ok { + ent.FSRead = append(ent.FSRead, v) + } + } + } case "cache-to": cacheTo, err := parseCacheArrValues(o.ArrValue) if err != nil { return err } t.CacheTo = cacheTo + for _, c := range t.CacheTo { + if c.Type == "local" { + if v, ok := c.Attrs["dest"]; ok { + ent.FSWrite = append(ent.FSWrite, v) + } + } + } case "target": t.Target = &value case "call": @@ -916,12 +930,20 @@ func (t *Target) AddOverrides(overrides map[string]Override) error { return errors.Wrap(err, "invalid value for outputs") } t.Secrets = secrets + for _, s := range t.Secrets { + if s.FilePath != "" { + ent.FSRead = append(ent.FSRead, s.FilePath) + } + } case "ssh": ssh, err := parseArrValue[buildflags.SSH](o.ArrValue) if err != nil { return errors.Wrap(err, "invalid value for outputs") } t.SSH = ssh + for _, s := range t.SSH { + ent.FSRead = append(ent.FSRead, s.Paths...) + } case "platform": t.Platforms = o.ArrValue case "output": @@ -930,8 +952,20 @@ func (t *Target) AddOverrides(overrides map[string]Override) error { return errors.Wrap(err, "invalid value for outputs") } t.Outputs = outputs + for _, o := range t.Outputs { + if o.Destination != "" { + ent.FSWrite = append(ent.FSWrite, o.Destination) + } + } case "entitlements": t.Entitlements = append(t.Entitlements, o.ArrValue...) + for _, v := range o.ArrValue { + if v == string(EntitlementKeyNetworkHost) { + ent.NetworkHost = true + } else if v == string(EntitlementKeySecurityInsecure) { + ent.SecurityInsecure = true + } + } case "annotations": t.Annotations = append(t.Annotations, o.ArrValue...) case "attest": @@ -1355,7 +1389,7 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) { outputs[i] = output.ToPB() } - bo.Exports, err = controllerapi.CreateExports(outputs) + bo.Exports, bo.ExportsLocalPathsTemporary, err = controllerapi.CreateExports(outputs) if err != nil { return nil, err } diff --git a/bake/bake_test.go b/bake/bake_test.go index b61e2ecff3e..0abc35ed1ad 100644 --- a/bake/bake_test.go +++ b/bake/bake_test.go @@ -41,7 +41,7 @@ target "webapp" { t.Run("NoOverrides", func(t *testing.T) { t.Parallel() - m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m)) @@ -59,7 +59,7 @@ target "webapp" { t.Run("InvalidTargetOverrides", func(t *testing.T) { t.Parallel() - _, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"nosuchtarget.context=foo"}, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"nosuchtarget.context=foo"}, nil, &EntitlementConf{}) require.Error(t, err) require.Equal(t, "could not find any target matching 'nosuchtarget'", err.Error()) }) @@ -75,7 +75,7 @@ target "webapp" { "webapp.args.VAR_FROMENV" + t.Name(), "webapp.args.VAR_INHERITED=override", // not overriding VAR_BOTH on purpose - }, nil) + }, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, "Dockerfile.webapp", *m["webapp"].Dockerfile) @@ -104,7 +104,7 @@ target "webapp" { m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{ "webDEP.args.VAR_INHERITED=override", "webDEP.args.VAR_BOTH=override", - }, nil) + }, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, ptrstr("override"), m["webapp"].Args["VAR_INHERITED"]) @@ -116,10 +116,10 @@ target "webapp" { t.Run("ContextOverride", func(t *testing.T) { t.Parallel() - _, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context"}, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context"}, nil, &EntitlementConf{}) require.Error(t, err) - m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context=foo"}, nil) + m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context=foo"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, "foo", *m["webapp"].Context) require.Equal(t, 1, len(g)) @@ -128,7 +128,7 @@ target "webapp" { t.Run("NoCacheOverride", func(t *testing.T) { t.Parallel() - m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.no-cache=false"}, nil) + m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.no-cache=false"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, false, *m["webapp"].NoCache) require.Equal(t, 1, len(g)) @@ -136,14 +136,14 @@ target "webapp" { }) t.Run("ShmSizeOverride", func(t *testing.T) { - m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.shm-size=256m"}, nil) + m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.shm-size=256m"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, "256m", *m["webapp"].ShmSize) }) t.Run("PullOverride", func(t *testing.T) { t.Parallel() - m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.pull=false"}, nil) + m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.pull=false"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, false, *m["webapp"].Pull) require.Equal(t, 1, len(g)) @@ -211,7 +211,7 @@ target "webapp" { } for _, test := range cases { t.Run(test.name, func(t *testing.T) { - m, g, err := ReadTargets(ctx, []File{fp}, test.targets, test.overrides, nil) + m, g, err := ReadTargets(ctx, []File{fp}, test.targets, test.overrides, nil, &EntitlementConf{}) test.check(t, m, g, err) }) } @@ -226,7 +226,7 @@ func TestPushOverride(t *testing.T) { `target "app" { }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, "type=image,push=true", m["app"].Outputs[0].String()) @@ -240,7 +240,7 @@ func TestPushOverride(t *testing.T) { output = ["type=image,compression=zstd"] }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, "type=image,compression=zstd,push=true", m["app"].Outputs[0].String()) @@ -254,7 +254,7 @@ func TestPushOverride(t *testing.T) { output = ["type=image,compression=zstd"] }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=false"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=false"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, "type=image,compression=zstd,push=false", m["app"].Outputs[0].String()) @@ -268,7 +268,7 @@ func TestPushOverride(t *testing.T) { output = ["type=registry"] }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, "type=registry", m["app"].Outputs[0].String()) @@ -282,7 +282,7 @@ func TestPushOverride(t *testing.T) { output = ["type=registry"] }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=false"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.push=false"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 0, len(m["app"].Outputs)) }) @@ -297,7 +297,7 @@ func TestPushOverride(t *testing.T) { target "bar" { }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo", "bar"}, []string{"*.push=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo", "bar"}, []string{"*.push=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(m)) require.Equal(t, 1, len(m["foo"].Outputs)) @@ -315,7 +315,7 @@ func TestLoadOverride(t *testing.T) { `target "app" { }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, "type=docker", m["app"].Outputs[0].String()) @@ -329,7 +329,7 @@ func TestLoadOverride(t *testing.T) { output = ["type=docker"] }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, []string{"type=docker"}, stringify(m["app"].Outputs)) @@ -343,7 +343,7 @@ func TestLoadOverride(t *testing.T) { output = ["type=image"] }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(m["app"].Outputs)) require.Equal(t, []string{"type=docker", "type=image"}, stringify(m["app"].Outputs)) @@ -357,7 +357,7 @@ func TestLoadOverride(t *testing.T) { output = ["type=image"] }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=false"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=false"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m["app"].Outputs)) require.Equal(t, []string{"type=image"}, stringify(m["app"].Outputs)) @@ -371,7 +371,7 @@ func TestLoadOverride(t *testing.T) { output = ["type=registry"] }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(m["app"].Outputs)) require.Equal(t, []string{"type=docker", "type=registry"}, stringify(m["app"].Outputs)) @@ -385,7 +385,7 @@ func TestLoadOverride(t *testing.T) { output = ["type=oci,dest=out"] }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(m["app"].Outputs)) require.Equal(t, []string{"type=docker", "type=oci,dest=out"}, stringify(m["app"].Outputs)) @@ -399,7 +399,7 @@ func TestLoadOverride(t *testing.T) { output = ["type=docker,dest=out"] }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{"*.load=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(m["app"].Outputs)) require.Equal(t, []string{"type=docker", "type=docker,dest=out"}, stringify(m["app"].Outputs)) @@ -415,7 +415,7 @@ func TestLoadOverride(t *testing.T) { target "bar" { }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo", "bar"}, []string{"*.load=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo", "bar"}, []string{"*.load=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(m)) require.Equal(t, 1, len(m["foo"].Outputs)) @@ -436,7 +436,7 @@ func TestLoadAndPushOverride(t *testing.T) { target "bar" { }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo", "bar"}, []string{"*.load=true", "*.push=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo", "bar"}, []string{"*.load=true", "*.push=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(m)) @@ -455,7 +455,7 @@ func TestLoadAndPushOverride(t *testing.T) { output = [ "type=registry" ] }`), } - m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo"}, []string{"*.load=true", "*.push=true"}, nil) + m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"foo"}, []string{"*.load=true", "*.push=true"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m)) @@ -510,7 +510,7 @@ services: ctx := context.TODO() - m, g, err := ReadTargets(ctx, []File{fp, fp2, fp3}, []string{"default"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{fp, fp2, fp3}, []string{"default"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 3, len(m)) @@ -557,7 +557,7 @@ services: ctx := context.TODO() - m, _, err := ReadTargets(ctx, []File{fp}, []string{"web.app"}, nil, nil) + m, _, err := ReadTargets(ctx, []File{fp}, []string{"web.app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m)) _, ok := m["web_app"] @@ -565,7 +565,7 @@ services: require.Equal(t, "Dockerfile.webapp", *m["web_app"].Dockerfile) require.Equal(t, ptrstr("1"), m["web_app"].Args["buildno"]) - m, _, err = ReadTargets(ctx, []File{fp2}, []string{"web_app"}, nil, nil) + m, _, err = ReadTargets(ctx, []File{fp2}, []string{"web_app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m)) _, ok = m["web_app"] @@ -573,7 +573,7 @@ services: require.Equal(t, "Dockerfile", *m["web_app"].Dockerfile) require.Equal(t, ptrstr("12"), m["web_app"].Args["buildno2"]) - m, g, err := ReadTargets(ctx, []File{fp, fp2}, []string{"default"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{fp, fp2}, []string{"default"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m)) _, ok = m["web_app"] @@ -598,7 +598,7 @@ func TestHCLContextCwdPrefix(t *testing.T) { }`), } ctx := context.TODO() - m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) bo, err := TargetsToBuildOpt(m, &Input{}) @@ -629,7 +629,7 @@ func TestHCLDockerfileCwdPrefix(t *testing.T) { cwd, err := os.Getwd() require.NoError(t, err) - m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) bo, err := TargetsToBuildOpt(m, &Input{}) @@ -660,7 +660,7 @@ func TestOverrideMerge(t *testing.T) { "app.platform=linux/arm", "app.platform=linux/ppc64le", "app.output=type=registry", - }, nil) + }, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m)) @@ -695,7 +695,7 @@ func TestReadContexts(t *testing.T) { } ctx := context.TODO() - m, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil) + m, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m)) @@ -711,7 +711,7 @@ func TestReadContexts(t *testing.T) { require.Equal(t, "baz", ctxs["foo"].Path) require.Equal(t, "def", ctxs["abc"].Path) - m, _, err = ReadTargets(ctx, []File{fp}, []string{"app"}, []string{"app.contexts.foo=bay", "base.contexts.ghi=jkl"}, nil) + m, _, err = ReadTargets(ctx, []File{fp}, []string{"app"}, []string{"app.contexts.foo=bay", "base.contexts.ghi=jkl"}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m)) @@ -729,7 +729,7 @@ func TestReadContexts(t *testing.T) { require.Equal(t, "jkl", ctxs["ghi"].Path) // test resetting base values - m, _, err = ReadTargets(ctx, []File{fp}, []string{"app"}, []string{"app.contexts.foo="}, nil) + m, _, err = ReadTargets(ctx, []File{fp}, []string{"app"}, []string{"app.contexts.foo="}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m)) @@ -764,7 +764,7 @@ func TestReadContextFromTargetUnknown(t *testing.T) { } ctx := context.TODO() - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil, &EntitlementConf{}) require.Error(t, err) require.Contains(t, err.Error(), "failed to find target bar") } @@ -788,7 +788,7 @@ services: ctx := context.TODO() - m, _, err := ReadTargets(ctx, []File{fp, fp2}, []string{"app1", "app2"}, nil, nil) + m, _, err := ReadTargets(ctx, []File{fp, fp2}, []string{"app1", "app2"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(m)) @@ -826,7 +826,7 @@ func TestReadContextFromTargetChain(t *testing.T) { `), } - m, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil) + m, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 3, len(m)) @@ -865,7 +865,7 @@ func TestReadContextFromTargetInfiniteLoop(t *testing.T) { } `), } - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app", "mid"}, []string{}, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app", "mid"}, []string{}, nil, &EntitlementConf{}) require.Error(t, err) require.Contains(t, err.Error(), "infinite loop from") } @@ -887,7 +887,7 @@ func TestReadContextFromTargetMultiPlatform(t *testing.T) { } `), } - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil, &EntitlementConf{}) require.NoError(t, err) } @@ -908,7 +908,7 @@ func TestReadContextFromTargetInvalidPlatforms(t *testing.T) { } `), } - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{}, nil, &EntitlementConf{}) require.Error(t, err) require.Contains(t, err.Error(), "defined for different platforms") } @@ -925,7 +925,7 @@ target "default" { }`), } - m, g, err := ReadTargets(ctx, []File{f}, []string{"default"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{f}, []string{"default"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 0, len(g)) require.Equal(t, 1, len(m)) @@ -944,10 +944,10 @@ target "image" { }`), } - _, _, err := ReadTargets(ctx, []File{f}, []string{"default"}, nil, nil) + _, _, err := ReadTargets(ctx, []File{f}, []string{"default"}, nil, nil, &EntitlementConf{}) require.Error(t, err) - m, g, err := ReadTargets(ctx, []File{f}, []string{"image"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{f}, []string{"image"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(g)) require.Equal(t, []string{"image"}, g["default"].Targets) @@ -970,7 +970,7 @@ target "image" { }`), } - m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(g)) require.Equal(t, []string{"foo"}, g["default"].Targets) @@ -997,7 +997,7 @@ target "image" { }`), } - m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(g)) require.Equal(t, []string{"foo"}, g["default"].Targets) @@ -1005,7 +1005,7 @@ target "image" { require.Equal(t, 1, len(m)) require.Equal(t, "test", *m["image"].Dockerfile) - m, g, err = ReadTargets(ctx, []File{f}, []string{"foo", "foo"}, nil, nil) + m, g, err = ReadTargets(ctx, []File{f}, []string{"foo", "foo"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(g)) require.Equal(t, []string{"foo"}, g["default"].Targets) @@ -1088,7 +1088,7 @@ services: }`), } - m, g, err := ReadTargets(ctx, []File{fhcl}, []string{"default"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{fhcl}, []string{"default"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(g)) require.Equal(t, []string{"image"}, g["default"].Targets) @@ -1096,7 +1096,7 @@ services: require.Equal(t, 1, len(m["image"].Outputs)) require.Equal(t, "type=docker", m["image"].Outputs[0].String()) - m, g, err = ReadTargets(ctx, []File{fhcl}, []string{"image-release"}, nil, nil) + m, g, err = ReadTargets(ctx, []File{fhcl}, []string{"image-release"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(g)) require.Equal(t, []string{"image-release"}, g["default"].Targets) @@ -1104,7 +1104,7 @@ services: require.Equal(t, 1, len(m["image-release"].Outputs)) require.Equal(t, "type=image,push=true", m["image-release"].Outputs[0].String()) - m, g, err = ReadTargets(ctx, []File{fhcl}, []string{"image", "image-release"}, nil, nil) + m, g, err = ReadTargets(ctx, []File{fhcl}, []string{"image", "image-release"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(g)) require.Equal(t, []string{"image", "image-release"}, g["default"].Targets) @@ -1113,21 +1113,21 @@ services: require.Equal(t, 1, len(m["image-release"].Outputs)) require.Equal(t, "type=image,push=true", m["image-release"].Outputs[0].String()) - m, g, err = ReadTargets(ctx, []File{fyml, fhcl}, []string{"default"}, nil, nil) + m, g, err = ReadTargets(ctx, []File{fyml, fhcl}, []string{"default"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(g)) require.Equal(t, []string{"image"}, g["default"].Targets) require.Equal(t, 1, len(m)) require.Equal(t, ".", *m["image"].Context) - m, g, err = ReadTargets(ctx, []File{fjson}, []string{"default"}, nil, nil) + m, g, err = ReadTargets(ctx, []File{fjson}, []string{"default"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(g)) require.Equal(t, []string{"image"}, g["default"].Targets) require.Equal(t, 1, len(m)) require.Equal(t, ".", *m["image"].Context) - m, g, err = ReadTargets(ctx, []File{fyml}, []string{"default"}, nil, nil) + m, g, err = ReadTargets(ctx, []File{fyml}, []string{"default"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(g)) sort.Strings(g["default"].Targets) @@ -1136,7 +1136,7 @@ services: require.Equal(t, "./Dockerfile", *m["addon"].Dockerfile) require.Equal(t, "./aws.Dockerfile", *m["aws"].Dockerfile) - m, g, err = ReadTargets(ctx, []File{fyml, fhcl}, []string{"addon", "aws"}, nil, nil) + m, g, err = ReadTargets(ctx, []File{fyml, fhcl}, []string{"addon", "aws"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(g)) sort.Strings(g["default"].Targets) @@ -1145,7 +1145,7 @@ services: require.Equal(t, "./Dockerfile", *m["addon"].Dockerfile) require.Equal(t, "./aws.Dockerfile", *m["aws"].Dockerfile) - m, g, err = ReadTargets(ctx, []File{fyml, fhcl}, []string{"addon", "aws", "image"}, nil, nil) + m, g, err = ReadTargets(ctx, []File{fyml, fhcl}, []string{"addon", "aws", "image"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(g)) sort.Strings(g["default"].Targets) @@ -1174,7 +1174,7 @@ target "image" { }`), } - m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(g)) require.Equal(t, []string{"foo"}, g["default"].Targets) @@ -1182,7 +1182,7 @@ target "image" { require.Equal(t, 1, len(m)) require.Equal(t, "bar", *m["foo"].Dockerfile) - m, g, err = ReadTargets(ctx, []File{f}, []string{"foo", "foo"}, nil, nil) + m, g, err = ReadTargets(ctx, []File{f}, []string{"foo", "foo"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(g)) require.Equal(t, []string{"foo"}, g["default"].Targets) @@ -1209,7 +1209,7 @@ target "image" { }`), } - m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{f}, []string{"foo"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(g)) require.Equal(t, []string{"foo"}, g["default"].Targets) @@ -1218,7 +1218,7 @@ target "image" { require.Equal(t, "bar", *m["foo"].Dockerfile) require.Equal(t, "type=docker", m["image"].Outputs[0].String()) - m, g, err = ReadTargets(ctx, []File{f}, []string{"foo", "image"}, nil, nil) + m, g, err = ReadTargets(ctx, []File{f}, []string{"foo", "image"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 2, len(g)) require.Equal(t, []string{"foo", "image"}, g["default"].Targets) @@ -1281,7 +1281,7 @@ target "d" { for _, tt := range cases { tt := tt t.Run(tt.name, func(t *testing.T) { - m, g, err := ReadTargets(ctx, []File{f}, []string{"d"}, tt.overrides, nil) + m, g, err := ReadTargets(ctx, []File{f}, []string{"d"}, tt.overrides, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(g)) require.Equal(t, []string{"d"}, g["default"].Targets) @@ -1354,7 +1354,7 @@ group "default" { for _, tt := range cases { tt := tt t.Run(tt.name, func(t *testing.T) { - m, g, err := ReadTargets(ctx, []File{f}, []string{"default"}, tt.overrides, nil) + m, g, err := ReadTargets(ctx, []File{f}, []string{"default"}, tt.overrides, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(g)) require.Equal(t, []string{"child1", "child2"}, g["default"].Targets) @@ -1412,7 +1412,7 @@ func TestTargetName(t *testing.T) { _, _, err := ReadTargets(ctx, []File{{ Name: "docker-bake.hcl", Data: []byte(`target "` + tt.target + `" {}`), - }}, []string{tt.target}, nil, nil) + }}, []string{tt.target}, nil, nil, &EntitlementConf{}) if tt.wantErr { require.Error(t, err) } else { @@ -1500,7 +1500,7 @@ target "f" { for _, tt := range cases { tt := tt t.Run(strings.Join(tt.names, "+"), func(t *testing.T) { - m, g, err := ReadTargets(ctx, []File{f}, tt.names, nil, nil) + m, g, err := ReadTargets(ctx, []File{f}, tt.names, nil, nil, &EntitlementConf{}) require.NoError(t, err) var gnames []string @@ -1577,7 +1577,7 @@ func TestHCLNullVars(t *testing.T) { } ctx := context.TODO() - m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil) + m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m)) @@ -1612,7 +1612,7 @@ func TestJSONNullVars(t *testing.T) { } ctx := context.TODO() - m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil) + m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) require.Equal(t, 1, len(m)) @@ -1687,7 +1687,7 @@ func TestAttestDuplicates(t *testing.T) { } ctx := context.TODO() - m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil) + m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil, &EntitlementConf{}) require.Equal(t, []string{"type=sbom,foo=bar", "type=provenance,mode=max"}, m["default"].Attest) require.NoError(t, err) @@ -1698,7 +1698,7 @@ func TestAttestDuplicates(t *testing.T) { "provenance": ptrstr("type=provenance,mode=max"), }, opts["default"].Attests) - m, _, err = ReadTargets(ctx, []File{fp}, []string{"default"}, []string{"*.attest=type=sbom,disabled=true"}, nil) + m, _, err = ReadTargets(ctx, []File{fp}, []string{"default"}, []string{"*.attest=type=sbom,disabled=true"}, nil, &EntitlementConf{}) require.Equal(t, []string{"type=sbom,disabled=true", "type=provenance,mode=max"}, m["default"].Attest) require.NoError(t, err) @@ -1720,7 +1720,7 @@ func TestAnnotations(t *testing.T) { }`), } ctx := context.TODO() - m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) bo, err := TargetsToBuildOpt(m, &Input{}) @@ -1747,7 +1747,7 @@ func TestHCLEntitlements(t *testing.T) { }`), } ctx := context.TODO() - m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) bo, err := TargetsToBuildOpt(m, &Input{}) @@ -1787,7 +1787,7 @@ func TestEntitlementsForNetHostCompose(t *testing.T) { } ctx := context.TODO() - m, g, err := ReadTargets(ctx, []File{fp, fp2}, []string{"app"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{fp, fp2}, []string{"app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) bo, err := TargetsToBuildOpt(m, &Input{}) @@ -1818,7 +1818,7 @@ func TestEntitlementsForNetHost(t *testing.T) { } ctx := context.TODO() - m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) bo, err := TargetsToBuildOpt(m, &Input{}) @@ -1849,7 +1849,7 @@ func TestNetNone(t *testing.T) { } ctx := context.TODO() - m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) bo, err := TargetsToBuildOpt(m, &Input{}) @@ -1889,12 +1889,12 @@ target "app" { t.Run("Valid", func(t *testing.T) { t.Setenv("FOO", "bar") - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) }) t.Run("Invalid", func(t *testing.T) { - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.Error(t, err) require.Contains(t, err.Error(), "FOO is required.") }) @@ -1926,19 +1926,19 @@ target "app" { t.Run("Valid", func(t *testing.T) { t.Setenv("FOO", "barbar") - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) }) t.Run("InvalidLength", func(t *testing.T) { t.Setenv("FOO", "bar") - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.Error(t, err) require.Contains(t, err.Error(), "FOO must be longer than 4 characters.") }) t.Run("InvalidEmpty", func(t *testing.T) { - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.Error(t, err) require.Contains(t, err.Error(), "FOO is required.") }) @@ -1967,19 +1967,19 @@ target "app" { t.Run("Valid", func(t *testing.T) { t.Setenv("FOO", "bar") - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) }) t.Run("SetBar", func(t *testing.T) { t.Setenv("FOO", "bar") t.Setenv("BAR", "baz") - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) }) t.Run("Invalid", func(t *testing.T) { - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.Error(t, err) require.Contains(t, err.Error(), "BAR requires FOO to be set.") }) @@ -2008,12 +2008,12 @@ target "app" { t.Run("Valid", func(t *testing.T) { t.Setenv("FOO", "10") - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.NoError(t, err) }) t.Run("Invalid", func(t *testing.T) { - _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + _, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{}) require.Error(t, err) require.Contains(t, err.Error(), "FOO must be greater than 5.") }) diff --git a/bake/entitlements.go b/bake/entitlements.go index b7160481894..116051ff1a8 100644 --- a/bake/entitlements.go +++ b/bake/entitlements.go @@ -113,17 +113,8 @@ func (c EntitlementConf) check(bo build.Options, expected *EntitlementConf) erro roPaths[p] = struct{}{} } - for _, out := range bo.Exports { - if out.Type == "local" { - if dest, ok := out.Attrs["dest"]; ok { - rwPaths[dest] = struct{}{} - } - } - if out.Type == "tar" { - if dest, ok := out.Attrs["dest"]; ok && dest != "-" { - rwPaths[dest] = struct{}{} - } - } + for _, p := range bo.ExportsLocalPathsTemporary { + rwPaths[p] = struct{}{} } for _, ce := range bo.CacheTo { diff --git a/bake/entitlements_test.go b/bake/entitlements_test.go index 16cd8bc6c3a..ef1bbdec85e 100644 --- a/bake/entitlements_test.go +++ b/bake/entitlements_test.go @@ -10,7 +10,6 @@ import ( "github.com/docker/buildx/build" "github.com/docker/buildx/controller/pb" "github.com/docker/buildx/util/osutil" - "github.com/moby/buildkit/client" "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/util/entitlements" "github.com/stretchr/testify/require" @@ -279,25 +278,10 @@ func TestValidateEntitlements(t *testing.T) { { name: "ExportLocal", opt: build.Options{ - Exports: []client.ExportEntry{ - { - Type: "local", - Attrs: map[string]string{ - "dest": dir1, - }, - }, - { - Type: "local", - Attrs: map[string]string{ - "dest": filepath.Join(dir1, "subdir"), - }, - }, - { - Type: "local", - Attrs: map[string]string{ - "dest": dir2, - }, - }, + ExportsLocalPathsTemporary: []string{ + dir1, + filepath.Join(dir1, "subdir"), + dir2, }, }, expected: EntitlementConf{ diff --git a/build/build.go b/build/build.go index 3a2e7663dd7..4663d1f436c 100644 --- a/build/build.go +++ b/build/build.go @@ -62,27 +62,28 @@ const ( type Options struct { Inputs Inputs - Ref string - Allow []entitlements.Entitlement - Attests map[string]*string - BuildArgs map[string]string - CacheFrom []client.CacheOptionsEntry - CacheTo []client.CacheOptionsEntry - CgroupParent string - Exports []client.ExportEntry - ExtraHosts []string - Labels map[string]string - NetworkMode string - NoCache bool - NoCacheFilter []string - Platforms []specs.Platform - Pull bool - SecretSpecs []*controllerapi.Secret - SSHSpecs []*controllerapi.SSH - ShmSize opts.MemBytes - Tags []string - Target string - Ulimits *opts.UlimitOpt + Ref string + Allow []entitlements.Entitlement + Attests map[string]*string + BuildArgs map[string]string + CacheFrom []client.CacheOptionsEntry + CacheTo []client.CacheOptionsEntry + CgroupParent string + Exports []client.ExportEntry + ExportsLocalPathsTemporary []string // should be removed after client.ExportEntry update in buildkit v0.19.0 + ExtraHosts []string + Labels map[string]string + NetworkMode string + NoCache bool + NoCacheFilter []string + Platforms []specs.Platform + Pull bool + SecretSpecs []*controllerapi.Secret + SSHSpecs []*controllerapi.SSH + ShmSize opts.MemBytes + Tags []string + Target string + Ulimits *opts.UlimitOpt Session []session.Attachable Linked bool // Linked marks this target as exclusively linked (not requested by the user). diff --git a/commands/bake.go b/commands/bake.go index ad94c23f31c..12befc84b31 100644 --- a/commands/bake.go +++ b/commands/bake.go @@ -199,7 +199,7 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba } } - tgts, grps, err := bake.ReadTargets(ctx, files, targets, overrides, defaults) + tgts, grps, err := bake.ReadTargets(ctx, files, targets, overrides, defaults, &ent) if err != nil { return err } diff --git a/controller/build/build.go b/controller/build/build.go index 7a57dc7d222..5e0c89c2249 100644 --- a/controller/build/build.go +++ b/controller/build/build.go @@ -93,7 +93,7 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in *controllerapi.Buil } opts.Session = append(opts.Session, ssh) - outputs, err := controllerapi.CreateExports(in.Exports) + outputs, _, err := controllerapi.CreateExports(in.Exports) if err != nil { return nil, nil, nil, err } diff --git a/controller/pb/export.go b/controller/pb/export.go index e8f49bb4fe7..8df341b3034 100644 --- a/controller/pb/export.go +++ b/controller/pb/export.go @@ -10,15 +10,16 @@ import ( "github.com/pkg/errors" ) -func CreateExports(entries []*ExportEntry) ([]client.ExportEntry, error) { +func CreateExports(entries []*ExportEntry) ([]client.ExportEntry, []string, error) { var outs []client.ExportEntry + var localPaths []string if len(entries) == 0 { - return nil, nil + return nil, nil, nil } var stdoutUsed bool for _, entry := range entries { if entry.Type == "" { - return nil, errors.Errorf("type is required for output") + return nil, nil, errors.Errorf("type is required for output") } out := client.ExportEntry{ @@ -50,20 +51,21 @@ func CreateExports(entries []*ExportEntry) ([]client.ExportEntry, error) { if supportDir { if entry.Destination == "" { - return nil, errors.Errorf("dest is required for %s exporter", out.Type) + return nil, nil, errors.Errorf("dest is required for %s exporter", out.Type) } if entry.Destination == "-" { - return nil, errors.Errorf("dest cannot be stdout for %s exporter", out.Type) + return nil, nil, errors.Errorf("dest cannot be stdout for %s exporter", out.Type) } fi, err := os.Stat(entry.Destination) if err != nil && !os.IsNotExist(err) { - return nil, errors.Wrapf(err, "invalid destination directory: %s", entry.Destination) + return nil, nil, errors.Wrapf(err, "invalid destination directory: %s", entry.Destination) } if err == nil && !fi.IsDir() { - return nil, errors.Errorf("destination directory %s is a file", entry.Destination) + return nil, nil, errors.Errorf("destination directory %s is a file", entry.Destination) } out.OutputDir = entry.Destination + localPaths = append(localPaths, entry.Destination) } if supportFile { if entry.Destination == "" && out.Type != client.ExporterDocker { @@ -71,32 +73,33 @@ func CreateExports(entries []*ExportEntry) ([]client.ExportEntry, error) { } if entry.Destination == "-" { if stdoutUsed { - return nil, errors.Errorf("multiple outputs configured to write to stdout") + return nil, nil, errors.Errorf("multiple outputs configured to write to stdout") } if _, err := console.ConsoleFromFile(os.Stdout); err == nil { - return nil, errors.Errorf("dest file is required for %s exporter. refusing to write to console", out.Type) + return nil, nil, errors.Errorf("dest file is required for %s exporter. refusing to write to console", out.Type) } out.Output = wrapWriteCloser(os.Stdout) stdoutUsed = true } else if entry.Destination != "" { fi, err := os.Stat(entry.Destination) if err != nil && !os.IsNotExist(err) { - return nil, errors.Wrapf(err, "invalid destination file: %s", entry.Destination) + return nil, nil, errors.Wrapf(err, "invalid destination file: %s", entry.Destination) } if err == nil && fi.IsDir() { - return nil, errors.Errorf("destination file %s is a directory", entry.Destination) + return nil, nil, errors.Errorf("destination file %s is a directory", entry.Destination) } f, err := os.Create(entry.Destination) if err != nil { - return nil, errors.Errorf("failed to open %s", err) + return nil, nil, errors.Errorf("failed to open %s", err) } out.Output = wrapWriteCloser(f) + localPaths = append(localPaths, entry.Destination) } } outs = append(outs, out) } - return outs, nil + return outs, localPaths, nil } func wrapWriteCloser(wc io.WriteCloser) func(map[string]string) (io.WriteCloser, error) {