package com.nirima.jenkins.plugins.docker.utils; import com.cloudbees.plugins.credentials.Credentials; import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials; import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.model.AuthConfig; import com.github.dockerjava.api.model.AuthConfigurations; import com.github.dockerjava.api.model.ExposedPort; import com.github.dockerjava.api.model.Ports; import com.github.dockerjava.core.NameParser; import com.nirima.jenkins.plugins.docker.DockerCloud; import com.nirima.jenkins.plugins.docker.DockerPluginConfiguration; import com.nirima.jenkins.plugins.docker.DockerRegistry; import com.nirima.jenkins.plugins.docker.DockerSlave; import org.jenkinsci.main.modules.instance_identity.InstanceIdentity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Collection; import java.util.Map; import javax.annotation.Nullable; import hudson.Launcher; import hudson.Util; import hudson.model.AbstractBuild; import hudson.model.Node; import hudson.model.Run; import hudson.remoting.Channel; import hudson.remoting.VirtualChannel; import hudson.slaves.Cloud; import jenkins.model.Jenkins; import shaded.com.google.common.base.Optional; import shaded.com.google.common.base.Predicate; import shaded.com.google.common.collect.Collections2; import shaded.com.google.common.collect.Iterables; import static hudson.plugins.sshslaves.SSHLauncher.lookupSystemCredentials; /** * Utilities to fetch things out of jenkins environment. */ public class JenkinsUtils { private static final Logger LOG = LoggerFactory.getLogger(JenkinsUtils.class); private static String _id; /** * If the build was on a cloud, get the ID of that cloud. */ public static Optional<DockerCloud> getCloudForBuild(AbstractBuild build) { Node node = build.getBuiltOn(); if (node instanceof DockerSlave) { DockerSlave slave = (DockerSlave) node; return Optional.of(slave.getCloud()); } return Optional.absent(); } /** * If the build was workflow, get the ID of that channel. */ public static Optional<DockerCloud> getCloudForChannel(VirtualChannel channel) { if( channel instanceof Channel) { Channel c = (Channel)channel; Node node = Jenkins.getInstance().getNode( c.getName() ); if (node instanceof DockerSlave) { DockerSlave slave = (DockerSlave) node; return Optional.of(slave.getCloud()); } } return Optional.absent(); } public static Optional<DockerCloud> getCloudThatWeBuiltOn(Run<?,?> build, Launcher launcher) { Optional<DockerCloud> cloud; // A bit unpleasant, but the getBuiltOn method is in AbstractBuild and // we may be a workflow run. if( build instanceof AbstractBuild ) { cloud = JenkinsUtils.getCloudForBuild((AbstractBuild)build); } else { cloud = JenkinsUtils.getCloudForChannel(launcher.getChannel()); } return cloud; } /** * Get the list of Docker servers. * * @return the list as a LinkedList of DockerCloud */ public static synchronized Collection<DockerCloud> getServers() { Collection clouds = Collections2.filter(Jenkins.getInstance().clouds, new Predicate<Cloud>() { public boolean apply(@Nullable Cloud input) { return input instanceof DockerCloud; } }); return (Collection<DockerCloud>)clouds; } public static DockerCloud getServer(final String serverName) { return Iterables.find(getServers(), new Predicate<DockerCloud>() { public boolean apply(@Nullable DockerCloud input) { return serverName.equals(input.getDisplayName()); } }); } public static String getHostnameFromBinding(InspectContainerResponse inspectContainerResponse) { Map<ExposedPort, Ports.Binding[]> bindings = inspectContainerResponse.getHostConfig().getPortBindings().getBindings(); if (bindings != null && !bindings.isEmpty()) { Ports.Binding[] binding = bindings.values().iterator().next(); if (binding != null && binding.length > 0) { String hostIp = binding[0].getHostIp(); return getHostnameForIp(hostIp); } } return null; } private static String getHostnameForIp(String hospIp) { try { return InetAddress.getByName(hospIp).getHostName(); } catch (UnknownHostException e) { return hospIp; } } public static AuthConfigurations getAuthConfigurations() { AuthConfigurations authConfigurations = new AuthConfigurations(); for(DockerRegistry registry : DockerPluginConfiguration.get().getRegistryList()) { AuthConfig ac = makeAuthConfig(registry); if( ac != null ) { authConfigurations.addConfig(ac); } } return authConfigurations; } public static AuthConfig getAuthConfigFor(String imageName) { // Do we have an auth config for the registry defined in this tag? NameParser.ReposTag reposTag = NameParser.parseRepositoryTag(imageName); NameParser.HostnameReposName hostnameReposName = NameParser.resolveRepositoryName(reposTag.repos); DockerRegistry registry = DockerPluginConfiguration.get().getRegistryByName(hostnameReposName.hostname); return makeAuthConfig(registry); } protected static AuthConfig makeAuthConfig(DockerRegistry registry) { if( registry == null ) return null; Credentials credentials = lookupSystemCredentials(registry.credentialsId); final AuthConfig authConfig = makeAuthConfig(credentials); if( authConfig == null ) return null; return authConfig.withRegistryAddress(registry.registry); } protected static AuthConfig makeAuthConfig(Credentials credentials) { if (credentials instanceof StandardUsernamePasswordCredentials) { StandardUsernamePasswordCredentials usernamePasswordCredentials = ((StandardUsernamePasswordCredentials) credentials); AuthConfig ac = new AuthConfig() .withUsername( usernamePasswordCredentials.getUsername() ) .withPassword( usernamePasswordCredentials.getPassword().getPlainText() ); return ac; } return null; } public static String getInstanceId() { try { if( _id == null ) { _id = Util.getDigestOf( new ByteArrayInputStream(InstanceIdentity.get().getPublic().getEncoded())); } } catch (IOException e) { LOG.error("Could not get Jenkins instance ID."); _id = ""; } return _id; } }