github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/cmd/cmd.go (about) 1 package cmd 2 3 import ( 4 "github.com/heroku/color" 5 "github.com/pkg/errors" 6 "github.com/spf13/cobra" 7 8 "github.com/buildpacks/pack/buildpackage" 9 builderwriter "github.com/buildpacks/pack/internal/builder/writer" 10 "github.com/buildpacks/pack/internal/commands" 11 "github.com/buildpacks/pack/internal/config" 12 imagewriter "github.com/buildpacks/pack/internal/inspectimage/writer" 13 "github.com/buildpacks/pack/internal/term" 14 "github.com/buildpacks/pack/pkg/client" 15 "github.com/buildpacks/pack/pkg/logging" 16 ) 17 18 // ConfigurableLogger defines behavior required by the PackCommand 19 type ConfigurableLogger interface { 20 logging.Logger 21 WantTime(f bool) 22 WantQuiet(f bool) 23 WantVerbose(f bool) 24 } 25 26 // NewPackCommand generates a Pack command 27 // 28 //nolint:staticcheck 29 func NewPackCommand(logger ConfigurableLogger) (*cobra.Command, error) { 30 cobra.EnableCommandSorting = false 31 cfg, cfgPath, err := initConfig() 32 if err != nil { 33 return nil, err 34 } 35 36 packClient, err := initClient(logger, cfg) 37 if err != nil { 38 return nil, err 39 } 40 41 rootCmd := &cobra.Command{ 42 Use: "pack", 43 Short: "CLI for building apps using Cloud Native Buildpacks", 44 PersistentPreRun: func(cmd *cobra.Command, args []string) { 45 if fs := cmd.Flags(); fs != nil { 46 if forceColor, err := fs.GetBool("force-color"); err == nil && !forceColor { 47 if flag, err := fs.GetBool("no-color"); err == nil && flag { 48 color.Disable(flag) 49 } 50 51 _, canDisplayColor := term.IsTerminal(logging.GetWriterForLevel(logger, logging.InfoLevel)) 52 if !canDisplayColor { 53 color.Disable(true) 54 } 55 } 56 if flag, err := fs.GetBool("quiet"); err == nil { 57 logger.WantQuiet(flag) 58 } 59 if flag, err := fs.GetBool("verbose"); err == nil { 60 logger.WantVerbose(flag) 61 } 62 if flag, err := fs.GetBool("timestamps"); err == nil { 63 logger.WantTime(flag) 64 } 65 } 66 }, 67 } 68 69 rootCmd.PersistentFlags().Bool("no-color", false, "Disable color output") 70 rootCmd.PersistentFlags().Bool("force-color", false, "Force color output") 71 rootCmd.PersistentFlags().Bool("timestamps", false, "Enable timestamps in output") 72 rootCmd.PersistentFlags().BoolP("quiet", "q", false, "Show less output") 73 rootCmd.PersistentFlags().BoolP("verbose", "v", false, "Show more output") 74 rootCmd.Flags().Bool("version", false, "Show current 'pack' version") 75 76 commands.AddHelpFlag(rootCmd, "pack") 77 78 rootCmd.AddCommand(commands.Build(logger, cfg, packClient)) 79 rootCmd.AddCommand(commands.NewBuilderCommand(logger, cfg, packClient)) 80 rootCmd.AddCommand(commands.NewBuildpackCommand(logger, cfg, packClient, buildpackage.NewConfigReader())) 81 rootCmd.AddCommand(commands.NewExtensionCommand(logger, cfg, packClient, buildpackage.NewConfigReader())) 82 rootCmd.AddCommand(commands.NewConfigCommand(logger, cfg, cfgPath, packClient)) 83 rootCmd.AddCommand(commands.InspectImage(logger, imagewriter.NewFactory(), cfg, packClient)) 84 rootCmd.AddCommand(commands.NewStackCommand(logger)) 85 rootCmd.AddCommand(commands.Rebase(logger, cfg, packClient)) 86 rootCmd.AddCommand(commands.NewSBOMCommand(logger, cfg, packClient)) 87 88 rootCmd.AddCommand(commands.InspectBuildpack(logger, cfg, packClient)) 89 rootCmd.AddCommand(commands.InspectBuilder(logger, cfg, packClient, builderwriter.NewFactory())) 90 91 rootCmd.AddCommand(commands.SetDefaultBuilder(logger, cfg, cfgPath, packClient)) 92 rootCmd.AddCommand(commands.SetRunImagesMirrors(logger, cfg, cfgPath)) 93 rootCmd.AddCommand(commands.SuggestBuilders(logger, packClient)) 94 rootCmd.AddCommand(commands.TrustBuilder(logger, cfg, cfgPath)) 95 rootCmd.AddCommand(commands.UntrustBuilder(logger, cfg, cfgPath)) 96 rootCmd.AddCommand(commands.ListTrustedBuilders(logger, cfg)) 97 rootCmd.AddCommand(commands.CreateBuilder(logger, cfg, packClient)) 98 rootCmd.AddCommand(commands.PackageBuildpack(logger, cfg, packClient, buildpackage.NewConfigReader())) 99 100 if cfg.Experimental { 101 rootCmd.AddCommand(commands.AddBuildpackRegistry(logger, cfg, cfgPath)) 102 rootCmd.AddCommand(commands.ListBuildpackRegistries(logger, cfg)) 103 rootCmd.AddCommand(commands.RegisterBuildpack(logger, cfg, packClient)) 104 rootCmd.AddCommand(commands.SetDefaultRegistry(logger, cfg, cfgPath)) 105 rootCmd.AddCommand(commands.RemoveRegistry(logger, cfg, cfgPath)) 106 rootCmd.AddCommand(commands.YankBuildpack(logger, cfg, packClient)) 107 rootCmd.AddCommand(commands.NewManifestCommand(logger, packClient)) 108 } 109 110 packHome, err := config.PackHome() 111 if err != nil { 112 return nil, err 113 } 114 115 rootCmd.AddCommand(commands.CompletionCommand(logger, packHome)) 116 rootCmd.AddCommand(commands.Report(logger, packClient.Version(), cfgPath)) 117 rootCmd.AddCommand(commands.Version(logger, packClient.Version())) 118 119 rootCmd.Version = packClient.Version() 120 rootCmd.SetVersionTemplate(`{{.Version}}{{"\n"}}`) 121 rootCmd.SetOut(logging.GetWriterForLevel(logger, logging.InfoLevel)) 122 rootCmd.SetErr(logging.GetWriterForLevel(logger, logging.ErrorLevel)) 123 124 return rootCmd, nil 125 } 126 127 func initConfig() (config.Config, string, error) { 128 path, err := config.DefaultConfigPath() 129 if err != nil { 130 return config.Config{}, "", errors.Wrap(err, "getting config path") 131 } 132 133 cfg, err := config.Read(path) 134 if err != nil { 135 return config.Config{}, "", errors.Wrap(err, "reading pack config") 136 } 137 return cfg, path, nil 138 } 139 140 func initClient(logger logging.Logger, cfg config.Config) (*client.Client, error) { 141 if err := client.ProcessDockerContext(logger); err != nil { 142 return nil, err 143 } 144 145 dc, err := tryInitSSHDockerClient() 146 if err != nil { 147 return nil, err 148 } 149 return client.NewClient(client.WithLogger(logger), client.WithExperimental(cfg.Experimental), client.WithRegistryMirrors(cfg.RegistryMirrors), client.WithDockerClient(dc)) 150 }