Merge pull request #271 from sgotti/executor_add_initimage_auth_options

executor: add init image config authentication options
This commit is contained in:
Simone Gotti 2021-05-26 11:25:25 +02:00 committed by GitHub
commit 8b7596559b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 96 additions and 22 deletions

View File

@ -120,6 +120,28 @@ type Executor struct {
type InitImage struct { type InitImage struct {
Image string `yaml:"image"` 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 { type Configstore struct {

View File

@ -44,27 +44,29 @@ import (
) )
type DockerDriver struct { type DockerDriver struct {
log *zap.SugaredLogger log *zap.SugaredLogger
client *client.Client client *client.Client
toolboxPath string toolboxPath string
initImage string initImage string
executorID string initDockerConfig *registry.DockerConfig
arch types.Arch 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")) cli, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("1.26"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &DockerDriver{ return &DockerDriver{
log: logger.Sugar(), log: logger.Sugar(),
client: cli, client: cli,
toolboxPath: toolboxPath, toolboxPath: toolboxPath,
initImage: initImage, initImage: initImage,
executorID: executorID, initDockerConfig: initDockerConfig,
arch: types.ArchFromString(runtime.GOARCH), executorID: executorID,
arch: types.ArchFromString(runtime.GOARCH),
}, nil }, 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) { 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 return nil, err
} }

View File

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

View File

@ -26,6 +26,7 @@ import (
"strings" "strings"
"time" "time"
"agola.io/agola/internal/services/executor/registry"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
"agola.io/agola/services/types" "agola.io/agola/services/types"
@ -75,6 +76,7 @@ type K8sDriver struct {
client *kubernetes.Clientset client *kubernetes.Clientset
toolboxPath string toolboxPath string
initImage string initImage string
initDockerConfig *registry.DockerConfig
namespace string namespace string
executorID string executorID string
executorsGroupID string executorsGroupID string
@ -96,7 +98,7 @@ type K8sPod struct {
initVolumeDir string 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("", "", "") kubeClientConfig := NewKubeClientConfig("", "", "")
kubecfg, err := kubeClientConfig.ClientConfig() kubecfg, err := kubeClientConfig.ClientConfig()
if err != nil { if err != nil {
@ -118,6 +120,7 @@ func NewK8sDriver(logger *zap.Logger, executorID, toolboxPath, initImage string)
client: kubecli, client: kubecli,
toolboxPath: toolboxPath, toolboxPath: toolboxPath,
initImage: initImage, initImage: initImage,
initDockerConfig: initDockerConfig,
namespace: namespace, namespace: namespace,
executorID: executorID, executorID: executorID,
k8sLabelArch: corev1.LabelArchStable, k8sLabelArch: corev1.LabelArchStable,
@ -324,13 +327,18 @@ func (d *K8sDriver) NewPod(ctx context.Context, podConfig *PodConfig, out io.Wri
labels[executorIDKey] = d.executorID labels[executorIDKey] = d.executorID
labels[executorsGroupIDKey] = d.executorsGroupID labels[executorsGroupIDKey] = d.executorsGroupID
// pod and secret name, based on pod id
name := podNamePrefix + podConfig.ID
dockerconfigj, err := json.Marshal(podConfig.DockerConfig) dockerconfigj, err := json.Marshal(podConfig.DockerConfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// pod and secret name, based on pod id initDockerconfigj, err := json.Marshal(d.initDockerConfig)
name := podNamePrefix + podConfig.ID if err != nil {
return nil, err
}
// secret that hold the docker registry auth // secret that hold the docker registry auth
secret := &corev1.Secret{ secret := &corev1.Secret{
@ -339,7 +347,7 @@ func (d *K8sDriver) NewPod(ctx context.Context, podConfig *PodConfig, out io.Wri
Labels: labels, Labels: labels,
}, },
Data: map[string][]byte{ Data: map[string][]byte{
".dockerconfigjson": dockerconfigj, ".dockerconfigjson": initDockerconfigj,
}, },
Type: corev1.SecretTypeDockerConfigJson, 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") 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) coreclient, err := corev1client.NewForConfig(d.restconfig)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -43,7 +43,7 @@ func TestK8sPod(t *testing.T) {
initImage := "busybox:stable" initImage := "busybox:stable"
d, err := NewK8sDriver(logger, "executorid01", toolboxPath, initImage) d, err := NewK8sDriver(logger, "executorid01", toolboxPath, initImage, nil)
if err != nil { if err != nil {
t.Fatalf("unexpected err: %v", err) 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) 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 var d driver.Driver
switch c.Driver.Type { switch c.Driver.Type {
case config.DriverTypeDocker: 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 { if err != nil {
return nil, errors.Errorf("failed to create docker driver: %w", err) return nil, errors.Errorf("failed to create docker driver: %w", err)
} }
case config.DriverTypeK8s: 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 { if err != nil {
return nil, errors.Errorf("failed to create kubernetes driver: %w", err) return nil, errors.Errorf("failed to create kubernetes driver: %w", err)
} }