feat: Add ability to push to multiple registries (#303)

Co-authored-by: Robert Kaussow <xoxys@rknet.org>
This commit is contained in:
Maxim Slipenko 2023-08-09 12:35:58 +03:00 committed by GitHub
parent 56914d2332
commit 13c17d9c3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 88 additions and 9 deletions

View File

@ -95,6 +95,36 @@ steps:
tags: latest tags: latest
``` ```
**Multiple registries:**
```yaml
kind: pipeline
name: default
steps:
- name: docker
image: thegeeklab/drone-docker-buildx:23
privileged: true
environment:
DOCKER_REGISTRY_PASSWORD:
from_secret: docker_registry_password
GITHUB_REGISTRY_PASSWORD:
from_secret: github_registry_password
settings:
repo:
- octocat/example
- ghcr.io/octocat/example
tags: latest
registries: |
registries:
- username: "octocat"
password: "$DOCKER_REGISTRY_PASSWORD"
- registry: "ghcr.io"
username: "octocat"
password: "$GITHUB_REGISTRY_PASSWORD"
```
## Build ## Build
Build the binary with the following command: Build the binary with the following command:

View File

@ -208,7 +208,7 @@ properties:
description: | description: |
Repository name for the image. If the image is to be pushed to registries other than the default DockerHub, Repository name for the image. If the image is to be pushed to registries other than the default DockerHub,
it is necessary to set `repo` as fully-qualified name. it is necessary to set `repo` as fully-qualified name.
type: string type: list
required: false required: false
- name: registry - name: registry
@ -293,3 +293,8 @@ properties:
This should be used with caution and avoided whenever possible. This should be used with caution and avoided whenever possible.
type: list type: list
required: false required: false
- name: registries
description: Credentials for multiple registries described in YAML format. Check out the Examples for more information.
type: string
required: false

View File

@ -235,7 +235,7 @@ func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
Destination: &settings.Build.Compress, Destination: &settings.Build.Compress,
Category: category, Category: category,
}, },
&cli.StringFlag{ &cli.StringSliceFlag{
Name: "repo", Name: "repo",
EnvVars: []string{"PLUGIN_REPO"}, EnvVars: []string{"PLUGIN_REPO"},
Usage: "repository name for the image", Usage: "repository name for the image",
@ -328,5 +328,12 @@ func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
Value: &drone.StringSliceFlag{}, Value: &drone.StringSliceFlag{},
Category: category, Category: category,
}, },
&cli.StringFlag{
Name: "docker.registries",
EnvVars: []string{"PLUGIN_REGISTRIES"},
Usage: "credentials for registries",
Destination: &settings.Login.RegistriesYaml,
Category: category,
},
} }
} }

1
go.mod
View File

@ -15,4 +15,5 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
gopkg.in/yaml.v3 v3.0.1
) )

View File

