Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flexible image pull secret reference #3016

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ Additional labels to apply to worker pods. Must be a YAML object, e.g. `{"exampl

Additional annotations to apply to worker pods. Must be a YAML object, e.g. `{"example.com/test-annotation":"test-value"}`.

### `WOODPECKER_BACKEND_K8S_PULL_SECRET_NAMES`
> Default: `regcred`
qwerty287 marked this conversation as resolved.
Show resolved Hide resolved

By default, in order to pull images from private repositories Kubernetes backend uses a secret named "regcred".
You can override it and also set many secret names.

## Job specific configuration

### Resources
Expand Down
6 changes: 6 additions & 0 deletions pipeline/backend/kubernetes/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,10 @@ var Flags = []cli.Flag{
Usage: "duration to wait before retrying to connect to the server",
Value: time.Second * 2,
},
&cli.StringSliceFlag{
EnvVars: []string{"WOODPECKER_BACKEND_K8S_PULL_SECRET_NAMES"},
Name: "backend-k8s-pod-image-pull-secret-names",
Usage: "backend k8s pull secret names for private registries",
qwerty287 marked this conversation as resolved.
Show resolved Hide resolved
Value: cli.NewStringSlice("regcred"),
},
}
28 changes: 15 additions & 13 deletions pipeline/backend/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@
}

type config struct {
Namespace string
StorageClass string
VolumeSize string
StorageRwx bool
PodLabels map[string]string
PodAnnotations map[string]string
SecurityContext SecurityContextConfig
Namespace string
StorageClass string
VolumeSize string
StorageRwx bool
PodLabels map[string]string
PodAnnotations map[string]string
ImagePullSecretNames []string
SecurityContext SecurityContextConfig
}
type SecurityContextConfig struct {
RunAsNonRoot bool
Expand All @@ -80,12 +81,13 @@
if ctx != nil {
if c, ok := ctx.Value(types.CliContext).(*cli.Context); ok {
config := config{
Namespace: c.String("backend-k8s-namespace"),
StorageClass: c.String("backend-k8s-storage-class"),
VolumeSize: c.String("backend-k8s-volume-size"),
StorageRwx: c.Bool("backend-k8s-storage-rwx"),
PodLabels: make(map[string]string), // just init empty map to prevent nil panic
PodAnnotations: make(map[string]string), // just init empty map to prevent nil panic
Namespace: c.String("backend-k8s-namespace"),
StorageClass: c.String("backend-k8s-storage-class"),
VolumeSize: c.String("backend-k8s-volume-size"),
StorageRwx: c.Bool("backend-k8s-storage-rwx"),
PodLabels: make(map[string]string), // just init empty map to prevent nil panic
PodAnnotations: make(map[string]string), // just init empty map to prevent nil panic
ImagePullSecretNames: c.StringSlice("backend-k8s-pod-image-pull-secret-names"),

Check warning on line 90 in pipeline/backend/kubernetes/kubernetes.go

View check run for this annotation

Codecov / codecov/patch

pipeline/backend/kubernetes/kubernetes.go#L84-L90

Added lines #L84 - L90 were not covered by tests
SecurityContext: SecurityContextConfig{
RunAsNonRoot: c.Bool("backend-k8s-secctx-nonroot"),
},
Expand Down
27 changes: 22 additions & 5 deletions pipeline/backend/kubernetes/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

func mkPod(namespace, name, image, workDir, goos, serviceAccountName string,
pool, privileged bool,
commands, vols []string,
commands, vols, pullSecretNames []string,
labels, annotations, env, nodeSelector map[string]string,
extraHosts []types.HostAlias, tolerations []types.Toleration, resources types.Resources,
securityContext *types.SecurityContext, securityContextConfig SecurityContextConfig,
Expand All @@ -45,7 +45,8 @@

meta := podMeta(name, namespace, labels, annotations)

spec, err := podSpec(serviceAccountName, vols, env, nodeSelector, extraHosts, tolerations, securityContext, securityContextConfig)
spec, err := podSpec(serviceAccountName, vols, pullSecretNames, env, nodeSelector, extraHosts, tolerations,
securityContext, securityContextConfig)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -85,15 +86,15 @@
return meta
}

func podSpec(serviceAccountName string, vols []string, env, backendNodeSelector map[string]string,
func podSpec(serviceAccountName string, vols, pullSecretNames []string, env, backendNodeSelector map[string]string,
extraHosts []types.HostAlias, backendTolerations []types.Toleration,
securityContext *types.SecurityContext, securityContextConfig SecurityContextConfig,
) (v1.PodSpec, error) {
var err error
spec := v1.PodSpec{
RestartPolicy: v1.RestartPolicyNever,
ServiceAccountName: serviceAccountName,
ImagePullSecrets: []v1.LocalObjectReference{{Name: "regcred"}},
ImagePullSecrets: imagePullSecretsReferences(pullSecretNames),
}

spec.HostAliases = hostAliases(extraHosts)
Expand Down Expand Up @@ -211,6 +212,22 @@
}
}

func imagePullSecretsReferences(imagePullSecretNames []string) []v1.LocalObjectReference {
log.Trace().Msgf("Using the image pull secrets: %v", imagePullSecretNames)

secretReferences := make([]v1.LocalObjectReference, len(imagePullSecretNames))
for i, imagePullSecretName := range imagePullSecretNames {
secretReferences[i] = imagePullSecretsReference(imagePullSecretName)
}
return secretReferences
}

func imagePullSecretsReference(imagePullSecretName string) v1.LocalObjectReference {
return v1.LocalObjectReference{
Name: imagePullSecretName,
}
}

func resourceRequirements(resources types.Resources) (v1.ResourceRequirements, error) {
var err error
requirements := v1.ResourceRequirements{}
Expand Down Expand Up @@ -357,7 +374,7 @@

pod, err := mkPod(engine.config.Namespace, podName, step.Image, step.WorkingDir, engine.goos, step.BackendOptions.Kubernetes.ServiceAccountName,
step.Pull, step.Privileged,
step.Commands, step.Volumes,
step.Commands, step.Volumes, engine.config.ImagePullSecretNames,

Check warning on line 377 in pipeline/backend/kubernetes/pod.go

View check run for this annotation

Codecov / codecov/patch

pipeline/backend/kubernetes/pod.go#L377

Added line #L377 was not covered by tests
engine.config.PodLabels, engine.config.PodAnnotations, step.Environment, step.BackendOptions.Kubernetes.NodeSelector,
step.ExtraHosts, step.BackendOptions.Kubernetes.Tolerations, step.BackendOptions.Kubernetes.Resources, step.BackendOptions.Kubernetes.SecurityContext, engine.config.SecurityContext)
if err != nil {
Expand Down
14 changes: 6 additions & 8 deletions pipeline/backend/kubernetes/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,14 @@ func TestTinyPod(t *testing.T) {
]
}
],
"restartPolicy": "Never",
"imagePullSecrets": [
{
"name": "regcred"
}
]
"restartPolicy": "Never"
},
"status": {}
}`

