From fcec6c5699dd4841340f336d99cb1a6d52bc3ebb Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sat, 15 Feb 2020 14:45:05 +0100 Subject: [PATCH] Add Push to hub feature Add to the backends the Push capabilities to push images that were correctly built. Also expose them to the CLI, along with KeepImg which was hidden. --- cmd/build.go | 12 ++++++++++++ pkg/compiler/backend/simpledocker.go | 12 ++++++++++++ pkg/compiler/backend/simpleimg.go | 12 ++++++++++++ pkg/compiler/compiler.go | 15 ++++++++++++++- pkg/compiler/interface.go | 15 +++++++++------ 5 files changed, 59 insertions(+), 7 deletions(-) diff --git a/cmd/build.go b/cmd/build.go index cf5adc2f..758e6185 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -47,6 +47,9 @@ var buildCmd = &cobra.Command{ viper.BindPFlag("compression", cmd.Flags().Lookup("compression")) viper.BindPFlag("image-repository", cmd.Flags().Lookup("image-repository")) + viper.BindPFlag("push", cmd.Flags().Lookup("push")) + viper.BindPFlag("pull", cmd.Flags().Lookup("pull")) + viper.BindPFlag("keep-images", cmd.Flags().Lookup("keep-images")) LuetCfg.Viper.BindPFlag("solver.type", cmd.Flags().Lookup("solver-type")) LuetCfg.Viper.BindPFlag("solver.discount", cmd.Flags().Lookup("solver-discount")) @@ -66,6 +69,9 @@ var buildCmd = &cobra.Command{ databaseType := viper.GetString("database") compressionType := viper.GetString("compression") imageRepository := viper.GetString("image-repository") + push := viper.GetBool("push") + pull := viper.GetBool("pull") + keepImages := viper.GetBool("keep-images") compilerSpecs := compiler.NewLuetCompilationspecs() var compilerBackend compiler.CompilerBackend @@ -117,6 +123,9 @@ var buildCmd = &cobra.Command{ opts.SolverOptions = *LuetCfg.GetSolverOptions() opts.ImageRepository = imageRepository opts.Clean = clean + opts.PullFirst = pull + opts.KeepImg = keepImages + opts.Push = push luetCompiler := compiler.NewLuetCompiler(compilerBackend, generalRecipe.GetDatabase(), opts) luetCompiler.SetConcurrency(concurrency) luetCompiler.SetCompressionType(compiler.CompressionImplementation(compressionType)) @@ -200,6 +209,9 @@ func init() { buildCmd.Flags().String("destination", path, "Destination folder") buildCmd.Flags().String("compression", "none", "Compression alg: none, gzip") buildCmd.Flags().String("image-repository", "luet/cache", "Default base image string for generated image") + buildCmd.Flags().Bool("push", false, "Push images to a hub") + buildCmd.Flags().Bool("pull", false, "Pull images from a hub") + buildCmd.Flags().Bool("keep-images", true, "Keep built docker images in the host") buildCmd.Flags().String("solver-type", "", "Solver strategy") buildCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate") diff --git a/pkg/compiler/backend/simpledocker.go b/pkg/compiler/backend/simpledocker.go index 7a84f5bb..a8a720e3 100644 --- a/pkg/compiler/backend/simpledocker.go +++ b/pkg/compiler/backend/simpledocker.go @@ -101,6 +101,18 @@ func (*SimpleDocker) RemoveImage(opts compiler.CompilerBackendOptions) error { return nil } +func (*SimpleDocker) Push(opts compiler.CompilerBackendOptions) error { + name := opts.ImageName + pusharg := []string{"push", name} + out, err := exec.Command("docker", pusharg...).CombinedOutput() + if err != nil { + return errors.Wrap(err, "Failed pushing image: "+string(out)) + } + Info(":whale: Pushed image:", name) + //Info(string(out)) + return nil +} + func (s *SimpleDocker) ImageDefinitionToTar(opts compiler.CompilerBackendOptions) error { if err := s.BuildImage(opts); err != nil { return errors.Wrap(err, "Failed building image") diff --git a/pkg/compiler/backend/simpleimg.go b/pkg/compiler/backend/simpleimg.go index 809a644a..23edb493 100644 --- a/pkg/compiler/backend/simpleimg.go +++ b/pkg/compiler/backend/simpleimg.go @@ -145,3 +145,15 @@ func (*SimpleImg) ExtractRootfs(opts compiler.CompilerBackendOptions, keepPerms func (*SimpleImg) Changes(fromImage, toImage string) ([]compiler.ArtifactLayer, error) { return NewSimpleDockerBackend().Changes(fromImage, toImage) } + +func (*SimpleImg) Push(opts compiler.CompilerBackendOptions) error { + name := opts.ImageName + pusharg := []string{"push", name} + out, err := exec.Command("img", pusharg...).CombinedOutput() + if err != nil { + return errors.Wrap(err, "Failed pushing image: "+string(out)) + } + Info(":tea: Pushed image:", name) + //Info(string(out)) + return nil +} diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index 925c5388..eca00f42 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -272,7 +272,7 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage packageImage = cs.ImageRepository + "-" + p.GetPackage().GetFingerPrint() } - if cs.PullFirst { + if cs.Options.PullFirst { //Best effort pull cs.Backend.DownloadImage(CompilerBackendOptions{ImageName: buildertaggedImage}) cs.Backend.DownloadImage(CompilerBackendOptions{ImageName: packageImage}) @@ -299,6 +299,12 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage return nil, errors.Wrap(err, "Could not export image") } + if cs.Options.Push { + err = cs.Backend.Push(builderOpts) + if err != nil { + return nil, errors.Wrap(err, "Could not push image: "+image+" "+builderOpts.DockerFileName) + } + } // Then we write the step image, which uses the builder one p.WriteStepImageDefinition(buildertaggedImage, filepath.Join(buildDir, p.GetPackage().GetFingerPrint()+".dockerfile")) runnerOpts := CompilerBackendOptions{ @@ -320,6 +326,13 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage if err := cs.Backend.ExportImage(runnerOpts); err != nil { return nil, errors.Wrap(err, "Failed exporting image") } + + if cs.Options.Push { + err = cs.Backend.Push(runnerOpts) + if err != nil { + return nil, errors.Wrap(err, "Could not push image: "+image+" "+builderOpts.DockerFileName) + } + } // } var diffs []ArtifactLayer diff --git a/pkg/compiler/interface.go b/pkg/compiler/interface.go index a9342820..6bba9567 100644 --- a/pkg/compiler/interface.go +++ b/pkg/compiler/interface.go @@ -44,11 +44,11 @@ type CompilerBackendOptions struct { } type CompilerOptions struct { - ImageRepository string - PullFirst, KeepImg bool - Concurrency int - CompressionType CompressionImplementation - Clean bool + ImageRepository string + PullFirst, KeepImg, Push bool + Concurrency int + CompressionType CompressionImplementation + Clean bool SolverOptions config.LuetSolverOptions } @@ -56,7 +56,8 @@ type CompilerOptions struct { func NewDefaultCompilerOptions() *CompilerOptions { return &CompilerOptions{ ImageRepository: "luet/cache", - PullFirst: true, + PullFirst: false, + Push: false, CompressionType: None, KeepImg: true, Concurrency: runtime.NumCPU(), @@ -74,6 +75,8 @@ type CompilerBackend interface { CopyImage(string, string) error DownloadImage(opts CompilerBackendOptions) error + + Push(opts CompilerBackendOptions) error } type Artifact interface {