Skip to content

Commit 8597e9b

Browse files
authored
Merge pull request #162 from tkgregory/secret-environment-variables
[JENKINS-39867] Add environment variables to container from a secret.
2 parents 83b93b4 + d6d712c commit 8597e9b

File tree

29 files changed

+742
-251
lines changed

29 files changed

+742
-251
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ Either way it provides access to the following fields:
9797
* **nodeSelector** The node selector of the pod.
9898
* **nodeUsageMode** Either 'NORMAL' or 'EXCLUSIVE', this controls whether Jenkins only schedules jobs with label expressions matching or use the node as much as possible.
9999
* **volumes** Volumes that are defined for the pod and are mounted by **ALL** containers.
100-
* **envVars*** Environment variables that are applied to **ALL** containers.
100+
* **envVars** Environment variables that are applied to **ALL** containers.
101+
* **envVar** An environment variable whose value is defined inline.
102+
* **secretEnvVar** An environment variable whose value is derived from a Kubernetes secret.
101103
* **annotations** Annotations to apply to the pod.
102104
* **inheritFrom** List of one or more pod templates to inherit from *(more details below)*.
103105

@@ -106,6 +108,8 @@ The `containerTemplate` is a template of container that will be added to the pod
106108
* **name** The name of the container.
107109
* **image** The image of the container.
108110
* **envVars** Environment variables that are applied to the container **(supplementing and overriding env vars that are set on pod level)**.
111+
* **envVar** An environment variable whose value is defined inline.
112+
* **secretEnvVar** An environment variable whose value is derived from a Kubernetes secret.
109113
* **command** The command the container will execute.
110114
* **args** The arguments passed to the command.
111115
* **ttyEnabled** Flag to mark that tty should be enabled.
@@ -222,7 +226,8 @@ podTemplate(label: 'mypod', cloud: 'kubernetes', containers: [
222226
resourceRequestMemory: '100Mi',
223227
resourceLimitMemory: '200Mi',
224228
envVars: [
225-
containerEnvVar(key: 'MYSQL_ALLOW_EMPTY_PASSWORD', value: 'true'),
229+
envVar(key: 'MYSQL_ALLOW_EMPTY_PASSWORD', value: 'true'),
230+
secretEnvVar(key: 'MYSQL_PASSWORD', secretName: 'mysql-secret', secretKey: 'password'),
226231
...
227232
],
228233
ports: [portMapping(name: 'mysql', containerPort: 3306, hostPort: 3306)]
Lines changed: 17 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,38 @@
11
package org.csanchez.jenkins.plugins.kubernetes;
22

3-
import hudson.Extension;
4-
import hudson.model.AbstractDescribableImpl;
5-
import hudson.model.Descriptor;
3+
import org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar;
64
import org.jenkinsci.Symbol;
7-
8-
import java.io.Serializable;
9-
105
import org.kohsuke.stapler.DataBoundConstructor;
116

12-
public class ContainerEnvVar extends AbstractDescribableImpl<ContainerEnvVar> implements Serializable {
7+
import hudson.Extension;
8+
import hudson.model.Descriptor;
139

14-
private String key;
15-
private String value;
10+
/**
11+
* Deprecated, use KeyValueEnvVar
12+
*/
13+
@Deprecated
14+
public class ContainerEnvVar extends KeyValueEnvVar {
1615

1716
@DataBoundConstructor
1817
public ContainerEnvVar(String key, String value) {
19-
this.key = key;
20-
this.value = value;
21-
}
22-
23-
public String getKey() {
24-
return key;
25-
}
26-
27-
public void setKey(String key) {
28-
this.key = key;
29-
}
30-
31-
public String getValue() {
32-
return value;
33-
}
34-
35-
public void setValue(String value) {
36-
this.value = value;
37-
}
38-
39-
public String toString() {
40-
return String.format("%s=%s", key, value);
18+
super(key, value);
4119
}
4220

4321
@Override
44-
public int hashCode() {
45-
final int prime = 31;
46-
int result = 1;
47-
result = prime * result + ((key == null) ? 0 : key.hashCode());
48-
result = prime * result + ((value == null) ? 0 : value.hashCode());
49-
return result;
50-
}
51-
52-
@Override
53-
public boolean equals(Object obj) {
54-
if (this == obj)
55-
return true;
56-
if (obj == null)
57-
return false;
58-
if (getClass() != obj.getClass())
59-
return false;
60-
ContainerEnvVar other = (ContainerEnvVar) obj;
61-
if (key == null) {
62-
if (other.key != null)
63-
return false;
64-
} else if (!key.equals(other.key))
65-
return false;
66-
if (value == null) {
67-
if (other.value != null)
68-
return false;
69-
} else if (!value.equals(other.value))
70-
return false;
71-
return true;
22+
public String toString() {
23+
return "ContainerEnvVar [getValue()=" + getValue() + ", getKey()=" + getKey() + "]";
7224
}
7325

7426
@Extension
7527
@Symbol("containerEnvVar")
76-
public static class DescriptorImpl extends Descriptor<ContainerEnvVar> {
28+
/**
29+
* deprecated, use envVar
30+
*/
31+
public static class DescriptorImplContainer extends Descriptor<KeyValueEnvVar> {
7732
@Override
7833
public String getDisplayName() {
79-
return "Container Environment Variable";
34+
return "Environment Variable";
8035
}
8136
}
37+
8238
}

src/main/java/org/csanchez/jenkins/plugins/kubernetes/ContainerTemplate.java

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
package org.csanchez.jenkins.plugins.kubernetes;
22

3-
import com.google.common.base.Preconditions;
4-
import hudson.Extension;
5-
import hudson.model.AbstractDescribableImpl;
6-
import hudson.model.Descriptor;
3+
import java.io.Serializable;
4+
import java.util.ArrayList;
5+
import java.util.Collections;
6+
import java.util.List;
7+
78
import org.apache.commons.lang.StringUtils;
9+
import org.csanchez.jenkins.plugins.kubernetes.model.TemplateEnvVar;
810
import org.jenkinsci.Symbol;
911
import org.kohsuke.stapler.DataBoundConstructor;
1012
import org.kohsuke.stapler.DataBoundSetter;
1113

12-
import java.io.Serializable;
13-
import java.util.ArrayList;
14-
import java.util.Collections;
15-
import java.util.List;
14+
import com.google.common.base.Preconditions;
15+
16+
import hudson.Extension;
17+
import hudson.model.AbstractDescribableImpl;
18+
import hudson.model.Descriptor;
1619

1720
public class ContainerTemplate extends AbstractDescribableImpl<ContainerTemplate> implements Serializable {
1821

@@ -44,7 +47,7 @@ public class ContainerTemplate extends AbstractDescribableImpl<ContainerTemplate
4447

4548
private String resourceLimitMemory;
4649

47-
private final List<ContainerEnvVar> envVars = new ArrayList<ContainerEnvVar>();
50+
private final List<TemplateEnvVar> envVars = new ArrayList<>();
4851
private List<PortMapping> ports = new ArrayList<PortMapping>();
4952

5053
private ContainerLivenessProbe livenessProbe;
@@ -145,12 +148,12 @@ public boolean isAlwaysPullImage() {
145148
return alwaysPullImage;
146149
}
147150

148-
public List<ContainerEnvVar> getEnvVars() {
151+
public List<TemplateEnvVar> getEnvVars() {
149152
return envVars != null ? envVars : Collections.emptyList();
150153
}
151154

152155
@DataBoundSetter
153-
public void setEnvVars(List<ContainerEnvVar> envVars) {
156+
public void setEnvVars(List<TemplateEnvVar> envVars) {
154157
this.envVars.addAll(envVars);
155158
}
156159

src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesCloud.java

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
import org.apache.commons.codec.binary.Base64;
3434
import org.apache.commons.lang.StringUtils;
35+
import org.csanchez.jenkins.plugins.kubernetes.model.TemplateEnvVar;
3536
import org.csanchez.jenkins.plugins.kubernetes.pipeline.PodTemplateStepExecution;
3637
import org.csanchez.jenkins.plugins.kubernetes.volumes.PodVolume;
3738
import org.jenkinsci.plugins.durabletask.executors.OnceRetentionStrategy;
@@ -337,7 +338,7 @@ private String getIdForLabel(Label label) {
337338
}
338339

339340

340-
private Container createContainer(KubernetesSlave slave, ContainerTemplate containerTemplate, Collection<PodEnvVar> globalEnvVars, Collection<VolumeMount> volumeMounts) {
341+
private Container createContainer(KubernetesSlave slave, ContainerTemplate containerTemplate, Collection<TemplateEnvVar> globalEnvVars, Collection<VolumeMount> volumeMounts) {
341342
// Last-write wins map of environment variable names to values
342343
HashMap<String, String> env = new HashMap<>();
343344

@@ -367,27 +368,29 @@ private Container createContainer(KubernetesSlave slave, ContainerTemplate conta
367368
// and `?` for java build tools. So we force HOME to a safe location.
368369
env.put("HOME", containerTemplate.getWorkingDir());
369370

371+
List<EnvVar> envVarsList = new ArrayList<>();
372+
370373
if (globalEnvVars != null) {
371-
for (PodEnvVar podEnvVar : globalEnvVars) {
372-
env.put(podEnvVar.getKey(), substituteEnv(podEnvVar.getValue()));
373-
}
374+
envVarsList.addAll(globalEnvVars.stream()
375+
.map(TemplateEnvVar::buildEnvVar)
376+
.collect(Collectors.toList()));
374377
}
375-
376378
if (containerTemplate.getEnvVars() != null) {
377-
for (ContainerEnvVar containerEnvVar : containerTemplate.getEnvVars()) {
378-
env.put(containerEnvVar.getKey(), substituteEnv(containerEnvVar.getValue()));
379-
}
379+
envVarsList.addAll(containerTemplate.getEnvVars().stream()
380+
.map(TemplateEnvVar::buildEnvVar)
381+
.collect(Collectors.toList()));
380382
}
381383

382-
// Convert our env map to an array
383-
EnvVar[] envVars = env.entrySet().stream()
384+
List<EnvVar> defaultEnvVars = env.entrySet().stream()
384385
.map(entry -> new EnvVar(entry.getKey(), entry.getValue(), null))
385-
.toArray(size -> new EnvVar[size]);
386+
.collect(Collectors.toList());
387+
envVarsList.addAll(defaultEnvVars);
388+
EnvVar [] envVars = envVarsList.stream().toArray(EnvVar[]::new);
386389

387390
List<String> arguments = Strings.isNullOrEmpty(containerTemplate.getArgs()) ? Collections.emptyList()
388391
: parseDockerCommand(containerTemplate.getArgs() //
389-
.replaceAll(JNLPMAC_REF, slave.getComputer().getJnlpMac()) //
390-
.replaceAll(NAME_REF, slave.getComputer().getName()));
392+
.replaceAll(JNLPMAC_REF, slave.getComputer().getJnlpMac()) //
393+
.replaceAll(NAME_REF, slave.getComputer().getName()));
391394

392395

393396
List<VolumeMount> containerMounts = new ArrayList<>(volumeMounts);
@@ -417,7 +420,7 @@ private Container createContainer(KubernetesSlave slave, ContainerTemplate conta
417420
.withImage(substituteEnv(containerTemplate.getImage()))
418421
.withImagePullPolicy(containerTemplate.isAlwaysPullImage() ? "Always" : "IfNotPresent")
419422
.withNewSecurityContext()
420-
.withPrivileged(containerTemplate.isPrivileged())
423+
.withPrivileged(containerTemplate.isPrivileged())
421424
.endSecurityContext()
422425
.withWorkingDir(substituteEnv(containerTemplate.getWorkingDir()))
423426
.withVolumeMounts(containerMounts.toArray(new VolumeMount[containerMounts.size()]))
@@ -428,8 +431,8 @@ private Container createContainer(KubernetesSlave slave, ContainerTemplate conta
428431
.withLivenessProbe(livenessProbe)
429432
.withTty(containerTemplate.isTtyEnabled())
430433
.withNewResources()
431-
.withRequests(getResourcesMap(containerTemplate.getResourceRequestMemory(), containerTemplate.getResourceRequestCpu()))
432-
.withLimits(getResourcesMap(containerTemplate.getResourceLimitMemory(), containerTemplate.getResourceLimitCpu()))
434+
.withRequests(getResourcesMap(containerTemplate.getResourceRequestMemory(), containerTemplate.getResourceRequestCpu()))
435+
.withLimits(getResourcesMap(containerTemplate.getResourceLimitMemory(), containerTemplate.getResourceLimitCpu()))
433436
.endResources()
434437
.build();
435438
}
@@ -480,17 +483,17 @@ private Pod getPodTemplate(KubernetesSlave slave, PodTemplate template) {
480483
.map((x) -> x.toLocalObjectReference()).collect(Collectors.toList());
481484
return new PodBuilder()
482485
.withNewMetadata()
483-
.withName(substituteEnv(slave.getNodeName()))
484-
.withLabels(getLabelsMap(template.getLabelSet()))
485-
.withAnnotations(getAnnotationsMap(template.getAnnotations()))
486+
.withName(substituteEnv(slave.getNodeName()))
487+
.withLabels(getLabelsMap(template.getLabelSet()))
488+
.withAnnotations(getAnnotationsMap(template.getAnnotations()))
486489
.endMetadata()
487490
.withNewSpec()
488-
.withVolumes(volumes)
489-
.withServiceAccount(substituteEnv(template.getServiceAccount()))
490-
.withImagePullSecrets(imagePullSecrets)
491-
.withContainers(containers.values().toArray(new Container[containers.size()]))
492-
.withNodeSelector(getNodeSelectorMap(template.getNodeSelector()))
493-
.withRestartPolicy("Never")
491+
.withVolumes(volumes)
492+
.withServiceAccount(substituteEnv(template.getServiceAccount()))
493+
.withImagePullSecrets(imagePullSecrets)
494+
.withContainers(containers.values().toArray(new Container[containers.size()]))
495+
.withNodeSelector(getNodeSelectorMap(template.getNodeSelector()))
496+
.withRestartPolicy("Never")
494497
.endSpec()
495498
.build();
496499
}

src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlave.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import org.apache.commons.lang.RandomStringUtils;
1212
import org.apache.commons.lang.StringUtils;
13+
import org.jenkinsci.plugins.durabletask.executors.Messages;
1314
import org.jenkinsci.plugins.durabletask.executors.OnceRetentionStrategy;
1415
import org.jvnet.localizer.Localizable;
1516
import org.jvnet.localizer.ResourceBundleHolder;

0 commit comments

Comments
 (0)