executor: add init image config authentication options
Add config options to define docker registry authentication for init image pulling.
This commit is contained in:
parent
42a07856cc
commit
d9d6b995da
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue