// Copyright © 2019 Ettore Di Giacinto // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, see . package cmd import ( "os" "path/filepath" helpers "github.com/mudler/luet/cmd/helpers" "github.com/mudler/luet/cmd/util" "github.com/mudler/luet/pkg/api/core/types" "github.com/mudler/luet/pkg/compiler" installer "github.com/mudler/luet/pkg/installer" "github.com/mudler/luet/pkg/tree" // . "github.com/mudler/luet/pkg/logger" pkg "github.com/mudler/luet/pkg/database" "github.com/spf13/cobra" "github.com/spf13/viper" ) var createrepoCmd = &cobra.Command{ Use: "create-repo", Short: "Create a luet repository from a build", Long: `Builds tree metadata from a set of packages and a tree definition: $ luet create-repo Provide specific paths for packages, tree, and metadata output which is generated: $ luet create-repo --packages my/packages/path --tree my/tree/path --output my/packages/path ... Provide name and description of the repository: $ luet create-repo --name "foo" --description "bar" ... Change compression method: $ luet create-repo --tree-compression gzip --meta-compression gzip Create a repository from the metadata description defined in the luet.yaml config file: $ luet create-repo --repo repository1 `, PreRun: func(cmd *cobra.Command, args []string) { viper.BindPFlag("packages", cmd.Flags().Lookup("packages")) viper.BindPFlag("tree", cmd.Flags().Lookup("tree")) viper.BindPFlag("output", cmd.Flags().Lookup("output")) viper.BindPFlag("backend", cmd.Flags().Lookup("backend")) viper.BindPFlag("name", cmd.Flags().Lookup("name")) viper.BindPFlag("descr", cmd.Flags().Lookup("descr")) viper.BindPFlag("urls", cmd.Flags().Lookup("urls")) viper.BindPFlag("type", cmd.Flags().Lookup("type")) viper.BindPFlag("tree-compression", cmd.Flags().Lookup("tree-compression")) viper.BindPFlag("tree-filename", cmd.Flags().Lookup("tree-filename")) viper.BindPFlag("meta-compression", cmd.Flags().Lookup("meta-compression")) viper.BindPFlag("meta-filename", cmd.Flags().Lookup("meta-filename")) viper.BindPFlag("reset-revision", cmd.Flags().Lookup("reset-revision")) viper.BindPFlag("repo", cmd.Flags().Lookup("repo")) viper.BindPFlag("from-metadata", cmd.Flags().Lookup("from-metadata")) viper.BindPFlag("force-push", cmd.Flags().Lookup("force-push")) viper.BindPFlag("push-images", cmd.Flags().Lookup("push-images")) }, Run: func(cmd *cobra.Command, args []string) { var err error var repo *installer.LuetSystemRepository treePaths := viper.GetStringSlice("tree") dst := viper.GetString("output") name := viper.GetString("name") descr := viper.GetString("descr") urls := viper.GetStringSlice("urls") t := viper.GetString("type") reset := viper.GetBool("reset-revision") treetype := viper.GetString("tree-compression") treeName := viper.GetString("tree-filename") metatype := viper.GetString("meta-compression") metaName := viper.GetString("meta-filename") source_repo := viper.GetString("repo") backendType := viper.GetString("backend") fromRepo, _ := cmd.Flags().GetBool("from-repositories") dockerFiles, _ := cmd.Flags().GetBool("dockerfiles") treeFile := installer.NewDefaultTreeRepositoryFile() metaFile := installer.NewDefaultMetaRepositoryFile() compilerBackend, err := compiler.NewBackend(util.DefaultContext, backendType) helpers.CheckErr(err) force := viper.GetBool("force-push") imagePush := viper.GetBool("push-images") snapshotID, _ := cmd.Flags().GetString("snapshot-id") opts := []installer.RepositoryOption{ installer.WithSource(viper.GetString("packages")), installer.WithPushImages(imagePush), installer.WithForce(force), installer.FromRepository(fromRepo), installer.WithImagePrefix(dst), installer.WithDatabase(pkg.NewInMemoryDatabase(false)), installer.WithCompilerBackend(compilerBackend), installer.FromMetadata(viper.GetBool("from-metadata")), installer.WithContext(util.DefaultContext), } if dockerFiles { opts = append(opts, installer.WithCompilerParser(append(tree.DefaultCompilerParsers, tree.BuildDockerfileParser)...)) opts = append(opts, installer.WithRuntimeParser(append(tree.DefaultInstallerParsers, tree.RuntimeDockerfileParser)...)) } if source_repo != "" { // Search for system repository lrepo, err := util.DefaultContext.Config.GetSystemRepository(source_repo) helpers.CheckErr(err) if len(treePaths) <= 0 { treePaths = []string{lrepo.TreePath} } if t == "" { t = lrepo.Type } opts = append(opts, installer.WithName(lrepo.Name), installer.WithDescription(lrepo.Description), installer.WithType(t), installer.WithUrls(lrepo.Urls...), installer.WithPriority(lrepo.Priority), installer.WithTree(treePaths...), ) } else { opts = append(opts, installer.WithName(name), installer.WithDescription(descr), installer.WithType(t), installer.WithUrls(urls...), installer.WithTree(treePaths...), ) } repo, err = installer.GenerateRepository(opts...) helpers.CheckErr(err) if treetype != "" { treeFile.SetCompressionType(types.CompressionImplementation(treetype)) } if treeName != "" { treeFile.SetFileName(treeName) } if metatype != "" { metaFile.SetCompressionType(types.CompressionImplementation(metatype)) } if metaName != "" { metaFile.SetFileName(metaName) } repo.SetSnapshotID(snapshotID) repo.SetRepositoryFile(installer.REPOFILE_TREE_KEY, treeFile) repo.SetRepositoryFile(installer.REPOFILE_META_KEY, metaFile) err = repo.Write(util.DefaultContext, dst, reset, true) helpers.CheckErr(err) }, } func init() { path, err := os.Getwd() helpers.CheckErr(err) createrepoCmd.Flags().String("packages", filepath.Join(path, "build"), "Packages folder (output from build)") createrepoCmd.Flags().StringSliceP("tree", "t", []string{path}, "Path of the source trees to use.") createrepoCmd.Flags().String("output", filepath.Join(path, "build"), "Destination for generated archives. With 'docker' repository type, it should be an image reference (e.g 'foo/bar')") createrepoCmd.Flags().String("name", "luet", "Repository name") createrepoCmd.Flags().String("descr", "luet", "Repository description") createrepoCmd.Flags().StringSlice("urls", []string{}, "Repository URLs") createrepoCmd.Flags().String("type", "disk", "Repository type (disk, http, docker)") createrepoCmd.Flags().Bool("reset-revision", false, "Reset repository revision.") createrepoCmd.Flags().String("repo", "", "Use repository defined in configuration.") createrepoCmd.Flags().String("backend", "docker", "backend used (docker,img)") createrepoCmd.Flags().Bool("dockerfiles", false, "Read dockerfiles in tree as packages.") createrepoCmd.Flags().Bool("force-push", false, "Force overwrite of docker images if already present online") createrepoCmd.Flags().Bool("push-images", false, "Enable/Disable docker image push for docker repositories") createrepoCmd.Flags().Bool("from-metadata", false, "Consider metadata files from the packages folder while indexing the new tree") createrepoCmd.Flags().String("tree-compression", "gzip", "Compression alg: none, gzip, zstd") createrepoCmd.Flags().String("tree-filename", installer.TREE_TARBALL, "Repository tree filename") createrepoCmd.Flags().String("meta-compression", "none", "Compression alg: none, gzip, zstd") createrepoCmd.Flags().String("meta-filename", installer.REPOSITORY_METAFILE+".tar", "Repository metadata filename") createrepoCmd.Flags().Bool("from-repositories", false, "Consume the user-defined repositories to pull specfiles from") createrepoCmd.Flags().String("snapshot-id", "", "Unique ID to use when creating repository snapshots") RootCmd.AddCommand(createrepoCmd) }