Skip to content

[JENKINS-39867] Add environment variables to container from a secret. #162

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

Merged
merged 13 commits into from
Aug 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
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
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ Either way it provides access to the following fields:
* **nodeSelector** The node selector of the pod.
* **nodeUsageMode** Either 'NORMAL' or 'EXCLUSIVE', this controls whether Jenkins only schedules jobs with label expressions matching or use the node as much as possible.
* **volumes** Volumes that are defined for the pod and are mounted by **ALL** containers.
* **envVars*** Environment variables that are applied to **ALL** containers.
* **envVars** Environment variables that are applied to **ALL** containers.
* **envVar** An environment variable whose value is defined inline.
* **secretEnvVar** An environment variable whose value is derived from a Kubernetes secret.
* **annotations** Annotations to apply to the pod.
* **inheritFrom** List of one or more pod templates to inherit from *(more details below)*.

Expand All @@ -106,6 +108,8 @@ The `containerTemplate` is a template of container that will be added to the pod
* **name** The name of the container.
* **image** The image of the container.
* **envVars** Environment variables that are applied to the container **(supplementing and overriding env vars that are set on pod level)**.
* **envVar** An environment variable whose value is defined inline.
* **secretEnvVar** An environment variable whose value is derived from a Kubernetes secret.
* **command** The command the container will execute.
* **args** The arguments passed to the command.
* **ttyEnabled** Flag to mark that tty should be enabled.
Expand Down Expand Up @@ -222,7 +226,8 @@ podTemplate(label: 'mypod', cloud: 'kubernetes', containers: [
resourceRequestMemory: '100Mi',
resourceLimitMemory: '200Mi',
envVars: [
containerEnvVar(key: 'MYSQL_ALLOW_EMPTY_PASSWORD', value: 'true'),
envVar(key: 'MYSQL_ALLOW_EMPTY_PASSWORD', value: 'true'),
secretEnvVar(key: 'MYSQL_PASSWORD', secretName: 'mysql-secret', secretKey: 'password'),
...
],
ports: [portMapping(name: 'mysql', containerPort: 3306, hostPort: 3306)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,82 +1,38 @@
package org.csanchez.jenkins.plugins.kubernetes;

import hudson.Extension;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar;
import org.jenkinsci.Symbol;

import java.io.Serializable;

import org.kohsuke.stapler.DataBoundConstructor;

public class ContainerEnvVar extends AbstractDescribableImpl<ContainerEnvVar> implements Serializable {
import hudson.Extension;
import hudson.model.Descriptor;

private String key;
private String value;
/**
* Deprecated, use KeyValueEnvVar
*/
@Deprecated
public class ContainerEnvVar extends KeyValueEnvVar {

@DataBoundConstructor
public ContainerEnvVar(String key, String value) {
this.key = key;
this.value = value;
}

public String getKey() {
return key;
}

public void setKey(String key) {
this.key = key;
}

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}

public String toString() {
return String.format("%s=%s", key, value);
super(key, value);
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((key == null) ? 0 : key.hashCode());
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ContainerEnvVar other = (ContainerEnvVar) obj;
if (key == null) {
if (other.key != null)
return false;
} else if (!key.equals(other.key))
return false;
if (value == null) {
if (other.value != null)
return false;
} else if (!value.equals(other.value))
return false;
return true;
public String toString() {
return "ContainerEnvVar [getValue()=" + getValue() + ", getKey()=" + getKey() + "]";
}

@Extension
@Symbol("containerEnvVar")
public static class DescriptorImpl extends Descriptor<ContainerEnvVar> {
/**
* deprecated, use envVar
*/
public static class DescriptorImplContainer extends Descriptor<KeyValueEnvVar> {
@Override
public String getDisplayName() {
return "Container Environment Variable";
return "Environment Variable";
}
}

}
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package org.csanchez.jenkins.plugins.kubernetes;

import com.google.common.base.Preconditions;
import hudson.Extension;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.csanchez.jenkins.plugins.kubernetes.model.TemplateEnvVar;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.google.common.base.Preconditions;

import hudson.Extension;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;

public class ContainerTemplate extends AbstractDescribableImpl<ContainerTemplate> implements Serializable {

Expand Down Expand Up @@ -44,7 +47,7 @@ public class ContainerTemplate extends AbstractDescribableImpl<ContainerTemplate

private String resourceLimitMemory;

private final List<ContainerEnvVar> envVars = new ArrayList<ContainerEnvVar>();
private final List<TemplateEnvVar> envVars = new ArrayList<>();
private List<PortMapping> ports = new ArrayList<PortMapping>();

private ContainerLivenessProbe livenessProbe;
Expand Down Expand Up @@ -145,12 +148,12 @@ public boolean isAlwaysPullImage() {
return alwaysPullImage;
}

public List<ContainerEnvVar> getEnvVars() {
public List<TemplateEnvVar> getEnvVars() {
return envVars != null ? envVars : Collections.emptyList();
}

@DataBoundSetter
public void setEnvVars(List<ContainerEnvVar> envVars) {
public void setEnvVars(List<TemplateEnvVar> envVars) {
this.envVars.addAll(envVars);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.csanchez.jenkins.plugins.kubernetes.model.TemplateEnvVar;
import org.csanchez.jenkins.plugins.kubernetes.pipeline.PodTemplateStepExecution;
import org.csanchez.jenkins.plugins.kubernetes.volumes.PodVolume;
import org.jenkinsci.plugins.durabletask.executors.OnceRetentionStrategy;
Expand Down Expand Up @@ -337,7 +338,7 @@ private String getIdForLabel(Label label) {
}


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

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

List<EnvVar> envVarsList = new ArrayList<>();

if (globalEnvVars != null) {
for (PodEnvVar podEnvVar : globalEnvVars) {
env.put(podEnvVar.getKey(), substituteEnv(podEnvVar.getValue()));
}
envVarsList.addAll(globalEnvVars.stream()
.map(TemplateEnvVar::buildEnvVar)
.collect(Collectors.toList()));
}

if (containerTemplate.getEnvVars() != null) {
for (ContainerEnvVar containerEnvVar : containerTemplate.getEnvVars()) {
env.put(containerEnvVar.getKey(), substituteEnv(containerEnvVar.getValue()));
}
envVarsList.addAll(containerTemplate.getEnvVars().stream()
.map(TemplateEnvVar::buildEnvVar)
.collect(Collectors.toList()));
}

// Convert our env map to an array
EnvVar[] envVars = env.entrySet().stream()
List<EnvVar> defaultEnvVars = env.entrySet().stream()
.map(entry -> new EnvVar(entry.getKey(), entry.getValue(), null))
.toArray(size -> new EnvVar[size]);
.collect(Collectors.toList());
envVarsList.addAll(defaultEnvVars);
EnvVar [] envVars = envVarsList.stream().toArray(EnvVar[]::new);

List<String> arguments = Strings.isNullOrEmpty(containerTemplate.getArgs()) ? Collections.emptyList()
: parseDockerCommand(containerTemplate.getArgs() //
.replaceAll(JNLPMAC_REF, slave.getComputer().getJnlpMac()) //
.replaceAll(NAME_REF, slave.getComputer().getName()));
.replaceAll(JNLPMAC_REF, slave.getComputer().getJnlpMac()) //
.replaceAll(NAME_REF, slave.getComputer().getName()));


List<VolumeMount> containerMounts = new ArrayList<>(volumeMounts);
Expand Down Expand Up @@ -417,7 +420,7 @@ private Container createContainer(KubernetesSlave slave, ContainerTemplate conta
.withImage(substituteEnv(containerTemplate.getImage()))
.withImagePullPolicy(containerTemplate.isAlwaysPullImage() ? "Always" : "IfNotPresent")
.withNewSecurityContext()
.withPrivileged(containerTemplate.isPrivileged())
.withPrivileged(containerTemplate.isPrivileged())
.endSecurityContext()
.withWorkingDir(substituteEnv(containerTemplate.getWorkingDir()))
.withVolumeMounts(containerMounts.toArray(new VolumeMount[containerMounts.size()]))
Expand All @@ -428,8 +431,8 @@ private Container createContainer(KubernetesSlave slave, ContainerTemplate conta
.withLivenessProbe(livenessProbe)
.withTty(containerTemplate.isTtyEnabled())
.withNewResources()
.withRequests(getResourcesMap(containerTemplate.getResourceRequestMemory(), containerTemplate.getResourceRequestCpu()))
.withLimits(getResourcesMap(containerTemplate.getResourceLimitMemory(), containerTemplate.getResourceLimitCpu()))
.withRequests(getResourcesMap(containerTemplate.getResourceRequestMemory(), containerTemplate.getResourceRequestCpu()))
.withLimits(getResourcesMap(containerTemplate.getResourceLimitMemory(), containerTemplate.getResourceLimitCpu()))
.endResources()
.build();
}
Expand Down Expand Up @@ -480,17 +483,17 @@ private Pod getPodTemplate(KubernetesSlave slave, PodTemplate template) {
.map((x) -> x.toLocalObjectReference()).collect(Collectors.toList());
return new PodBuilder()
.withNewMetadata()
.withName(substituteEnv(slave.getNodeName()))
.withLabels(getLabelsMap(template.getLabelSet()))
.withAnnotations(getAnnotationsMap(template.getAnnotations()))
.withName(substituteEnv(slave.getNodeName()))
.withLabels(getLabelsMap(template.getLabelSet()))
.withAnnotations(getAnnotationsMap(template.getAnnotations()))
.endMetadata()
.withNewSpec()
.withVolumes(volumes)
.withServiceAccount(substituteEnv(template.getServiceAccount()))
.withImagePullSecrets(imagePullSecrets)
.withContainers(containers.values().toArray(new Container[containers.size()]))
.withNodeSelector(getNodeSelectorMap(template.getNodeSelector()))
.withRestartPolicy("Never")
.withVolumes(volumes)
.withServiceAccount(substituteEnv(template.getServiceAccount()))
.withImagePullSecrets(imagePullSecrets)
.withContainers(containers.values().toArray(new Container[containers.size()]))
.withNodeSelector(getNodeSelectorMap(template.getNodeSelector()))
.withRestartPolicy("Never")
.endSpec()
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.durabletask.executors.Messages;
import org.jenkinsci.plugins.durabletask.executors.OnceRetentionStrategy;
import org.jvnet.localizer.Localizable;
import org.jvnet.localizer.ResourceBundleHolder;
Expand Down
Loading