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  }