@ -11,7 +11,7 @@ import (
) )
// helper function to create the docker login command. // helper function to create the docker login command.
func commandLogin(login Login) *execabs.Cmd { func commandLogin(login RegistryData) *execabs.Cmd {
if login.Email != "" { if login.Email != "" {
return commandLoginEmail(login) return commandLoginEmail(login)
} }
@ -28,7 +28,7 @@ func commandLogin(login Login) *execabs.Cmd {
) )
} }
func commandLoginEmail(login Login) *execabs.Cmd { func commandLoginEmail(login RegistryData) *execabs.Cmd {
args := []string{ args := []string{
"login", "login",
"-u", login.Username, "-u", login.Username,
@ -140,8 +140,10 @@ func commandBuild(build Build, dryrun bool) *execabs.Cmd {
args = append(args, "--platform", strings.Join(build.Platforms.Value(), ",")) args = append(args, "--platform", strings.Join(build.Platforms.Value(), ","))
} }
for _, arg := range build.Tags.Value() { for _, repo := range build.Repo.Value() {
args = append(args, "-t", fmt.Sprintf("%s:%s", build.Repo, arg)) for _, arg := range build.Tags.Value() {
args = append(args, "-t", fmt.Sprintf("%s:%s", repo, arg))
}
} }
for _, arg := range build.ExtraTags.Value() { for _, arg := range build.ExtraTags.Value() {

View File

@ -9,6 +9,7 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"golang.org/x/sys/execabs" "golang.org/x/sys/execabs"
"gopkg.in/yaml.v3"
) )
// Daemon defines Docker daemon parameters. // Daemon defines Docker daemon parameters.
@ -31,11 +32,20 @@ type Daemon struct {
// Login defines Docker login parameters. // Login defines Docker login parameters.
type Login struct { type Login struct {
RegistryData
Config string // Docker Auth Config
RegistriesYaml string // Docker Auth with YAML config
}
type RegistryData struct {
Registry string // Docker registry address Registry string // Docker registry address
Username string // Docker registry username Username string // Docker registry username
Password string // Docker registry password Password string // Docker registry password
Email string // Docker registry email Email string // Docker registry email
Config string // Docker Auth Config }
type RegistriesYaml struct {
Registries []RegistryData `yaml:"registries"`
} }
// Build defines Docker build parameters. // Build defines Docker build parameters.
@ -56,7 +66,7 @@ type Build struct {
CacheFrom []string // Docker build cache-from CacheFrom []string // Docker build cache-from
CacheTo string // Docker build cache-to CacheTo string // Docker build cache-to
Compress bool // Docker build compress Compress bool // Docker build compress
Repo string // Docker build repository Repo cli.StringSlice // Docker build repositories
NoCache bool // Docker build no-cache NoCache bool // Docker build no-cache
AddHost cli.StringSlice // Docker build add-host AddHost cli.StringSlice // Docker build add-host
Quiet bool // Docker build quiet Quiet bool // Docker build quiet
@ -167,7 +177,7 @@ func (p *Plugin) Execute() error {
// login to the Docker registry // login to the Docker registry
if p.settings.Login.Password != "" { if p.settings.Login.Password != "" {
cmd := commandLogin(p.settings.Login) cmd := commandLogin(p.settings.Login.RegistryData)
err := cmd.Run() err := cmd.Run()
if err != nil { if err != nil {
@ -175,6 +185,28 @@ func (p *Plugin) Execute() error {
} }
} }
if p.settings.Login.RegistriesYaml != "" {
var t RegistriesYaml
err := yaml.Unmarshal([]byte(p.settings.Login.RegistriesYaml), &t)
if err != nil {
return fmt.Errorf("error unmarshal registries: %w", err)
}
for _, registryData := range t.Registries {
if registryData.Registry == "" {
registryData.Registry = "https://index.docker.io/v1/"
}
cmd := commandLogin(registryData)
err := cmd.Run()
if err != nil {
return fmt.Errorf("error authenticating: %w", err)
}
}
}
if p.settings.Daemon.BuildkitConfig != "" { if p.settings.Daemon.BuildkitConfig != "" {
err := os.WriteFile(buildkitConfig, []byte(p.settings.Daemon.BuildkitConfig), strictFilePerm) err := os.WriteFile(buildkitConfig, []byte(p.settings.Daemon.BuildkitConfig), strictFilePerm)
if err != nil { if err != nil {
@ -185,6 +217,8 @@ func (p *Plugin) Execute() error {
switch { switch {
case p.settings.Login.Password != "": case p.settings.Login.Password != "":
logrus.Info("Detected registry credentials") logrus.Info("Detected registry credentials")
case p.settings.Login.RegistriesYaml != "":
logrus.Info("Detected multiple registry credentials")
case p.settings.Login.Config != "": case p.settings.Login.Config != "":
logrus.Info("Detected registry credentials file") logrus.Info("Detected registry credentials file")
default: default: