diff --git a/cmd/executor/cmd/args.go b/cmd/executor/cmd/args.go index fdf6eb0c93..3e67d791a6 100644 --- a/cmd/executor/cmd/args.go +++ b/cmd/executor/cmd/args.go @@ -21,23 +21,23 @@ import ( "strings" ) -// The buildArg type is used to pass in multiple --build-arg flags -type buildArg []string +// This type is used to supported passing in multiple flags +type multiArg []string // Now, for our new type, implement the two methods of // the flag.Value interface... // The first method is String() string -func (b *buildArg) String() string { +func (b *multiArg) String() string { return strings.Join(*b, ",") } // The second method is Set(value string) error -func (b *buildArg) Set(value string) error { - logrus.Infof("appending to build args %s", value) +func (b *multiArg) Set(value string) error { + logrus.Infof("appending to multi args %s", value) *b = append(*b, value) return nil } -func (b *buildArg) Type() string { - return "build-arg type" +func (b *multiArg) Type() string { + return "multi-arg type" } diff --git a/cmd/executor/cmd/root.go b/cmd/executor/cmd/root.go index 63e42831d7..43dbc547c9 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -31,14 +31,14 @@ import ( var ( dockerfilePath string - destination string + destinations multiArg srcContext string snapshotMode string bucket string dockerInsecureSkipTLSVerify bool logLevel string force bool - buildArgs buildArg + buildArgs multiArg tarPath string ) @@ -46,7 +46,7 @@ func init() { RootCmd.PersistentFlags().StringVarP(&dockerfilePath, "dockerfile", "f", "Dockerfile", "Path to the dockerfile to be built.") RootCmd.PersistentFlags().StringVarP(&srcContext, "context", "c", "/workspace/", "Path to the dockerfile build context.") RootCmd.PersistentFlags().StringVarP(&bucket, "bucket", "b", "", "Name of the GCS bucket from which to access build context as tarball.") - RootCmd.PersistentFlags().StringVarP(&destination, "destination", "d", "", "Registry the final image should be pushed to (ex: gcr.io/test/example:latest)") + RootCmd.PersistentFlags().VarP(&destinations, "destination", "d", "Registry the final image should be pushed to. Set it repeatedly for multiple destinations.") RootCmd.MarkPersistentFlagRequired("destination") RootCmd.PersistentFlags().StringVarP(&snapshotMode, "snapshotMode", "", "full", "Set this flag to change the file attributes inspected during snapshotting") RootCmd.PersistentFlags().VarP(&buildArgs, "build-arg", "", "This flag allows you to pass in ARG values at build time. Set it repeatedly for multiple values.") @@ -84,10 +84,12 @@ var RootCmd = &cobra.Command{ logrus.Error(err) os.Exit(1) } - if err := executor.DoPush(ref, image, destination, tarPath); err != nil { + + if err := executor.DoPush(ref, image, destinations, tarPath); err != nil { logrus.Error(err) os.Exit(1) } + }, } diff --git a/pkg/executor/executor.go b/pkg/executor/executor.go index b3c697859d..7300ec1d03 100644 --- a/pkg/executor/executor.go +++ b/pkg/executor/executor.go @@ -170,26 +170,35 @@ func DoBuild(dockerfilePath, srcContext, snapshotMode string, args []string) (na return nil, nil, err } -func DoPush(ref name.Reference, image v1.Image, destination, tarPath string) error { - // Push the image - destRef, err := name.NewTag(destination, name.WeakValidation) - if err != nil { - return err - } +func DoPush(ref name.Reference, image v1.Image, destinations []string, tarPath string) error { + // continue pushing unless an error occurs + for _, destination := range destinations { + // Push the image + destRef, err := name.NewTag(destination, name.WeakValidation) + if err != nil { + return err + } - if tarPath != "" { - return tarball.WriteToFile(tarPath, destRef, image, nil) - } + if tarPath != "" { + return tarball.WriteToFile(tarPath, destRef, image, nil) + } - wo := remote.WriteOptions{} - if ref != nil { - wo.MountPaths = []name.Repository{ref.Context()} - } - pushAuth, err := authn.DefaultKeychain.Resolve(destRef.Context().Registry) - if err != nil { - return err + wo := remote.WriteOptions{} + if ref != nil { + wo.MountPaths = []name.Repository{ref.Context()} + } + pushAuth, err := authn.DefaultKeychain.Resolve(destRef.Context().Registry) + if err != nil { + return err + } + + err = remote.Write(destRef, image, pushAuth, http.DefaultTransport, wo) + if err != nil { + logrus.Error(fmt.Errorf("Failed to push to destination %s", destination)) + return err + } } - return remote.Write(destRef, image, pushAuth, http.DefaultTransport, wo) + return nil } func saveStageDependencies(index int, stages []instructions.Stage, buildArgs *dockerfile.BuildArgs) error { // First, get the files in this stage later stages will need