executor: add init image config authentication options

Add config options to define docker registry authentication for init image
pulling.
This commit is contained in:
Simone Gotti 2021-05-25 10:20:20 +02:00
parent 42a07856cc
commit d9d6b995da
6 changed files with 96 additions and 22 deletions

View File

@ -120,6 +120,28 @@ type Executor struct {
type InitImage struct {
Image string `yaml:"image"`
Auth *DockerRegistryAuth `yaml:"auth"`
}
type DockerRegistryAuthType string
const (
DockerRegistryAuthTypeBasic DockerRegistryAuthType = "basic"
DockerRegistryAuthTypeEncodedAuth DockerRegistryAuthType = "encodedauth"
)
type DockerRegistryAuth struct {
Type DockerRegistryAuthType `json:"type"`
// basic auth
Username string `json:"username"`
Password string `json:"password"`
// encoded auth string
Auth string `json:"auth"`
// future auths like aws ecr auth
}
type Configstore struct {

View File

@ -48,11 +48,12 @@ type DockerDriver struct {
client *client.Client
toolboxPath string
initImage string
initDockerConfig *registry.DockerConfig
executorID string
arch types.Arch
}
func NewDockerDriver(logger *zap.Logger, executorID, toolboxPath, initImage string) (*DockerDriver, error) {
func NewDockerDriver(logger *zap.Logger, executorID, toolboxPath, initImage string, initDockerConfig *registry.DockerConfig) (*DockerDriver, error) {
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("1.26"))
if err != nil {
return nil, err
@ -63,6 +64,7 @@ func NewDockerDriver(logger *zap.Logger, executorID, toolboxPath, initImage stri
client: cli,
toolboxPath: toolboxPath,
initImage: initImage,
initDockerConfig: initDockerConfig,
executorID: executorID,
arch: types.ArchFromString(runtime.GOARCH),
}, nil
@ -73,7 +75,7 @@ func (d *DockerDriver) Setup(ctx context.Context) error {
}
func (d *DockerDriver) createToolboxVolume(ctx context.Context, podID string, out io.Writer) (*dockertypes.Volume, error) {
if err := d.fetchImage(ctx, d.initImage, false, nil, out); err != nil {
if err := d.fetchImage(ctx, d.initImage, false, d.initDockerConfig, out); err != nil {
return nil, err
}

View File

@ -44,7 +44,7 @@ func TestDockerPod(t *testing.T) {
initImage := "busybox:stable"
d, err := NewDockerDriver(logger, "executorid01", toolboxPath, initImage)
d, err := NewDockerDriver(logger, "executorid01", toolboxPath, initImage, nil)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}

View File

@ -26,6 +26,7 @@ import (
"strings"
"time"
"agola.io/agola/internal/services/executor/registry"
"agola.io/agola/internal/util"
"agola.io/agola/services/types"
@ -75,6 +76,7 @@ type K8sDriver struct {
client *kubernetes.Clientset
toolboxPath string
initImage string
initDockerConfig *registry.DockerConfig
namespace string
executorID string
executorsGroupID string
@ -96,7 +98,7 @@ type K8sPod struct {
initVolumeDir string
}
func NewK8sDriver(logger *zap.Logger, executorID, toolboxPath, initImage string) (*K8sDriver, error) {
func NewK8sDriver(logger *zap.Logger, executorID, toolboxPath, initImage string, initDockerConfig *registry.DockerConfig) (*K8sDriver, error) {
kubeClientConfig := NewKubeClientConfig("", "", "")
kubecfg, err := kubeClientConfig.ClientConfig()
if err != nil {
@ -118,6 +120,7 @@ func NewK8sDriver(logger *zap.Logger, executorID, toolboxPath, initImage string)
client: kubecli,
toolboxPath: toolboxPath,
initImage: initImage,
initDockerConfig: initDockerConfig,
namespace: namespace,
executorID: executorID,
k8sLabelArch: corev1.LabelArchStable,
@ -324,13 +327,18 @@ func (d *K8sDriver) NewPod(ctx context.Context, podConfig *PodConfig, out io.Wri
labels[executorIDKey] = d.executorID
labels[executorsGroupIDKey] = d.executorsGroupID
// pod and secret name, based on pod id
name := podNamePrefix + podConfig.ID
dockerconfigj, err := json.Marshal(podConfig.DockerConfig)
if err != nil {
return nil, err
}
// pod and secret name, based on pod id
name := podNamePrefix + podConfig.ID
initDockerconfigj, err := json.Marshal(d.initDockerConfig)
if err != nil {
return nil, err
}
// secret that hold the docker registry auth
secret := &corev1.Secret{
@ -339,7 +347,7 @@ func (d *K8sDriver) NewPod(ctx context.Context, podConfig *PodConfig, out io.Wri
Labels: labels,
},
Data: map[string][]byte{
".dockerconfigjson": dockerconfigj,
".dockerconfigjson": initDockerconfigj,
},
Type: corev1.SecretTypeDockerConfigJson,
}
@ -488,6 +496,28 @@ func (d *K8sDriver) NewPod(ctx context.Context, podConfig *PodConfig, out io.Wri
fmt.Fprintf(out, "init container ready\n")
// Remove init container docker auth so it won't be used by user defined containers
dur := int64(0)
if err := secretClient.Delete(name, &metav1.DeleteOptions{GracePeriodSeconds: &dur}); err != nil {
return nil, err
}
secret = &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: labels,
},
Data: map[string][]byte{
".dockerconfigjson": dockerconfigj,
},
Type: corev1.SecretTypeDockerConfigJson,
}
_, err = secretClient.Create(secret)
if err != nil {
return nil, err
}
coreclient, err := corev1client.NewForConfig(d.restconfig)
if err != nil {
return nil, err

View File

@ -43,7 +43,7 @@ func TestK8sPod(t *testing.T) {
initImage := "busybox:stable"
d, err := NewK8sDriver(logger, "executorid01", toolboxPath, initImage)
d, err := NewK8sDriver(logger, "executorid01", toolboxPath, initImage, nil)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}

View File

@ -1423,15 +1423,35 @@ func NewExecutor(ctx context.Context, l *zap.Logger, c *config.Executor) (*Execu
e.listenAddress = fmt.Sprintf(":%s", port)
var initDockerConfig *registry.DockerConfig
if e.c.InitImage.Auth != nil {
regName, err := registry.GetRegistry(e.c.InitImage.Image)
if err != nil {
return nil, err
}
dockerAuthConfig :=
types.DockerRegistryAuth{
Type: types.DockerRegistryAuthType(e.c.InitImage.Auth.Type),
Username: e.c.InitImage.Auth.Username,
Password: e.c.InitImage.Auth.Password,
Auth: e.c.InitImage.Auth.Auth,
}
initDockerConfig, err = registry.GenDockerConfig(map[string]types.DockerRegistryAuth{regName: dockerAuthConfig}, []string{e.c.InitImage.Image})
if err != nil {
return nil, err
}
}
var d driver.Driver
switch c.Driver.Type {
case config.DriverTypeDocker:
d, err = driver.NewDockerDriver(logger, e.id, e.c.ToolboxPath, e.c.InitImage.Image)
d, err = driver.NewDockerDriver(logger, e.id, e.c.ToolboxPath, e.c.InitImage.Image, initDockerConfig)
if err != nil {
return nil, errors.Errorf("failed to create docker driver: %w", err)
}
case config.DriverTypeK8s:
d, err = driver.NewK8sDriver(logger, e.id, c.ToolboxPath, e.c.InitImage.Image)
d, err = driver.NewK8sDriver(logger, e.id, c.ToolboxPath, e.c.InitImage.Image, initDockerConfig)
if err != nil {
return nil, errors.Errorf("failed to create kubernetes driver: %w", err)
}