Skip to content

Commit

Permalink
Merge pull request #294 from colemickens/kubeconfig-from-secretfile
Browse files Browse the repository at this point in the history
[JENKINS-49817] Support kubeconfig from secretFile credentials
  • Loading branch information
carlossg authored Mar 20, 2018
2 parents 479ccd3 + 4ab127c commit d76e72d
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,22 @@
import jenkins.model.Jenkins;
import jenkins.tasks.SimpleBuildWrapper;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.kubernetes.credentials.TokenProducer;
import org.jenkinsci.plugins.plaincredentials.FileCredentials;
import org.jenkinsci.plugins.plaincredentials.StringCredentials;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;

import javax.annotation.Nonnull;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
Expand All @@ -44,6 +51,7 @@
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;

import static com.google.common.collect.Sets.newHashSet;

Expand Down Expand Up @@ -87,6 +95,9 @@ public void setUp(Context context, Run<?, ?> build, FilePath workspace, Launcher
FilePath configFile = workspace.createTempFile(".kube", "config");
Set<String> tempFiles = newHashSet(configFile.getRemote());

context.env("KUBECONFIG", configFile.getRemote());
context.setDisposer(new CleanupDisposer(tempFiles));

String tlsConfig;
if (caCertificate != null && !caCertificate.isEmpty()) {
FilePath caCrtFile = workspace.createTempFile("cert-auth", "crt");
Expand All @@ -113,7 +124,16 @@ public void setUp(Context context, Run<?, ?> build, FilePath workspace, Launcher
String login;
if (c == null) {
throw new AbortException("No credentials defined to setup Kubernetes CLI");
} else if (c instanceof StringCredentials) {
}

if (c instanceof FileCredentials) {
try (InputStream in = ((FileCredentials) c).getContent(); OutputStream out = configFile.write()) {
IOUtils.copy(in, out);
}
return;
}

if (c instanceof StringCredentials) {
login = "--token=" + ((StringCredentials) c).getSecret().getPlainText();
} else if (c instanceof TokenProducer) {
login = "--token=" + ((TokenProducer) c).getToken(serverUrl, null, true);
Expand Down Expand Up @@ -168,10 +188,6 @@ public void setUp(Context context, Run<?, ?> build, FilePath workspace, Launcher
.cmdAsSingleString("kubectl config --kubeconfig=\"" + configFile.getRemote() + "\" use-context k8s")
.join();
if (status != 0) throw new IOException("Failed to run kubectl config "+status);

context.setDisposer(new CleanupDisposer(tempFiles));

context.env("KUBECONFIG", configFile.getRemote());
}

/**
Expand Down Expand Up @@ -223,7 +239,8 @@ public ListBoxModel doFillCredentialsIdItems(@AncestorInPath Item item, @QueryPa
CredentialsMatchers.anyOf(
CredentialsMatchers.instanceOf(StandardUsernamePasswordCredentials.class),
CredentialsMatchers.instanceOf(TokenProducer.class),
CredentialsMatchers.instanceOf(StandardCertificateCredentials.class)
CredentialsMatchers.instanceOf(StandardCertificateCredentials.class),
CredentialsMatchers.instanceOf(FileCredentials.class)
),
CredentialsProvider.lookupCredentials(
StandardCredentials.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.plaincredentials.StringCredentials;
import org.jenkinsci.plugins.plaincredentials.FileCredentials;
import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
Expand Down Expand Up @@ -593,6 +594,7 @@ public ListBoxModel doFillCredentialsIdItems(@QueryParameter String serverUrl) {
.withMatching( //
CredentialsMatchers.anyOf(
CredentialsMatchers.instanceOf(StandardUsernamePasswordCredentials.class),
CredentialsMatchers.instanceOf(FileCredentials.class),
CredentialsMatchers.instanceOf(TokenProducer.class),
CredentialsMatchers.instanceOf(
org.jenkinsci.plugins.kubernetes.credentials.TokenProducer.class),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import static java.nio.charset.StandardCharsets.*;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.Key;
Expand All @@ -14,10 +17,12 @@
import java.util.Collections;
import static java.util.logging.Level.*;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import javax.annotation.CheckForNull;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

import com.cloudbees.plugins.credentials.CredentialsMatchers;
Expand All @@ -35,6 +40,7 @@
import io.fabric8.kubernetes.client.KubernetesClient;
import jenkins.model.Jenkins;
import org.jenkinsci.plugins.kubernetes.credentials.TokenProducer;
import org.jenkinsci.plugins.plaincredentials.FileCredentials;
import org.jenkinsci.plugins.plaincredentials.StringCredentials;

/**
Expand Down Expand Up @@ -98,27 +104,30 @@ public KubernetesClient createClient() throws NoSuchAlgorithmException, Unrecove
KeyStoreException, IOException, CertificateEncodingException {

ConfigBuilder builder;
// autoconfigure if url is not set
if (StringUtils.isBlank(serviceAddress)) {
LOGGER.log(FINE, "Autoconfiguring Kubernetes client");
builder = new ConfigBuilder(Config.autoConfigure(null));
// configure from kubeconfig
if (credentials instanceof FileCredentials) {
LOGGER.log(FINE, "Configuring Kubernetes client from kubeconfig file");
try (InputStream is = ((FileCredentials) credentials).getContent()) {
Config config = Config.fromKubeconfig(IOUtils.toString(is, StandardCharsets.UTF_8));
builder = new ConfigBuilder(config);
}
} else {
// although this will still autoconfigure based on Config constructor notes
// In future releases (2.4.x) the public constructor will be empty.
// The current functionality will be provided by autoConfigure().
// This is a necessary change to allow us distinguish between auto configured values and builder values.
builder = new ConfigBuilder().withMasterUrl(serviceAddress);
// autoconfigure if url is not set
if (StringUtils.isBlank(serviceAddress)) {
LOGGER.log(FINE, "Autoconfiguring Kubernetes client");
builder = new ConfigBuilder(Config.autoConfigure(null));
} else {
// although this will still autoconfigure based on Config constructor notes
// In future releases (2.4.x) the public constructor will be empty.
// The current functionality will be provided by autoConfigure().
// This is a necessary change to allow us distinguish between auto configured values and builder values.
builder = new ConfigBuilder().withMasterUrl(serviceAddress);
}
}

builder = builder.withRequestTimeout(readTimeout * 1000).withConnectionTimeout(connectTimeout * 1000);

if (!StringUtils.isBlank(namespace)) {
builder.withNamespace(namespace);
} else if (StringUtils.isBlank(builder.getNamespace())) {
builder.withNamespace("default");
}

if (credentials instanceof StringCredentials) {
if (credentials instanceof FileCredentials) {
// already handled above
} else if (credentials instanceof StringCredentials) {
final String token = ((StringCredentials) credentials).getSecret().getPlainText();
builder.withOauthToken(token);
} else if (credentials instanceof TokenProducer) {
Expand Down Expand Up @@ -147,8 +156,16 @@ public KubernetesClient createClient() throws NoSuchAlgorithmException, Unrecove
// JENKINS-38829 CaCertData expects a Base64 encoded certificate
builder.withCaCertData(Base64.encodeBase64String(caCertData.getBytes(UTF_8)));
}

builder = builder.withRequestTimeout(readTimeout * 1000).withConnectionTimeout(connectTimeout * 1000);
builder.withMaxConcurrentRequestsPerHost(maxRequestsPerHost);

if (!StringUtils.isBlank(namespace)) {
builder.withNamespace(namespace);
} else if (StringUtils.isBlank(builder.getNamespace())) {
builder.withNamespace("default");
}

LOGGER.log(FINE, "Creating Kubernetes client: {0}", this.toString());
return new DefaultKubernetesClient(builder.build());
}
Expand Down

0 comments on commit d76e72d

Please sign in to comment.