github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/internal/commands/config_registries.go (about)

     1  package commands
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/pkg/errors"
     8  	"github.com/spf13/cobra"
     9  
    10  	"github.com/buildpacks/pack/internal/config"
    11  	"github.com/buildpacks/pack/internal/slices"
    12  	"github.com/buildpacks/pack/internal/stringset"
    13  	"github.com/buildpacks/pack/internal/style"
    14  	"github.com/buildpacks/pack/pkg/logging"
    15  	"github.com/buildpacks/pack/registry"
    16  )
    17  
    18  var (
    19  	bpRegistryExplanation = "A Buildpack Registry is a (still experimental) place to publish, store, and discover buildpacks. "
    20  )
    21  
    22  var (
    23  	setDefault   bool
    24  	registryType string
    25  )
    26  
    27  func ConfigRegistries(logger logging.Logger, cfg config.Config, cfgPath string) *cobra.Command {
    28  	cmd := &cobra.Command{
    29  		Use:     "registries",
    30  		Aliases: []string{"registry", "registreis"},
    31  		Short:   "List, add and remove registries",
    32  		Long:    bpRegistryExplanation + "\nYou can use the attached commands to list, add, and remove registries from your config",
    33  		RunE: logError(logger, func(cmd *cobra.Command, args []string) error {
    34  			listRegistries(args, logger, cfg)
    35  			return nil
    36  		}),
    37  	}
    38  
    39  	listCmd := generateListCmd("registries", logger, cfg, listRegistries)
    40  	listCmd.Example = "pack config registries list"
    41  	listCmd.Long = bpRegistryExplanation + "List Registries saved in the pack config.\n\nShow the registries that are either added by default or have been explicitly added by using `pack config registries add`"
    42  	cmd.AddCommand(listCmd)
    43  
    44  	addCmd := generateAdd("registries", logger, cfg, cfgPath, addRegistry)
    45  	addCmd.Args = cobra.ExactArgs(2)
    46  	addCmd.Example = "pack config registries add my-registry https://github.com/buildpacks/my-registry"
    47  	addCmd.Long = bpRegistryExplanation + "Users can add registries from the config by using registries remove, and publish/yank buildpacks from it, as well as use those buildpacks when building applications."
    48  	addCmd.Flags().BoolVar(&setDefault, "default", false, "Set this buildpack registry as the default")
    49  	addCmd.Flags().StringVar(&registryType, "type", "github", "Type of buildpack registry [git|github]")
    50  	cmd.AddCommand(addCmd)
    51  
    52  	rmCmd := generateRemove("registries", logger, cfg, cfgPath, removeRegistry)
    53  	rmCmd.Example = "pack config registries remove myregistry"
    54  	rmCmd.Long = bpRegistryExplanation + "Users can remove registries from the config by using `pack config registries remove <registry>`"
    55  	cmd.AddCommand(rmCmd)
    56  
    57  	cmd.AddCommand(ConfigRegistriesDefault(logger, cfg, cfgPath))
    58  
    59  	AddHelpFlag(cmd, "registries")
    60  	return cmd
    61  }
    62  
    63  func addRegistry(args []string, logger logging.Logger, cfg config.Config, cfgPath string) error {
    64  	newRegistry := config.Registry{
    65  		Name: args[0],
    66  		URL:  args[1],
    67  		Type: registryType,
    68  	}
    69  
    70  	return addRegistryToConfig(logger, newRegistry, setDefault, cfg, cfgPath)
    71  }
    72  
    73  func addRegistryToConfig(logger logging.Logger, newRegistry config.Registry, setDefault bool, cfg config.Config, cfgPath string) error {
    74  	if newRegistry.Name == config.OfficialRegistryName {
    75  		return errors.Errorf("%s is a reserved registry, please provide a different name",
    76  			style.Symbol(config.OfficialRegistryName))
    77  	}
    78  
    79  	if _, ok := stringset.FromSlice(registry.Types)[newRegistry.Type]; !ok {
    80  		return errors.Errorf("%s is not a valid type. Supported types are: %s.",
    81  			style.Symbol(newRegistry.Type),
    82  			strings.Join(slices.MapString(registry.Types, style.Symbol), ", "))
    83  	}
    84  
    85  	if registriesContains(config.GetRegistries(cfg), newRegistry.Name) {
    86  		return errors.Errorf("Buildpack registry %s already exists.",
    87  			style.Symbol(newRegistry.Name))
    88  	}
    89  
    90  	if setDefault {
    91  		cfg.DefaultRegistryName = newRegistry.Name
    92  	}
    93  	cfg.Registries = append(cfg.Registries, newRegistry)
    94  	if err := config.Write(cfg, cfgPath); err != nil {
    95  		return errors.Wrapf(err, "writing config to %s", cfgPath)
    96  	}
    97  
    98  	logger.Infof("Successfully added %s to registries", style.Symbol(newRegistry.Name))
    99  	return nil
   100  }
   101  
   102  func removeRegistry(args []string, logger logging.Logger, cfg config.Config, cfgPath string) error {
   103  	registryName := args[0]
   104  
   105  	if registryName == config.OfficialRegistryName {
   106  		return errors.Errorf("%s is a reserved registry name, please provide a different registry",
   107  			style.Symbol(config.OfficialRegistryName))
   108  	}
   109  
   110  	index := findRegistryIndex(cfg.Registries, registryName)
   111  	if index < 0 {
   112  		return errors.Errorf("registry %s does not exist", style.Symbol(registryName))
   113  	}
   114  
   115  	cfg.Registries = removeBPRegistry(index, cfg.Registries)
   116  	if cfg.DefaultRegistryName == registryName {
   117  		cfg.DefaultRegistryName = config.OfficialRegistryName
   118  	}
   119  
   120  	if err := config.Write(cfg, cfgPath); err != nil {
   121  		return errors.Wrapf(err, "writing config to %s", cfgPath)
   122  	}
   123  
   124  	logger.Infof("Successfully removed %s from registries", style.Symbol(registryName))
   125  	return nil
   126  }
   127  
   128  func listRegistries(args []string, logger logging.Logger, cfg config.Config) {
   129  	for _, currRegistry := range config.GetRegistries(cfg) {
   130  		isDefaultRegistry := (currRegistry.Name == cfg.DefaultRegistryName) ||
   131  			(currRegistry.Name == config.OfficialRegistryName && cfg.DefaultRegistryName == "")
   132  
   133  		logger.Info(fmtRegistry(
   134  			currRegistry,
   135  			isDefaultRegistry,
   136  			logger.IsVerbose()))
   137  	}
   138  	logging.Tip(logger, "Run %s to add additional registries", style.Symbol("pack config registries add"))
   139  }
   140  
   141  // Local private funcs
   142  func fmtRegistry(registry config.Registry, isDefaultRegistry, isVerbose bool) string {
   143  	registryOutput := fmt.Sprintf("  %s", registry.Name)
   144  	if isDefaultRegistry {
   145  		registryOutput = fmt.Sprintf("* %s", registry.Name)
   146  	}
   147  	if isVerbose {
   148  		registryOutput = fmt.Sprintf("%-12s %s", registryOutput, registry.URL)
   149  	}
   150  
   151  	return registryOutput
   152  }
   153  
   154  func registriesContains(registries []config.Registry, registry string) bool {
   155  	return findRegistryIndex(registries, registry) != -1
   156  }
   157  
   158  func findRegistryIndex(registries []config.Registry, registryName string) int {
   159  	for index, r := range registries {
   160  		if r.Name == registryName {
   161  			return index
   162  		}
   163  	}
   164  
   165  	return -1
   166  }
   167  
   168  func removeBPRegistry(index int, registries []config.Registry) []config.Registry {
   169  	registries[index] = registries[len(registries)-1]
   170  	return registries[:len(registries)-1]
   171  }