Merge pull request #271 from sgotti/executor_add_initimage_auth_options
executor: add init image config authentication options
This commit is contained in:
commit
8b7596559b
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue