diff --git a/cli/catalogue/catalogue.go b/cli/catalogue/catalogue.go index fc3fa6af..a1e7b3af 100644 --- a/cli/catalogue/catalogue.go +++ b/cli/catalogue/catalogue.go @@ -59,13 +59,15 @@ var CatalogueSkipList = map[string]bool{ var catalogueGenerateCommand = &cli.Command{ Name: "generate", Aliases: []string{"g"}, - Usage: "Generate a new copy of the catalogue", + Usage: "Generate a new copy of the recipe catalogue", Flags: []cli.Flag{ internal.PushFlag, internal.CommitFlag, internal.CommitMessageFlag, internal.DryFlag, internal.SkipUpdatesFlag, + internal.RegistryUsernameFlag, + internal.RegistryPasswordFlag, }, Description: ` This command generates a new copy of the recipe catalogue which can be found on: @@ -73,8 +75,8 @@ This command generates a new copy of the recipe catalogue which can be found on: https://recipes.coopcloud.tech It polls the entire git.coopcloud.tech/coop-cloud/... recipe repository -listing, parses README and tags to produce recipe metadata and produces a -apps.json file which is placed in your ~/.abra/catalogue/recipes.json. +listing, parses README.md and git tags of those repositories to produce recipe +metadata and produces a recipes JSON file. It is possible to generate new metadata for a single recipe by passing . The existing local catalogue will be updated, not overwritten. @@ -84,6 +86,9 @@ A new catalogue copy can be published to the recipes repository by passing the https://git.coopcloud.tech/coop-cloud/recipes +It is quite easy to get rate limited by Docker Hub when running this command. +If you have a Hub account you can have Abra log you in to avoid this. Pass +"--username" and "--password". `, ArgsUsage: "[]", Action: func(c *cli.Context) error { @@ -133,7 +138,11 @@ A new catalogue copy can be published to the recipes repository by passing the continue } - versions, err := catalogue.GetRecipeVersions(recipeMeta.Name) + versions, err := catalogue.GetRecipeVersions( + recipeMeta.Name, + internal.RegistryUsername, + internal.RegistryPassword, + ) if err != nil { logrus.Fatal(err) } diff --git a/cli/internal/common.go b/cli/internal/common.go index 8450a92c..b0523dff 100644 --- a/cli/internal/common.go +++ b/cli/internal/common.go @@ -455,6 +455,26 @@ var SkipUpdatesFlag = &cli.BoolFlag{ Destination: &SkipUpdates, } +var RegistryUsername string +var RegistryUsernameFlag = &cli.StringFlag{ + Name: "username", + Aliases: []string{"u"}, + Value: "", + Usage: "Registry username", + EnvVars: []string{"REGISTRY_USERNAME"}, + Destination: &RegistryUsername, +} + +var RegistryPassword string +var RegistryPasswordFlag = &cli.StringFlag{ + Name: "password", + Aliases: []string{"p"}, + Value: "", + Usage: "Registry password", + EnvVars: []string{"REGISTRY_PASSWORD"}, + Destination: &RegistryUsername, +} + // SSHFailMsg is a hopefully helpful SSH failure message var SSHFailMsg = ` Woops, Abra is unable to connect to connect to %s. diff --git a/pkg/catalogue/catalogue.go b/pkg/catalogue/catalogue.go index f6806e06..39745131 100644 --- a/pkg/catalogue/catalogue.go +++ b/pkg/catalogue/catalogue.go @@ -362,7 +362,7 @@ func ReadReposMetadata() (RepoCatalogue, error) { } // GetRecipeVersions retrieves all recipe versions. -func GetRecipeVersions(recipeName string) (RecipeVersions, error) { +func GetRecipeVersions(recipeName, registryUsername, registryPassword string) (RecipeVersions, error) { versions := RecipeVersions{} recipeDir := path.Join(config.RECIPES_DIR, recipeName) @@ -439,7 +439,7 @@ func GetRecipeVersions(recipeName string) (RecipeVersions, error) { if digest, exists = queryCache[img]; !exists { logrus.Debugf("looking up image: %s from %s", img, path) var err error - digest, err = client.GetTagDigest(cl, img) + digest, err = client.GetTagDigest(cl, img, registryUsername, registryPassword) if err != nil { logrus.Warn(err) continue diff --git a/pkg/client/registry.go b/pkg/client/registry.go index 5780b054..2a57039c 100644 --- a/pkg/client/registry.go +++ b/pkg/client/registry.go @@ -6,7 +6,6 @@ import ( "fmt" "io/ioutil" "net/http" - "os" "strings" "coopcloud.tech/abra/pkg/web" @@ -42,7 +41,7 @@ func basicAuth(username, password string) string { } // getRegv2Token retrieves a registry v2 authentication token. -func getRegv2Token(cl *client.Client, image reference.Named) (string, error) { +func getRegv2Token(cl *client.Client, image reference.Named, registryUsername, registryPassword string) (string, error) { img := reference.Path(image) tokenURL := "https://auth.docker.io/token" values := fmt.Sprintf("service=registry.docker.io&scope=repository:%s:pull", img) @@ -53,11 +52,10 @@ func getRegv2Token(cl *client.Client, image reference.Named) (string, error) { return "", err } - username, userOk := os.LookupEnv("DOCKER_USERNAME") - password, passOk := os.LookupEnv("DOCKER_PASSWORD") - if userOk && passOk { - logrus.Debugf("using docker log in credentials for registry token request") - req.Header.Add("Authorization", fmt.Sprintf("Basic %s", basicAuth(username, password))) + if registryUsername != "" && registryPassword != "" { + logrus.Debugf("using registry log in credentials for token request") + auth := basicAuth(registryUsername, registryPassword) + req.Header.Add("Authorization", fmt.Sprintf("Basic %s", auth)) } client := web.NewHTTPRetryClient() @@ -94,7 +92,7 @@ func getRegv2Token(cl *client.Client, image reference.Named) (string, error) { } // GetTagDigest retrieves an image digest from a v2 registry -func GetTagDigest(cl *client.Client, image reference.Named) (string, error) { +func GetTagDigest(cl *client.Client, image reference.Named, registryUsername, registryPassword string) (string, error) { img := reference.Path(image) tag := image.(reference.NamedTagged).Tag() manifestURL := fmt.Sprintf("https://index.docker.io/v2/%s/manifests/%s", img, tag) @@ -104,7 +102,7 @@ func GetTagDigest(cl *client.Client, image reference.Named) (string, error) { return "", err } - token, err := getRegv2Token(cl, image) + token, err := getRegv2Token(cl, image, registryUsername, registryPassword) if err != nil { return "", err }