/******************************************************************************* * Copyright (c) 2012-2017 Red Hat, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Red Hat, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.che.plugin.openshift.client.kubernetes; import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.StringUtils; public final class KubernetesStringUtils { /** * Max length of a Kubernetes name or label; */ private static final int MAX_CHARS = 63; private static final String DOCKER_PREFIX = "docker://"; private KubernetesStringUtils() { } /** * Converts strings to fit requirements of Kubernetes names and labels. * Names in Kubernetes are limited to 63 characters. * @param input the string to normalize * @return the normalized string. */ public static String getNormalizedString(String input) { int end = Math.min(input.length(), MAX_CHARS - 1); return input.substring(0, end); } /** * @param containerID * @return normalized version of 'ContainerID' without 'docker://' prefix and double quotes */ public static String normalizeContainerID(final String containerID) { return StringUtils.replaceOnce(containerID, DOCKER_PREFIX, "").replace("\"", ""); } /** * @param containerID * @return label based on 'ContainerID' (first 12 chars of ID) */ public static String getLabelFromContainerID(final String containerID) { return StringUtils.substring(containerID, 0, 12); } /** * Che workspace id is used as OpenShift service / deployment config name * and must match the regex [a-z]([-a-z0-9]*[a-z0-9]) e.g. "q5iuhkwjvw1w9emg" * * @return randomly generated workspace id */ public static String generateWorkspaceID() { return RandomStringUtils.random(16, true, true).toLowerCase(); } /** * Converts a String into a suitable name for an openshift container. * Kubernetes names are limited to 63 chars and must match the regex * {@code [a-z0-9]([-a-z0-9]*[a-z0-9])?} * @param input the string to convert */ public static String convertToContainerName(String input) { if (input.startsWith("workspace")) { input = input.replaceFirst("workspace", ""); } return getNormalizedString(input.replaceAll("_", "-")); } /** * Converts image stream name (e.g. eclipse/ubuntu_jdk8 to eclipse_ubuntu_jdk8). * This has to be done because for OpenShift ImageStream names, the organization component * of a docker repository is the namespace of the ImageStream, and so '/' is not supported * in ImageStream names. * @param repository the original docker repository String. * @return */ public static String convertPullSpecToImageStreamName(String repository) { repository = stripTagFromPullSpec(repository); return getNormalizedString(repository.replaceAll("/", "_")); } /** * Generates a name to be used as a tag from a docker repository. * In OpenShift, tagging functionality is limited, so while in Docker we may want to * <p>{@code docker tag eclipse/ubuntu_jdk8 eclipse-che/<workspace-id>},<p> this is not * possible in OpenShift. This method returns a trimmed version of {@code <workspace-id>} * @param repository the target repository spec in a {@code docker tag} command. * @return an appropriate tag name */ public static String convertPullSpecToTagName(String repository) { String name; if (repository.contains("/")) { String[] nameSegments = repository.split("/"); name = nameSegments[nameSegments.length - 1]; } else { name = repository; } name = stripTagFromPullSpec(name); name = name.replaceAll("workspace", "") .replaceAll("machine", "") .replaceAll("che_.*", "") .replaceAll("_", ""); name = "che-ws-" + name; return getNormalizedString(name); } /** * Gets an ImageStreamTag name from docker pull specs by converting repository strings * to suit the convention used in {@link KubernetesStringUtils#convertPullSpecToImageStreamName(String)} * and {@link KubernetesStringUtils#convertPullSpecToTagName(String)}. * * <p> e.g. will convert {@code eclipse/ubuntu_jdk8} and {@code eclipse-che/<workspace-id>} * into {@code eclipse_ubuntu_jdk8:<workspace-id>} * * @param oldRepository * The docker image repository that is tracked by the ImageStream * @param newRepository * The docker repository that has been tagged to follow oldRepository * @return A string that can be used to refer to the ImageStreamTag formed from these repositories. */ public static String createImageStreamTagName(String oldRepository, String newRepository) { String tag = convertPullSpecToTagName(newRepository); String repo = convertPullSpecToImageStreamName(oldRepository); return getNormalizedString(String.format("%s:%s", repo, tag)); } /** * Gets the ImageStreamName fromm a docker pull spec. For example, provided * {@code [<registry>]/[<organization>]/<image>:[<tag>]}, will return just {@code <image>} * * In the case where the pull spec does not contain optional components, this method simply * returns the pull spec provided. * * @param pullSpec * @return */ public static String getImageStreamNameFromPullSpec(String pullSpec) { return pullSpec.replaceAll(".*/", "").replaceAll(":.*", ""); } /** * Remove the tag from a pull spec, if applicable. If pull spec does not include a tag, * returns the pull spec unchanged. * @param pullSpec * @return */ public static String stripTagFromPullSpec(String pullSpec) { return pullSpec.replaceAll(":.*", ""); } /** * Gets the tag fromm a docker pull spec. For example, provided * {@code [<registry>]/[<organization>]/<image>:[<tag>]}, will return just {@code <tag>} * * @param pullSpec * @return the tag on the pull spec, or null if pull spec does not contain a tag */ public static String getTagNameFromPullSpec(String pullSpec) { if (!pullSpec.contains(":")) { return null; } return pullSpec.replaceAll(".*:", ""); } }