public DockerRegistryEndpoint getRegistry() { if (registry == null) { registry = new DockerRegistryEndpoint(null, pullCredentialsId); } return registry; }
@Override public UninstantiatedDescribable uninstantiate(Step step) throws UnsupportedOperationException { RegistryEndpointStep s = (RegistryEndpointStep) step; Map<String, Object> args = new TreeMap<>(); args.put("url", s.registry.getUrl()); args.put("credentialsId", s.registry.getCredentialsId()); args.put("toolName", s.toolName); args.values().removeAll(Collections.singleton(null)); return new UninstantiatedDescribable(args); }
/** * @deprecated Call {@link #newKeyMaterialFactory(Item, VirtualChannel, Launcher, TaskListener)} */ @Deprecated public KeyMaterialFactory newKeyMaterialFactory(Item context, @Nonnull VirtualChannel target) throws IOException, InterruptedException { return newKeyMaterialFactory(context, target, null, TaskListener.NULL); }
private Object readResolve() { if (pushCredentialsId == null && registry != null) { pushCredentialsId = registry.getCredentialsId(); } if (pullCredentialsId != null) { fromRegistry = new DockerRegistryEndpoint(null, pullCredentialsId); } return this; } }
private Object readResolve() throws ObjectStreamException { // coming from an older version <1.0 ? let's try to parse the registry if (registry == null) { registry = DockerRegistryEndpoint.fromImageName(repoName, null); if (registry.getUrl() != null) { repoName = repoName.substring(repoName.indexOf('/') + 1); // take out the host:port part logger.log( Level.WARNING, "Using Docker registry from old configuration field, you may need to configure credentials in the build step: {0} {1}", new String[] { registry.getUrl(), repoName }); } } return this; }
@DataBoundSetter public void setDockerCredentials(List<DockerRegistryEndpoint> dockerCredentials) { List<DockerRegistryEndpoint> endpoints = new ArrayList<>(); for (DockerRegistryEndpoint endpoint : dockerCredentials) { String credentialsId = org.apache.commons.lang.StringUtils.trimToNull(endpoint.getCredentialsId()); if (credentialsId == null) { // no credentials item is selected, skip this endpoint continue; } String registryUrl = org.apache.commons.lang.StringUtils.trimToNull(endpoint.getUrl()); // null URL results in "https://index.docker.io/v1/" effectively if (registryUrl != null) { // It's common that the user omits the scheme prefix, we add http:// as default. // Otherwise it will cause MalformedURLException when we call endpoint.getEffectiveURL(); if (!Constants.URI_SCHEME_PREFIX.matcher(registryUrl).find()) { registryUrl = "http://" + registryUrl; } } endpoints.add(new DockerRegistryEndpoint(registryUrl, credentialsId)); } this.dockerCredentials = endpoints; }
public AuthConfig getAuthConfig(Job<?, ?> project) { if (dockerRegistryEndpoint == null || Strings.isNullOrEmpty(dockerRegistryEndpoint.getCredentialsId())) { return null; } AuthConfig authConfig = new AuthConfig(); authConfig.withRegistryAddress(dockerRegistryEndpoint.getUrl()); DockerRegistryToken token = this.dockerRegistryEndpoint.getToken(project); if (token != null) { String credentials = new String(Base64.decodeBase64(token.getToken()), Charsets.UTF_8); String[] usernamePassword = credentials.split(":"); authConfig.withUsername(usernamePassword[0]); authConfig.withPassword(usernamePassword[1]); authConfig.withEmail(token.getEmail()); } return authConfig; }
protected Object readResolve() { if (volumesFrom != null) { if (StringUtils.isNotBlank(volumesFrom)) { setVolumesFrom2(new String[]{volumesFrom}); } volumesFrom = null; } if (pullCredentialsId == null && registry != null) { pullCredentialsId = registry.getCredentialsId(); } return this; }
@Override public List<ResolvedDockerRegistryEndpoint> resolveEndpoints(Item context) throws IOException { List<ResolvedDockerRegistryEndpoint> endpoints = new ArrayList<>(); List<DockerRegistryEndpoint> configured = getDockerCredentials(); for (DockerRegistryEndpoint endpoint : configured) { DockerRegistryToken token = endpoint.getToken(context); if (token == null) { throw new IllegalArgumentException("No credentials found for " + endpoint); } endpoints.add(new ResolvedDockerRegistryEndpoint(endpoint.getEffectiveUrl(), token)); } return endpoints; }
@Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { // TODO could maybe use Docker REST API, need first to check Java can talk with linux sockets // TODO maybe use DockerHost API int status = 0; KeyMaterial key = null; final EnvVars env = build.getEnvironment(listener); String expandedImage = env.expand(image); try { // get Docker registry credentials key = registry.newKeyMaterialFactory(build).materialize(); status = launcher.launch() .cmds("docker", "pull", registry.imageName(expandedImage)).envs(key.env()) .writeStdin().stdout(listener.getLogger()).stderr(listener.getLogger()).join(); if (status != 0) { throw new RuntimeException("Failed to pull docker image"); } } catch (IOException e) { throw new RuntimeException("Failed to pull docker image", e); } catch (InterruptedException e) { throw new RuntimeException("Failed to pull docker image", e); } finally { if (key != null) { key.close(); } } listener.getLogger().println("docker pull " + image); return true; }
/** * Decorates the repository ID namespace/name (ie. "jenkinsci/workflow-demo") with registry prefix * (docker.acme.com:80/jenkinsci/workflow-demo). * * @param userAndRepo * the namespace/name part to append to the registry * @return the full registry:port/namespace/name string * @throws IOException */ public String imageName(@Nonnull String userAndRepo) throws IOException { if (userAndRepo == null) { throw new IllegalArgumentException("Image name cannot be null."); } if (url == null) { return userAndRepo; } URL effectiveUrl = getEffectiveUrl(); StringBuilder s = new StringBuilder(effectiveUrl.getHost()); if (effectiveUrl.getPort() > 0 ) { s.append(':').append(effectiveUrl.getPort()); } if (userAndRepo.startsWith(String.valueOf(s))) { return userAndRepo; } return s.append('/').append(userAndRepo).toString(); }
/** * Fully qualified repository/image name with the registry url in front * @return ie. docker.acme.com/jdoe/busybox * @throws IOException */ public String getRepo() throws IOException { return getRegistry().imageName(repoName); }
@Override public String getRegistryCredentialsId(@Nullable Run run) { if (config.getRegistry() != null && !StringUtils.isBlank(config.getRegistry().getCredentialsId())) { return config.getRegistry().getCredentialsId(); } else { return null; } } }
/** * Makes the credentials available locally and returns {@link KeyMaterialFactory} that gives you the parameters * needed to access it. */ public KeyMaterialFactory newKeyMaterialFactory(@CheckForNull Item context, @Nonnull VirtualChannel target, @CheckForNull Launcher launcher, @Nonnull TaskListener listener) throws IOException, InterruptedException { if (credentialsId == null) { return KeyMaterialFactory.NULL; // nothing needed to be done } DockerRegistryToken token = getToken(context); if (token == null) { throw new AbortException("Could not find credentials matching " + credentialsId); } return token.newKeyMaterialFactory(getEffectiveUrl(), target, launcher, listener); }
@Override public String getRegistryUrl(@Nullable Run run) { if (run != null) { Job job = run.getParent(); ItemGroup parent = job.getParent(); while (parent != null) { if (parent instanceof AbstractFolder) { AbstractFolder folder = (AbstractFolder) parent; FolderConfig config = (FolderConfig) folder.getProperties().get(FolderConfig.class); if (config != null) { DockerRegistryEndpoint registry = config.getRegistry(); if (registry != null && !StringUtils.isBlank(registry.getUrl())) { return registry.getUrl(); } } } if (parent instanceof Item) { parent = ((Item) parent).getParent(); } else { parent = null; } } } return null; }
/** * Decorates the repository ID namespace/name (ie. "jenkinsci/workflow-demo") with registry prefix * (docker.acme.com:80/jenkinsci/workflow-demo). * * @param userAndRepo * the namespace/name part to append to the registry * @return the full registry:port/namespace/name string * @throws IOException */ public String imageName(@Nonnull String userAndRepo) throws IOException { if (userAndRepo == null) { throw new IllegalArgumentException("Image name cannot be null."); } if (url == null) { return userAndRepo; } URL effectiveUrl = getEffectiveUrl(); StringBuilder s = new StringBuilder(effectiveUrl.getHost()); if (effectiveUrl.getPort() > 0 ) { s.append(':').append(effectiveUrl.getPort()); } if (userAndRepo.startsWith(String.valueOf(s))) { return userAndRepo; } return s.append('/').append(userAndRepo).toString(); }
private Object readResolve() { if (pushOnSuccess && registry == null) { registry = new DockerRegistryEndpoint(null, null); } return this; } }
withId(registry.getCredentialsId())); throw new IllegalArgumentException("Invalid Credential ID " + registry.getCredentialsId()); if (registry.getUrl() != null) { auth.withRegistryAddress(registry.getUrl());
/** * @deprecated Call {@link #newKeyMaterialFactory(Item, FilePath, Launcher, EnvVars, TaskListener, String)} */ @Deprecated public KeyMaterialFactory newKeyMaterialFactory(Item context, @Nonnull VirtualChannel target) throws IOException, InterruptedException { return newKeyMaterialFactory(context, target, null, TaskListener.NULL); }