mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-09-27 06:00:10 +00:00
K8s secrets reference from step
This commit is contained in:
parent
2d66cfcce2
commit
f33488c80f
7 changed files with 81 additions and 18 deletions
|
@ -14,6 +14,7 @@ type BackendOptions struct {
|
||||||
NodeSelector map[string]string `mapstructure:"nodeSelector"`
|
NodeSelector map[string]string `mapstructure:"nodeSelector"`
|
||||||
Tolerations []Toleration `mapstructure:"tolerations"`
|
Tolerations []Toleration `mapstructure:"tolerations"`
|
||||||
SecurityContext *SecurityContext `mapstructure:"securityContext"`
|
SecurityContext *SecurityContext `mapstructure:"securityContext"`
|
||||||
|
SecretNames []string `mapstructure:"secretNames"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resources defines two maps for kubernetes resource definitions
|
// Resources defines two maps for kubernetes resource definitions
|
||||||
|
|
|
@ -42,6 +42,9 @@ func Test_parseBackendOptions(t *testing.T) {
|
||||||
"localhostProfile": "k8s-apparmor-example-deny-write",
|
"localhostProfile": "k8s-apparmor-example-deny-write",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"secretNames": []string{
|
||||||
|
"test-secret",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -69,5 +72,8 @@ func Test_parseBackendOptions(t *testing.T) {
|
||||||
LocalhostProfile: "k8s-apparmor-example-deny-write",
|
LocalhostProfile: "k8s-apparmor-example-deny-write",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
SecretNames: []string{
|
||||||
|
"test-secret",
|
||||||
|
},
|
||||||
}, got)
|
}, got)
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,4 +66,10 @@ var Flags = []cli.Flag{
|
||||||
Usage: "backend k8s pull secret names for private registries",
|
Usage: "backend k8s pull secret names for private registries",
|
||||||
Value: cli.NewStringSlice("regcred"),
|
Value: cli.NewStringSlice("regcred"),
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
EnvVars: []string{"WOODPECKER_BACKEND_K8S_NATIVE_SECRETS_ALLOW_FROM_STEP"},
|
||||||
|
Name: "backend-k8s-native-secrets-allow-from-step",
|
||||||
|
Usage: "whether to allow existing Kubernetes secrets to be referenced from step",
|
||||||
|
Value: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ type config struct {
|
||||||
PodAnnotations map[string]string
|
PodAnnotations map[string]string
|
||||||
ImagePullSecretNames []string
|
ImagePullSecretNames []string
|
||||||
SecurityContext SecurityContextConfig
|
SecurityContext SecurityContextConfig
|
||||||
|
NativeSecretsAllowFromStep bool
|
||||||
}
|
}
|
||||||
type SecurityContextConfig struct {
|
type SecurityContextConfig struct {
|
||||||
RunAsNonRoot bool
|
RunAsNonRoot bool
|
||||||
|
@ -92,6 +93,7 @@ func configFromCliContext(ctx context.Context) (*config, error) {
|
||||||
SecurityContext: SecurityContextConfig{
|
SecurityContext: SecurityContextConfig{
|
||||||
RunAsNonRoot: c.Bool("backend-k8s-secctx-nonroot"),
|
RunAsNonRoot: c.Bool("backend-k8s-secctx-nonroot"),
|
||||||
},
|
},
|
||||||
|
NativeSecretsAllowFromStep: c.Bool("backend-k8s-native-secrets-allow-from-step"),
|
||||||
}
|
}
|
||||||
// TODO: remove in next major
|
// TODO: remove in next major
|
||||||
if len(config.ImagePullSecretNames) == 1 && config.ImagePullSecretNames[0] == "regcred" {
|
if len(config.ImagePullSecretNames) == 1 && config.ImagePullSecretNames[0] == "regcred" {
|
||||||
|
|
|
@ -48,7 +48,7 @@ func mkPod(step *types.Step, config *config, podName, goos string, options Backe
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
container, err := podContainer(step, podName, goos, options)
|
container, err := podContainer(step, config, podName, goos, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ func podSpec(step *types.Step, config *config, options BackendOptions) (v1.PodSp
|
||||||
return spec, nil
|
return spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func podContainer(step *types.Step, podName, goos string, options BackendOptions) (v1.Container, error) {
|
func podContainer(step *types.Step, config *config, podName, goos string, options BackendOptions) (v1.Container, error) {
|
||||||
var err error
|
var err error
|
||||||
container := v1.Container{
|
container := v1.Container{
|
||||||
Name: podName,
|
Name: podName,
|
||||||
|
@ -159,6 +159,14 @@ func podContainer(step *types.Step, podName, goos string, options BackendOptions
|
||||||
|
|
||||||
container.Env = mapToEnvVars(step.Environment)
|
container.Env = mapToEnvVars(step.Environment)
|
||||||
|
|
||||||
|
if len(options.SecretNames) > 0 {
|
||||||
|
if config.NativeSecretsAllowFromStep {
|
||||||
|
container.EnvFrom = containerSecrets(options.SecretNames)
|
||||||
|
} else {
|
||||||
|
log.Debug().Msg("Secret names were defined in backend options, but its using disallowed by instance configuration ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
container.Resources, err = resourceRequirements(options.Resources)
|
container.Resources, err = resourceRequirements(options.Resources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return container, err
|
return container, err
|
||||||
|
@ -236,6 +244,25 @@ func containerPort(port types.Port) v1.ContainerPort {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func containerSecrets(secretNames []string) []v1.EnvFromSource {
|
||||||
|
if secretNames == nil || len(secretNames) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
secretRefs := make([]v1.EnvFromSource, len(secretNames))
|
||||||
|
for i, secretName := range secretNames {
|
||||||
|
secretRefs[i] = containerSecret(secretName)
|
||||||
|
}
|
||||||
|
return secretRefs
|
||||||
|
}
|
||||||
|
|
||||||
|
func containerSecret(secretName string) v1.EnvFromSource {
|
||||||
|
return v1.EnvFromSource{
|
||||||
|
SecretRef: &v1.SecretEnvSource{
|
||||||
|
LocalObjectReference: secretReference(secretName),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Here is the service IPs (placed in /etc/hosts in the Pod)
|
// Here is the service IPs (placed in /etc/hosts in the Pod)
|
||||||
func hostAliases(extraHosts []types.HostAlias) []v1.HostAlias {
|
func hostAliases(extraHosts []types.HostAlias) []v1.HostAlias {
|
||||||
var hostAliases []v1.HostAlias
|
var hostAliases []v1.HostAlias
|
||||||
|
@ -258,14 +285,14 @@ func imagePullSecretsReferences(imagePullSecretNames []string) []v1.LocalObjectR
|
||||||
|
|
||||||
secretReferences := make([]v1.LocalObjectReference, len(imagePullSecretNames))
|
secretReferences := make([]v1.LocalObjectReference, len(imagePullSecretNames))
|
||||||
for i, imagePullSecretName := range imagePullSecretNames {
|
for i, imagePullSecretName := range imagePullSecretNames {
|
||||||
secretReferences[i] = imagePullSecretsReference(imagePullSecretName)
|
secretReferences[i] = secretReference(imagePullSecretName)
|
||||||
}
|
}
|
||||||
return secretReferences
|
return secretReferences
|
||||||
}
|
}
|
||||||
|
|
||||||
func imagePullSecretsReference(imagePullSecretName string) v1.LocalObjectReference {
|
func secretReference(secretName string) v1.LocalObjectReference {
|
||||||
return v1.LocalObjectReference{
|
return v1.LocalObjectReference{
|
||||||
Name: imagePullSecretName,
|
Name: secretName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,19 @@ func TestFullPod(t *testing.T) {
|
||||||
"protocol": "UDP"
|
"protocol": "UDP"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"envFrom": [
|
||||||
|
"<<UNORDERED>>",
|
||||||
|
{
|
||||||
|
"secretRef": {
|
||||||
|
"name": "ghcr-push-secret"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"secretRef": {
|
||||||
|
"name": "aws-ecr"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"env": [
|
"env": [
|
||||||
"<<UNORDERED>>",
|
"<<UNORDERED>>",
|
||||||
{
|
{
|
||||||
|
@ -333,6 +346,7 @@ func TestFullPod(t *testing.T) {
|
||||||
PodLabels: map[string]string{"app": "test"},
|
PodLabels: map[string]string{"app": "test"},
|
||||||
PodAnnotations: map[string]string{"apps.kubernetes.io/pod-index": "0"},
|
PodAnnotations: map[string]string{"apps.kubernetes.io/pod-index": "0"},
|
||||||
SecurityContext: SecurityContextConfig{RunAsNonRoot: false},
|
SecurityContext: SecurityContextConfig{RunAsNonRoot: false},
|
||||||
|
NativeSecretsAllowFromStep: true,
|
||||||
}, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{
|
}, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{
|
||||||
NodeSelector: map[string]string{"storage": "ssd"},
|
NodeSelector: map[string]string{"storage": "ssd"},
|
||||||
RuntimeClassName: &runtimeClass,
|
RuntimeClassName: &runtimeClass,
|
||||||
|
@ -343,6 +357,7 @@ func TestFullPod(t *testing.T) {
|
||||||
Limits: map[string]string{"memory": "256Mi", "cpu": "2"},
|
Limits: map[string]string{"memory": "256Mi", "cpu": "2"},
|
||||||
},
|
},
|
||||||
SecurityContext: &secCtx,
|
SecurityContext: &secCtx,
|
||||||
|
SecretNames: []string{"ghcr-push-secret", "aws-ecr"},
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
|
@ -700,6 +700,12 @@
|
||||||
"runtimeClassName": {
|
"runtimeClassName": {
|
||||||
"description": "Read more: https://woodpecker-ci.org/docs/administration/backends/kubernetes#runtimeclassname",
|
"description": "Read more: https://woodpecker-ci.org/docs/administration/backends/kubernetes#runtimeclassname",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"secretNames": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue