Skip to content

Commit

Permalink
Add config registries subcommand
Browse files Browse the repository at this point in the history
* Deprecate add-registry, list_registries, remove_registry, and set_default_registry in favor of:
** pack config registries add
** pack config registries remove
** pack config registries list
** pack config registries deprecate [<registry>|--unset]

Signed-off-by: David Freilich <dfreilich@vmware.com>
  • Loading branch information
dfreilich committed Dec 23, 2020
1 parent b94eca8 commit 8d7e20c
Show file tree
Hide file tree
Showing 15 changed files with 770 additions and 148 deletions.
13 changes: 1 addition & 12 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type ConfigurableLogger interface {
WantVerbose(f bool)
}

//nolint:staticcheck
// NewPackCommand generates a Pack command
func NewPackCommand(logger ConfigurableLogger) (*cobra.Command, error) {
cobra.EnableCommandSorting = false
Expand Down Expand Up @@ -69,27 +70,17 @@ func NewPackCommand(logger ConfigurableLogger) (*cobra.Command, error) {

rootCmd.AddCommand(commands.InspectImage(logger, imagewriter.NewFactory(), cfg, &packClient))
rootCmd.AddCommand(commands.InspectBuildpack(logger, &cfg, &packClient))
//nolint:staticcheck
rootCmd.AddCommand(commands.SetRunImagesMirrors(logger, cfg))

rootCmd.AddCommand(commands.SetDefaultBuilder(logger, cfg, &packClient))
rootCmd.AddCommand(commands.InspectBuilder(logger, cfg, &packClient, builderwriter.NewFactory()))

//nolint:staticcheck
rootCmd.AddCommand(commands.SuggestBuilders(logger, &packClient))
//nolint:staticcheck
rootCmd.AddCommand(commands.TrustBuilder(logger, cfg))
//nolint:staticcheck
rootCmd.AddCommand(commands.UntrustBuilder(logger, cfg))
//nolint:staticcheck
rootCmd.AddCommand(commands.ListTrustedBuilders(logger, cfg))
//nolint:staticcheck
rootCmd.AddCommand(commands.CreateBuilder(logger, cfg, &packClient))

//nolint:staticcheck
rootCmd.AddCommand(commands.PackageBuildpack(logger, cfg, &packClient, buildpackage.NewConfigReader()))

//nolint:staticcheck
rootCmd.AddCommand(commands.SuggestStacks(logger))

rootCmd.AddCommand(commands.Version(logger, pack.Version))
Expand All @@ -98,11 +89,9 @@ func NewPackCommand(logger ConfigurableLogger) (*cobra.Command, error) {
if cfg.Experimental {
rootCmd.AddCommand(commands.AddBuildpackRegistry(logger, cfg, cfgPath))
rootCmd.AddCommand(commands.ListBuildpackRegistries(logger, cfg))
//nolint:staticcheck
rootCmd.AddCommand(commands.RegisterBuildpack(logger, cfg, &packClient))
rootCmd.AddCommand(commands.SetDefaultRegistry(logger, cfg, cfgPath))
rootCmd.AddCommand(commands.RemoveRegistry(logger, cfg, cfgPath))
//nolint:staticcheck
rootCmd.AddCommand(commands.YankBuildpack(logger, cfg, &packClient))
}

Expand Down
49 changes: 4 additions & 45 deletions internal/commands/add_registry.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
package commands

import (
"strings"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/buildpacks/pack/internal/slices"
"github.com/buildpacks/pack/internal/stringset"
"github.com/buildpacks/pack/internal/style"
"github.com/buildpacks/pack/registry"

"github.com/buildpacks/pack/internal/config"
"github.com/buildpacks/pack/logging"
)

// Deprecated: Use config registries add instead
func AddBuildpackRegistry(logger logging.Logger, cfg config.Config, cfgPath string) *cobra.Command {
var (
setDefault bool
Expand All @@ -29,53 +22,19 @@ func AddBuildpackRegistry(logger logging.Logger, cfg config.Config, cfgPath stri
Long: "A Buildpack Registry is a (still experimental) place to publish, store, and discover buildpacks. " +
"Users can add buildpacks registries using add-registry, and publish/yank buildpacks from it, as well as use those buildpacks when building applications.",
RunE: logError(logger, func(cmd *cobra.Command, args []string) error {
deprecationWarning(logger, "add-registry", "config registries add")
newRegistry := config.Registry{
Name: args[0],
URL: args[1],
Type: registryType,
}

if newRegistry.Name == config.OfficialRegistryName {
return errors.Errorf("%s is a reserved registry, please provide a different name",
style.Symbol(config.OfficialRegistryName))
}

err := addRegistry(newRegistry, setDefault, cfg, cfgPath)
if err != nil {
return err
}

logger.Infof("Successfully added %s to buildpack registries", style.Symbol(newRegistry.Name))

return nil
return addRegistryToConfig(logger, newRegistry, setDefault, cfg, cfgPath)
}),
}
cmd.Flags().BoolVar(&setDefault, "default", false, "Set this buildpack registry as the default")
cmd.Flags().StringVar(&registryType, "type", "github", "Type of buildpack registry [git|github]")
AddHelpFlag(cmd, "add-buildpack-registry")
AddHelpFlag(cmd, "add-registry")

return cmd
}

func addRegistry(newRegistry config.Registry, setDefault bool, cfg config.Config, cfgPath string) error {
if _, ok := stringset.FromSlice(registry.Types)[newRegistry.Type]; !ok {
return errors.Errorf(
"%s is not a valid type. Supported types are: %s.",
style.Symbol(newRegistry.Type),
strings.Join(slices.MapString(registry.Types, style.Symbol), ", "))
}

for _, r := range cfg.Registries {
if r.Name == newRegistry.Name {
return errors.Errorf(
"Buildpack registry %s already exists.",
style.Symbol(newRegistry.Name))
}
}

if setDefault {
cfg.DefaultRegistryName = newRegistry.Name
}
cfg.Registries = append(cfg.Registries, newRegistry)
return config.Write(cfg, cfgPath)
}
1 change: 1 addition & 0 deletions internal/commands/add_registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func testAddRegistryCommand(t *testing.T, when spec.G, it spec.S) {
assert.Equal(cfg.Registries[0].Type, "github")
assert.Equal(cfg.Registries[0].URL, "https://github.com/buildpacks/registry-index/")
assert.Equal(cfg.DefaultRegistryName, "")
assert.Contains(outBuf.String(), "been deprecated, please use 'pack config registries add' instead")
})
})

Expand Down
4 changes: 4 additions & 0 deletions internal/commands/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ func NewConfigCommand(logger logging.Logger, cfg config.Config, cfgPath string)
cmd.AddCommand(ConfigRunImagesMirrors(logger, cfg, cfgPath))
cmd.AddCommand(ConfigExperimental(logger, cfg, cfgPath))

if cfg.Experimental {
cmd.AddCommand(ConfigRegistries(logger, cfg, cfgPath))
}

AddHelpFlag(cmd, "config")
return cmd
}
Expand Down
173 changes: 173 additions & 0 deletions internal/commands/config_registries.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package commands

