Skip to content

Commit 2352a4a

Browse files
ndeloofglours
authored andcommitted
introduce config --lock-image-digests
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
1 parent 1f076a3 commit 2352a4a

File tree

4 files changed

+54
-5
lines changed

4 files changed

+54
-5
lines changed

‎cmd/compose/config.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ type configOptions struct {
5656
noConsistency bool
5757
variables bool
5858
environment bool
59+
lockImageDigests bool
5960
}
6061

6162
func (o *configOptions) ToProject(ctx context.Context, dockerCli command.Cli, services []string, po ...cli.ProjectOptionsFn) (*types.Project, error) {
@@ -98,6 +99,9 @@ func configCommand(p *ProjectOptions, dockerCli command.Cli) *cobra.Command {
9899
if p.Compatibility {
99100
opts.noNormalize = true
100101
}
102+
if opts.lockImageDigests {
103+
opts.resolveImageDigests = true
104+
}
101105
return nil
102106
}),
103107
RunE: Adapt(func(ctx context.Context, args []string) error {
@@ -133,6 +137,7 @@ func configCommand(p *ProjectOptions, dockerCli command.Cli) *cobra.Command {
133137
flags := cmd.Flags()
134138
flags.StringVar(&opts.Format, "format", "", "Format the output. Values: [yaml | json]")
135139
flags.BoolVar(&opts.resolveImageDigests, "resolve-image-digests", false, "Pin image tags to digests")
140+
flags.BoolVar(&opts.lockImageDigests, "lock-image-digests", false, "Produces an override file with image digests")
136141
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only validate the configuration, don't print anything")
137142
flags.BoolVar(&opts.noInterpolate, "no-interpolate", false, "Don't interpolate environment variables")
138143
flags.BoolVar(&opts.noNormalize, "no-normalize", false, "Don't normalize compose model")
@@ -208,6 +213,10 @@ func runConfigInterpolate(ctx context.Context, dockerCli command.Cli, opts confi
208213
}
209214
}
210215

216+
if opts.lockImageDigests {
217+
project = imagesOnly(project)
218+
}
219+
211220
var content []byte
212221
switch opts.Format {
213222
case "json":
@@ -223,6 +232,18 @@ func runConfigInterpolate(ctx context.Context, dockerCli command.Cli, opts confi
223232
return content, nil
224233
}
225234

235+
// imagesOnly return project with all attributes removed but service.images
236+
func imagesOnly(project *types.Project) *types.Project {
237+
digests := types.Services{}
238+
for name, config := range project.Services {
239+
digests[name] = types.ServiceConfig{
240+
Image: config.Image,
241+
}
242+
}
243+
project = &types.Project{Services: digests}
244+
return project
245+
}
246+
226247
func runConfigNoInterpolate(ctx context.Context, dockerCli command.Cli, opts configOptions, services []string) ([]byte, error) {
227248
// we can't use ToProject, so the model we render here is only partially resolved
228249
model, err := opts.ToModel(ctx, dockerCli, services)
@@ -237,6 +258,23 @@ func runConfigNoInterpolate(ctx context.Context, dockerCli command.Cli, opts con
237258
}
238259
}
239260

261+
if opts.lockImageDigests {
262+
for key, e := range model {
263+
if key != "services" {
264+
delete(model, key)
265+
} else {
266+
for _, s := range e.(map[string]any) {
267+
service := s.(map[string]any)
268+
for key := range service {
269+
if key != "image" {
270+
delete(service, key)
271+
}
272+
}
273+
}
274+
}
275+
}
276+
}
277+
240278
return formatModel(model, opts.Format)
241279
}
242280

‎docs/reference/compose_config.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ the canonical format.
1414
| `--format` | `string` | | Format the output. Values: [yaml \| json] |
1515
| `--hash` | `string` | | Print the service config hash, one per line. |
1616
| `--images` | `bool` | | Print the image names, one per line. |
17+
| `--lock-image-digests` | `bool` | | Produces an override file with image digests |
1718
| `--no-consistency` | `bool` | | Don't check model consistency - warning: may produce invalid Compose output |
1819
| `--no-env-resolution` | `bool` | | Don't resolve service env files |
1920
| `--no-interpolate` | `bool` | | Don't interpolate environment variables |

‎docs/reference/docker_compose_config.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ options:
4646
experimentalcli: false
4747
kubernetes: false
4848
swarm: false
49+
- option: lock-image-digests
50+
value_type: bool
51+
default_value: "false"
52+
description: Produces an override file with image digests
53+
deprecated: false
54+
hidden: false
55+
experimental: false
56+
experimentalcli: false
57+
kubernetes: false
58+
swarm: false
4959
- option: no-consistency
5060
value_type: bool
5161
default_value: "false"

‎pkg/e2e/compose_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ func TestCompatibility(t *testing.T) {
235235
}
236236

237237
func TestConfig(t *testing.T) {
238-
const projectName = "compose-e2e-convert"
238+
const projectName = "compose-e2e-config"
239239
c := NewParallelCLI(t)
240240

241241
wd, err := os.Getwd()
@@ -253,24 +253,24 @@ services:
253253
default: null
254254
networks:
255255
default:
256-
name: compose-e2e-convert_default
256+
name: compose-e2e-config_default
257257
`, projectName, filepath.Join(wd, "fixtures", "simple-build-test", "nginx-build")), ExitCode: 0})
258258
})
259259
}
260260

261261
func TestConfigInterpolate(t *testing.T) {
262-
const projectName = "compose-e2e-convert-interpolate"
262+
const projectName = "compose-e2e-config-interpolate"
263263
c := NewParallelCLI(t)
264264

265265
wd, err := os.Getwd()
266266
assert.NilError(t, err)
267267

268-
t.Run("convert", func(t *testing.T) {
268+
t.Run("config", func(t *testing.T) {
269269
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/simple-build-test/compose-interpolate.yaml", "-p", projectName, "config", "--no-interpolate")
270270
res.Assert(t, icmd.Expected{Out: fmt.Sprintf(`name: %s
271271
networks:
272272
default:
273-
name: compose-e2e-convert-interpolate_default
273+
name: compose-e2e-config-interpolate_default
274274
services:
275275
nginx:
276276
build:

0 commit comments

Comments
 (0)