pod, err := mkPod("woodpecker", "wp-01he8bebctabr3kgk0qj36d2me-0", "gradle:8.4.0-jdk21", "/woodpecker/src", "linux/amd64", "",
false, false,
[]string{"gradle build"}, []string{"workspace:/woodpecker/src"},
[]string{"gradle build"}, []string{"workspace:/woodpecker/src"}, nil,
nil, nil, map[string]string{"CI": "woodpecker"}, nil,
nil, nil,
types.Resources{Requests: nil, Limits: nil}, nil, SecurityContextConfig{},
Expand Down Expand Up @@ -213,6 +208,9 @@ func TestFullPod(t *testing.T) {
"imagePullSecrets": [
{
"name": "regcred"
},
{
"name": "another-pull-secret"
}
],
"tolerations": [
Expand Down Expand Up @@ -246,7 +244,7 @@ func TestFullPod(t *testing.T) {
}
pod, err := mkPod("woodpecker", "wp-01he8bebctabr3kgk0qj36d2me-0", "meltwater/drone-cache", "/woodpecker/src", "linux/amd64", "wp-svc-acc",
true, true,
[]string{"go get", "go test"}, []string{"woodpecker-cache:/woodpecker/src/cache"},
[]string{"go get", "go test"}, []string{"woodpecker-cache:/woodpecker/src/cache"}, []string{"regcred", "another-pull-secret"},
map[string]string{"app": "test"}, map[string]string{"apparmor.security": "runtime/default"}, map[string]string{"CGO": "0"}, map[string]string{"storage": "ssd"},
hostAliases, []types.Toleration{{Key: "net-port", Value: "100Mbit", Effect: types.TaintEffectNoSchedule}},
types.Resources{Requests: map[string]string{"memory": "128Mi", "cpu": "1000m"}, Limits: map[string]string{"memory": "256Mi", "cpu": "2"}},
Expand Down