introduce config --lock-image-digests
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
1f076a3781
commit
2352a4a016
@ -56,6 +56,7 @@ type configOptions struct {
|
||||
noConsistency bool
|
||||
variables bool
|
||||
environment bool
|
||||
lockImageDigests bool
|
||||
}
|
||||
|
||||
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 {
|
||||
if p.Compatibility {
|
||||
opts.noNormalize = true
|
||||
}
|
||||
if opts.lockImageDigests {
|
||||
opts.resolveImageDigests = true
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
@ -133,6 +137,7 @@ func configCommand(p *ProjectOptions, dockerCli command.Cli) *cobra.Command {
|
||||
flags := cmd.Flags()
|
||||
flags.StringVar(&opts.Format, "format", "", "Format the output. Values: [yaml | json]")
|
||||
flags.BoolVar(&opts.resolveImageDigests, "resolve-image-digests", false, "Pin image tags to digests")
|
||||
flags.BoolVar(&opts.lockImageDigests, "lock-image-digests", false, "Produces an override file with image digests")
|
||||
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only validate the configuration, don't print anything")
|
||||
flags.BoolVar(&opts.noInterpolate, "no-interpolate", false, "Don't interpolate environment variables")
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
if opts.lockImageDigests {
|
||||
project = imagesOnly(project)
|
||||
}
|
||||
|
||||
var content []byte
|
||||
switch opts.Format {
|
||||
case "json":
|
||||
@ -223,6 +232,18 @@ func runConfigInterpolate(ctx context.Context, dockerCli command.Cli, opts confi
|
||||
return content, nil
|
||||
}
|
||||
|
||||
// imagesOnly return project with all attributes removed but service.images
|
||||
func imagesOnly(project *types.Project) *types.Project {
|
||||
digests := types.Services{}
|
||||
for name, config := range project.Services {
|
||||
digests[name] = types.ServiceConfig{
|
||||
Image: config.Image,
|
||||
}
|
||||
}
|
||||
project = &types.Project{Services: digests}
|
||||
return project
|
||||
}
|
||||
|
||||
func runConfigNoInterpolate(ctx context.Context, dockerCli command.Cli, opts configOptions, services []string) ([]byte, error) {
|
||||
// we can't use ToProject, so the model we render here is only partially resolved
|
||||
model, err := opts.ToModel(ctx, dockerCli, services)
|
||||
@ -237,6 +258,23 @@ func runConfigNoInterpolate(ctx context.Context, dockerCli command.Cli, opts con
|
||||
}
|
||||
}
|
||||
|
||||
if opts.lockImageDigests {
|
||||
for key, e := range model {
|
||||
if key != "services" {
|
||||
delete(model, key)
|
||||
} else {
|
||||
for _, s := range e.(map[string]any) {
|
||||
service := s.(map[string]any)
|
||||
for key := range service {
|
||||
if key != "image" {
|
||||
delete(service, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return formatModel(model, opts.Format)
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ the canonical format.
|
||||
| `--format` | `string` | | Format the output. Values: [yaml \| json] |
|
||||
| `--hash` | `string` | | Print the service config hash, one per line. |
|
||||
| `--images` | `bool` | | Print the image names, one per line. |
|
||||
| `--lock-image-digests` | `bool` | | Produces an override file with image digests |
|
||||
| `--no-consistency` | `bool` | | Don't check model consistency - warning: may produce invalid Compose output |
|
||||
| `--no-env-resolution` | `bool` | | Don't resolve service env files |
|
||||
| `--no-interpolate` | `bool` | | Don't interpolate environment variables |
|
||||
|
@ -46,6 +46,16 @@ options:
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: lock-image-digests
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Produces an override file with image digests
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: no-consistency
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
|
@ -235,7 +235,7 @@ func TestCompatibility(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
const projectName = "compose-e2e-convert"
|
||||
const projectName = "compose-e2e-config"
|
||||
c := NewParallelCLI(t)
|
||||
|
||||
wd, err := os.Getwd()
|
||||
@ -253,24 +253,24 @@ services:
|
||||
default: null
|
||||
networks:
|
||||
default:
|
||||
name: compose-e2e-convert_default
|
||||
name: compose-e2e-config_default
|
||||
`, projectName, filepath.Join(wd, "fixtures", "simple-build-test", "nginx-build")), ExitCode: 0})
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigInterpolate(t *testing.T) {
|
||||
const projectName = "compose-e2e-convert-interpolate"
|
||||
const projectName = "compose-e2e-config-interpolate"
|
||||
c := NewParallelCLI(t)
|
||||
|
||||
wd, err := os.Getwd()
|
||||
assert.NilError(t, err)
|
||||
|
||||
t.Run("convert", func(t *testing.T) {
|
||||
t.Run("config", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/simple-build-test/compose-interpolate.yaml", "-p", projectName, "config", "--no-interpolate")
|
||||
res.Assert(t, icmd.Expected{Out: fmt.Sprintf(`name: %s
|
||||
networks:
|
||||
default:
|
||||
name: compose-e2e-convert-interpolate_default
|
||||
name: compose-e2e-config-interpolate_default
|
||||
services:
|
||||
nginx:
|
||||
build:
|
||||
|
Loading…
x
Reference in New Issue
Block a user