From 6ef45e5cf1e1eca503effb685402a3ff08260110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= Date: Wed, 18 Jul 2018 00:24:55 +0200 Subject: [PATCH] Migrate --authfile to sharedImageOptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This introduces YET ANOTHER *Options structure, only to share this option between copy source and destination. (We do need to do this, because the libraries, rightly, refuse to work with source and destination declaring its own versino of the --authfile flag.) Signed-off-by: Miloslav Trmač --- cmd/skopeo/copy.go | 13 +++++-------- cmd/skopeo/delete.go | 10 +++------- cmd/skopeo/inspect.go | 11 ++++------- cmd/skopeo/layers.go | 5 +++-- cmd/skopeo/utils.go | 42 +++++++++++++++++++++++++++++----------- cmd/skopeo/utils_test.go | 10 ++++++---- 6 files changed, 52 insertions(+), 39 deletions(-) diff --git a/cmd/skopeo/copy.go b/cmd/skopeo/copy.go index f5b2e9c5..a1a71310 100644 --- a/cmd/skopeo/copy.go +++ b/cmd/skopeo/copy.go @@ -42,8 +42,9 @@ type copyOptions struct { } func copyCmd(global *globalOptions) cli.Command { - srcFlags, srcOpts := imageFlags(global, "src-", "screds") - destFlags, destOpts := imageDestFlags(global, "dest-", "dcreds") + sharedFlags, sharedOpts := sharedImageFlags() + srcFlags, srcOpts := imageFlags(global, sharedOpts, "src-", "screds") + destFlags, destOpts := imageDestFlags(global, sharedOpts, "dest-", "dcreds") opts := copyOptions{global: global, srcImage: srcOpts, destImage: destOpts, @@ -64,16 +65,12 @@ func copyCmd(global *globalOptions) cli.Command { ArgsUsage: "SOURCE-IMAGE DESTINATION-IMAGE", Action: opts.run, // FIXME: Do we need to namespace the GPG aspect? - Flags: append(append([]cli.Flag{ + Flags: append(append(append([]cli.Flag{ cli.StringSliceFlag{ Name: "additional-tag", Usage: "additional tags (supports docker-archive)", Value: &opts.additionalTags, // Surprisingly StringSliceFlag does not support Destination:, but modifies Value: in place. }, - cli.StringFlag{ - Name: "authfile", - Usage: "path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json", - }, cli.BoolFlag{ Name: "remove-signatures", Usage: "Do not copy signatures from SOURCE-IMAGE", @@ -89,7 +86,7 @@ func copyCmd(global *globalOptions) cli.Command { Usage: "`MANIFEST TYPE` (oci, v2s1, or v2s2) to use when saving image to directory using the 'dir:' transport (default is manifest type of source)", Value: newOptionalStringValue(&opts.format), }, - }, srcFlags...), destFlags...), + }, sharedFlags...), srcFlags...), destFlags...), } } diff --git a/cmd/skopeo/delete.go b/cmd/skopeo/delete.go index a7d4f0d1..9a3723e8 100644 --- a/cmd/skopeo/delete.go +++ b/cmd/skopeo/delete.go @@ -16,7 +16,8 @@ type deleteOptions struct { } func deleteCmd(global *globalOptions) cli.Command { - imageFlags, imageOpts := imageFlags(global, "", "") + sharedFlags, sharedOpts := sharedImageFlags() + imageFlags, imageOpts := imageFlags(global, sharedOpts, "", "") opts := deleteOptions{ global: global, image: imageOpts, @@ -34,12 +35,7 @@ func deleteCmd(global *globalOptions) cli.Command { `, strings.Join(transports.ListNames(), ", ")), ArgsUsage: "IMAGE-NAME", Action: opts.run, - Flags: append([]cli.Flag{ - cli.StringFlag{ - Name: "authfile", - Usage: "path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json", - }, - }, imageFlags...), + Flags: append(sharedFlags, imageFlags...), } } diff --git a/cmd/skopeo/inspect.go b/cmd/skopeo/inspect.go index 0bd7c928..0b01f077 100644 --- a/cmd/skopeo/inspect.go +++ b/cmd/skopeo/inspect.go @@ -36,7 +36,8 @@ type inspectOptions struct { } func inspectCmd(global *globalOptions) cli.Command { - imageFlags, imageOpts := imageFlags(global, "", "") + sharedFlags, sharedOpts := sharedImageFlags() + imageFlags, imageOpts := imageFlags(global, sharedOpts, "", "") opts := inspectOptions{ global: global, image: imageOpts, @@ -53,17 +54,13 @@ func inspectCmd(global *globalOptions) cli.Command { See skopeo(1) section "IMAGE NAMES" for the expected format `, strings.Join(transports.ListNames(), ", ")), ArgsUsage: "IMAGE-NAME", - Flags: append([]cli.Flag{ - cli.StringFlag{ - Name: "authfile", - Usage: "path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json", - }, + Flags: append(append([]cli.Flag{ cli.BoolFlag{ Name: "raw", Usage: "output raw manifest", Destination: &opts.raw, }, - }, imageFlags...), + }, sharedFlags...), imageFlags...), Action: opts.run, } } diff --git a/cmd/skopeo/layers.go b/cmd/skopeo/layers.go index e4c53518..8f5d08da 100644 --- a/cmd/skopeo/layers.go +++ b/cmd/skopeo/layers.go @@ -21,7 +21,8 @@ type layersOptions struct { } func layersCmd(global *globalOptions) cli.Command { - imageFlags, imageOpts := imageFlags(global, "", "") + sharedFlags, sharedOpts := sharedImageFlags() + imageFlags, imageOpts := imageFlags(global, sharedOpts, "", "") opts := layersOptions{ global: global, image: imageOpts, @@ -32,7 +33,7 @@ func layersCmd(global *globalOptions) cli.Command { ArgsUsage: "IMAGE-NAME [LAYER...]", Hidden: true, Action: opts.run, - Flags: imageFlags, + Flags: append(sharedFlags, imageFlags...), } } diff --git a/cmd/skopeo/utils.go b/cmd/skopeo/utils.go index 9a7ca3b0..d4c63841 100644 --- a/cmd/skopeo/utils.go +++ b/cmd/skopeo/utils.go @@ -10,22 +10,42 @@ import ( "github.com/urfave/cli" ) +// sharedImageOptions collects CLI flags which are image-related, but do not change across images. +// This really should be a part of globalOptions, but that would break existing users of (skopeo copy --authfile=). +type sharedImageOptions struct { + authFilePath string // Path to a */containers/auth.json +} + +// imageFlags prepares a collection of CLI flags writing into sharedImageOptions, and the managed sharedImageOptions structure. +func sharedImageFlags() ([]cli.Flag, *sharedImageOptions) { + opts := sharedImageOptions{} + return []cli.Flag{ + cli.StringFlag{ + Name: "authfile", + Usage: "path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json", + Destination: &opts.authFilePath, + }, + }, &opts +} + // imageOptions collects CLI flags which are the same across subcommands, but may be different for each image // (e.g. may differ between the source and destination of a copy) type imageOptions struct { - global *globalOptions // May be shared across several imageOptions instances. - flagPrefix string // FIXME: Drop this eventually. - credsOption optionalString // username[:password] for accessing a registry - dockerCertPath string // A directory using Docker-like *.{crt,cert,key} files for connecting to a registry or a daemon - tlsVerify optionalBool // Require HTTPS and verify certificates (for docker: and docker-daemon:) - sharedBlobDir string // A directory to use for OCI blobs, shared across repositories - dockerDaemonHost string // docker-daemon: host to connect to + global *globalOptions // May be shared across several imageOptions instances. + shared *sharedImageOptions // May be shared across several imageOptions instances. + flagPrefix string // FIXME: Drop this eventually. + credsOption optionalString // username[:password] for accessing a registry + dockerCertPath string // A directory using Docker-like *.{crt,cert,key} files for connecting to a registry or a daemon + tlsVerify optionalBool // Require HTTPS and verify certificates (for docker: and docker-daemon:) + sharedBlobDir string // A directory to use for OCI blobs, shared across repositories + dockerDaemonHost string // docker-daemon: host to connect to } // imageFlags prepares a collection of CLI flags writing into imageOptions, and the managed imageOptions structure. -func imageFlags(global *globalOptions, flagPrefix, credsOptionAlias string) ([]cli.Flag, *imageOptions) { +func imageFlags(global *globalOptions, shared *sharedImageOptions, flagPrefix, credsOptionAlias string) ([]cli.Flag, *imageOptions) { opts := imageOptions{ global: global, + shared: shared, flagPrefix: flagPrefix, } @@ -74,7 +94,7 @@ func contextFromImageOptions(c *cli.Context, opts *imageOptions) (*types.SystemC OSChoice: opts.global.overrideOS, DockerCertPath: opts.dockerCertPath, OCISharedBlobDirPath: opts.sharedBlobDir, - AuthFilePath: c.String("authfile"), + AuthFilePath: opts.shared.authFilePath, DockerDaemonHost: opts.dockerDaemonHost, DockerDaemonCertPath: opts.dockerCertPath, } @@ -106,8 +126,8 @@ type imageDestOptions struct { } // imageDestFlags prepares a collection of CLI flags writing into imageDestOptions, and the managed imageDestOptions structure. -func imageDestFlags(global *globalOptions, flagPrefix, credsOptionAlias string) ([]cli.Flag, *imageDestOptions) { - genericFlags, genericOptions := imageFlags(global, flagPrefix, credsOptionAlias) +func imageDestFlags(global *globalOptions, shared *sharedImageOptions, flagPrefix, credsOptionAlias string) ([]cli.Flag, *imageDestOptions) { + genericFlags, genericOptions := imageFlags(global, shared, flagPrefix, credsOptionAlias) opts := imageDestOptions{imageOptions: genericOptions} return append(genericFlags, []cli.Flag{ diff --git a/cmd/skopeo/utils_test.go b/cmd/skopeo/utils_test.go index 615a77f8..8dfdaa06 100644 --- a/cmd/skopeo/utils_test.go +++ b/cmd/skopeo/utils_test.go @@ -35,7 +35,8 @@ func fakeImageContext(t *testing.T, cmdName string, flagPrefix string, globalFla cmd := app.Command(cmdName) require.NotNil(t, cmd) - imageFlags, imageOpts := imageFlags(globalOpts, flagPrefix, "") + sharedFlags, sharedOpts := sharedImageFlags() + imageFlags, imageOpts := imageFlags(globalOpts, sharedOpts, flagPrefix, "") appliedFlags := map[string]struct{}{} // Ugly: cmd.Flags includes imageFlags as well. For now, we need cmd.Flags to apply here // to be able to test the non-Destination: flags, but we must not apply the same flag name twice. @@ -46,7 +47,7 @@ func fakeImageContext(t *testing.T, cmdName string, flagPrefix string, globalFla return strings.Split(f.GetName(), ",")[0] } flagSet := flag.NewFlagSet(cmd.Name, flag.ContinueOnError) - for _, f := range imageFlags { + for _, f := range append(sharedFlags, imageFlags...) { f.Apply(flagSet) appliedFlags[firstName(f)] = struct{}{} } @@ -145,7 +146,8 @@ func fakeImageDestContext(t *testing.T, cmdName string, flagPrefix string, globa cmd := app.Command(cmdName) require.NotNil(t, cmd) - imageFlags, imageOpts := imageDestFlags(globalOpts, flagPrefix, "") + sharedFlags, sharedOpts := sharedImageFlags() + imageFlags, imageOpts := imageDestFlags(globalOpts, sharedOpts, flagPrefix, "") appliedFlags := map[string]struct{}{} // Ugly: cmd.Flags includes imageFlags as well. For now, we need cmd.Flags to apply here // to be able to test the non-Destination: flags, but we must not apply the same flag name twice. @@ -156,7 +158,7 @@ func fakeImageDestContext(t *testing.T, cmdName string, flagPrefix string, globa return strings.Split(f.GetName(), ",")[0] } flagSet := flag.NewFlagSet(cmd.Name, flag.ContinueOnError) - for _, f := range imageFlags { + for _, f := range append(sharedFlags, imageFlags...) { f.Apply(flagSet) appliedFlags[firstName(f)] = struct{}{} }