import (
"fmt"
"strings"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/buildpacks/pack/internal/config"
"github.com/buildpacks/pack/internal/slices"
"github.com/buildpacks/pack/internal/stringset"
"github.com/buildpacks/pack/internal/style"
"github.com/buildpacks/pack/logging"
"github.com/buildpacks/pack/registry"
)

var (
bpRegistryExplanation = "A Buildpack Registry is a (still experimental) place to publish, store, and discover buildpacks. "
)

var (
setDefault bool
registryType string
)

func ConfigRegistries(logger logging.Logger, cfg config.Config, cfgPath string) *cobra.Command {
cmd := &cobra.Command{
Use: "registries",
Aliases: []string{"registry", "registreis"},
Short: prependExperimental("Interact with registries"),
RunE: logError(logger, func(cmd *cobra.Command, args []string) error {
listRegistries(args, logger, cfg)
return nil
}),
}

addCmd := generateAdd("registries", logger, cfg, cfgPath, addRegistry)
addCmd.Args = cobra.ExactArgs(2)
addCmd.Example = "pack config registries add my-registry https://github.com/buildpacks/my-registry"
addCmd.Short = prependExperimental(addCmd.Short)
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."
addCmd.Flags().BoolVar(&setDefault, "default", false, "Set this buildpack registry as the default")
addCmd.Flags().StringVar(&registryType, "type", "github", "Type of buildpack registry [git|github]")
cmd.AddCommand(addCmd)

rmCmd := generateRemove("registries", logger, cfg, cfgPath, removeRegistry)
rmCmd.Example = "pack config registries remove myregistry"
rmCmd.Short = prependExperimental(rmCmd.Short)
rmCmd.Long = bpRegistryExplanation + "Users can remove registries from the config by using `pack config registries remove <registry>`"
cmd.AddCommand(rmCmd)

listCmd := generateListCmd("registries", logger, cfg, listRegistries)
listCmd.Example = "pack config registries list"
listCmd.Short = prependExperimental(listCmd.Short)
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`"
cmd.AddCommand(listCmd)

cmd.AddCommand(ConfigRegistriesDefault(logger, cfg, cfgPath))

AddHelpFlag(cmd, "registries")
return cmd
}

func addRegistry(args []string, logger logging.Logger, cfg config.Config, cfgPath string) error {
newRegistry := config.Registry{
Name: args[0],
URL: args[1],
Type: registryType,
}

return addRegistryToConfig(logger, newRegistry, setDefault, cfg, cfgPath)
}

func addRegistryToConfig(logger logging.Logger, newRegistry config.Registry, setDefault bool, cfg config.Config, cfgPath string) error {
if newRegistry.Name == config.OfficialRegistryName {
return errors.Errorf("%s is a reserved registry, please provide a different name",
style.Symbol(config.OfficialRegistryName))
}

if _, ok := stringset.FromSlice(registry.Types)[newRegistry.Type]; !ok {
return errors.Errorf("%s is not a valid type. Supported types are: %s.",
style.Symbol(newRegistry.Type),
strings.Join(slices.MapString(registry.Types, style.Symbol), ", "))
}

if registriesContains(config.GetRegistries(cfg), newRegistry.Name) {
return errors.Errorf("Buildpack registry %s already exists.",
style.Symbol(newRegistry.Name))
}

if setDefault {
cfg.DefaultRegistryName = newRegistry.Name
}
cfg.Registries = append(cfg.Registries, newRegistry)
if err := config.Write(cfg, cfgPath); err != nil {
return errors.Wrapf(err, "writing config to %s", cfgPath)
}

logger.Infof("Successfully added %s to registries", style.Symbol(newRegistry.Name))
return nil
}

func removeRegistry(args []string, logger logging.Logger, cfg config.Config, cfgPath string) error {
registryName := args[0]

if registryName == config.OfficialRegistryName {
return errors.Errorf("%s is a reserved registry name, please provide a different registry",
style.Symbol(config.OfficialRegistryName))
}

index := findRegistryIndex(cfg.Registries, registryName)
if index < 0 {
return errors.Errorf("registry %s does not exist", style.Symbol(registryName))
}

cfg.Registries = removeBPRegistry(index, cfg.Registries)
if cfg.DefaultRegistryName == registryName {
cfg.DefaultRegistryName = config.OfficialRegistryName
}

if err := config.Write(cfg, cfgPath); err != nil {
return errors.Wrapf(err, "writing config to %s", cfgPath)
}

logger.Infof("Successfully removed %s from registries", style.Symbol(registryName))
return nil
}

func listRegistries(args []string, logger logging.Logger, cfg config.Config) {
for _, currRegistry := range config.GetRegistries(cfg) {
isDefaultRegistry := (currRegistry.Name == cfg.DefaultRegistryName) ||
(currRegistry.Name == config.OfficialRegistryName && cfg.DefaultRegistryName == "")

logger.Info(fmtRegistry(
currRegistry,
isDefaultRegistry,
logger.IsVerbose()))
}
logging.Tip(logger, "Run %s to add additional registries", style.Symbol("pack config registries add"))
}

// Local private funcs
func fmtRegistry(registry config.Registry, isDefaultRegistry, isVerbose bool) string {
registryOutput := fmt.Sprintf(" %s", registry.Name)
if isDefaultRegistry {
registryOutput = fmt.Sprintf("* %s", registry.Name)
}
if isVerbose {
registryOutput = fmt.Sprintf("%-12s %s", registryOutput, registry.URL)
}

return registryOutput
}

func registriesContains(registries []config.Registry, registry string) bool {
return findRegistryIndex(registries, registry) != -1
}

func findRegistryIndex(registries []config.Registry, registryName string) int {
for index, r := range registries {
if r.Name == registryName {
return index
}
}

return -1
}

func removeBPRegistry(index int, registries []config.Registry) []config.Registry {
registries[index] = registries[len(registries)-1]
return registries[:len(registries)-1]
}
71 changes: 71 additions & 0 deletions internal/commands/config_registries_default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package commands

import (
"fmt"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/buildpacks/pack/internal/config"
"github.com/buildpacks/pack/internal/style"
"github.com/buildpacks/pack/logging"
)

func ConfigRegistriesDefault(logger logging.Logger, cfg config.Config, cfgPath string) *cobra.Command {
var unset bool

cmd := &cobra.Command{
Use: "default <name>",
Args: cobra.MaximumNArgs(1),
Short: prependExperimental("Set default registry"),
Example: "pack config registries default myregistry",
Long: bpRegistryExplanation + "\n\nYou can use this command to list, set, and unset a default registry, which will be used when looking for buildpacks:" +
"* To list your default registry, run `pack config registries default`.\n" +
"* To set your default registry, run `pack config registries default <registry-name>`.\n" +
"* To unset your default registry, run `pack config registries default --unset`.\n" +
fmt.Sprintf("Unsetting the default registry will reset the default-registry to be the official buildpacks registry, %s", style.Symbol(config.DefaultRegistry().URL)),
RunE: logError(logger, func(cmd *cobra.Command, args []string) error {
switch {
case unset:
if cfg.DefaultRegistryName == "" || cfg.DefaultRegistryName == config.OfficialRegistryName {
return errors.Errorf("Registry %s is a protected registry, and can be replaced as a default registry, but not removed entirely. "+
"To add a new registry and set as default, run `pack config registries add <registry-name> <registry-url> --default.\n"+
"To set an existing registry as default, call `pack config registries default <registry-name>`", style.Symbol(config.OfficialRegistryName))
}
oldRegistry := cfg.DefaultRegistryName
cfg.DefaultRegistryName = ""
if err := config.Write(cfg, cfgPath); err != nil {
return errors.Wrapf(err, "writing config to %s", cfgPath)
}
logger.Infof("Successfully unset default registry %s", style.Symbol(oldRegistry))
logger.Infof("Default registry has been set to %s", style.Symbol(config.OfficialRegistryName))
case len(args) == 0: //list
if cfg.DefaultRegistryName == "" {
cfg.DefaultRegistryName = config.OfficialRegistryName
}
logger.Infof("The current default registry is %s", style.Symbol(cfg.DefaultRegistryName))
default: // set
registryName := args[0]
if !registriesContains(config.GetRegistries(cfg), registryName) {
return errors.Errorf("no registry with the name %s exists", style.Symbol(registryName))
}

if cfg.DefaultRegistryName != registryName {
cfg.DefaultRegistryName = registryName
err := config.Write(cfg, cfgPath)
if err != nil {
return errors.Wrapf(err, "writing config to %s", cfgPath)
}
}

logger.Infof("Successfully set %s as the default registry", style.Symbol(registryName))
}

return nil
}),
}

cmd.Flags().BoolVarP(&unset, "unset", "u", false, "Unset the current default registry, and set it to the official buildpacks registry")
AddHelpFlag(cmd, "default")
return cmd
}
Loading

0 comments on commit 8d7e20c

Please sign in to comment.