-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
532 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
# Maven | ||
target | ||
tmp | ||
|
||
# Eclipse | ||
.settings | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package cz.xtf.core.config; | ||
|
||
import java.nio.file.Paths; | ||
|
||
public class HelmConfig { | ||
|
||
public static final String HELM_BINARY_CACHE_PATH = "xtf.helm.binary.cache.path"; | ||
public static final String HELM_BINARY_CACHE_ENABLED = "xtf.helm.binary.cache.enabled"; | ||
public static final String HELM_BINARY_PATH = "xtf.helm.binary.path"; | ||
public static final String HELM_CLIENT_VERSION = "xtf.helm.client.version"; | ||
private static final String HELM_BINARY_CACHE_DEFAULT_FOLDER = "xtf-helm-cache"; | ||
|
||
public static boolean isHelmBinaryCacheEnabled() { | ||
return Boolean.parseBoolean(XTFConfig.get(HELM_BINARY_CACHE_ENABLED, "true")); | ||
} | ||
|
||
public static String binaryCachePath() { | ||
return XTFConfig.get(HELM_BINARY_CACHE_PATH, Paths.get(System.getProperty("java.io.tmpdir"), | ||
HELM_BINARY_CACHE_DEFAULT_FOLDER).toAbsolutePath().normalize().toString()); | ||
} | ||
|
||
public static String binaryPath() { | ||
return XTFConfig.get(HELM_BINARY_PATH); | ||
} | ||
|
||
public static String helmClientVersion() { | ||
return XTFConfig.get(HELM_CLIENT_VERSION, "latest"); | ||
} | ||
|
||
} |
10 changes: 10 additions & 0 deletions
10
core/src/main/java/cz/xtf/core/helm/ConfiguredPathHelmBinaryResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package cz.xtf.core.helm; | ||
|
||
import cz.xtf.core.config.HelmConfig; | ||
|
||
class ConfiguredPathHelmBinaryResolver implements HelmBinaryPathResolver { | ||
@Override | ||
public String resolve() { | ||
return HelmConfig.binaryPath(); | ||
} | ||
} |
132 changes: 132 additions & 0 deletions
132
core/src/main/java/cz/xtf/core/helm/ConfiguredVersionHelmBinaryPathResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
package cz.xtf.core.helm; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.nio.file.StandardCopyOption; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
import org.apache.commons.codec.digest.DigestUtils; | ||
import org.apache.commons.lang3.SystemUtils; | ||
|
||
import cz.xtf.core.config.HelmConfig; | ||
import cz.xtf.core.http.Https; | ||
import cz.xtf.core.openshift.ClusterVersionInfo; | ||
import cz.xtf.core.openshift.ClusterVersionInfoFactory; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@Slf4j | ||
class ConfiguredVersionHelmBinaryPathResolver implements HelmBinaryPathResolver { | ||
|
||
private static final String OCP_4_HELM_BINARY_DOWNLOAD_URL = "https://mirror.openshift.com/pub/openshift-v4/clients/helm"; | ||
|
||
@Override | ||
public String resolve() { | ||
final ClusterVersionInfo clusterVersionInfo = ClusterVersionInfoFactory.INSTANCE.getClusterVersionInfo(); | ||
if (!clusterVersionInfo.getOpenshiftVersion().startsWith("4")) { | ||
log.warn( | ||
"Unsupported Openshift version for Helm client, OCP cluster is of version {}, while currently only OCP 4 is supported", | ||
clusterVersionInfo.getOpenshiftVersion()); | ||
return null; | ||
} | ||
final boolean cacheEnabled = HelmConfig.isHelmBinaryCacheEnabled(); | ||
final String helmClientVersion = HelmConfig.helmClientVersion(); | ||
final String clientUrl = getHelmClientUrlBasedOnConfiguredHelmVersion(helmClientVersion); | ||
final Path archivePath = getCachedOrDownloadClientArchive(clientUrl, helmClientVersion, cacheEnabled); | ||
return unpackHelmClientArchive(archivePath, !cacheEnabled); | ||
} | ||
|
||
private String unpackHelmClientArchive(final Path archivePath, final boolean deleteArchiveWhenDone) { | ||
Objects.requireNonNull(archivePath); | ||
|
||
try { | ||
List<String> args = Stream | ||
.of("tar", "-xf", archivePath.toAbsolutePath().toString(), "-C", | ||
getProjectHelmDir().toAbsolutePath().toString()) | ||
.collect(Collectors.toList()); | ||
ProcessBuilder pb = new ProcessBuilder(args); | ||
|
||
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); | ||
pb.redirectError(ProcessBuilder.Redirect.INHERIT); | ||
|
||
int result = pb.start().waitFor(); | ||
|
||
if (result != 0) { | ||
throw new IOException("Failed to execute: " + args); | ||
} | ||
|
||
} catch (IOException | InterruptedException e) { | ||
throw new IllegalStateException("Failed to extract helm binary " + archivePath.toAbsolutePath(), e); | ||
} | ||
|
||
try { | ||
if (deleteArchiveWhenDone) { | ||
Files.delete(archivePath); | ||
} | ||
} catch (IOException ioe) { | ||
log.warn("It wasn't possible to delete Helm client archive {}", archivePath.toAbsolutePath(), ioe); | ||
} | ||
try (Stream<Path> helmDirContents = Files.list(getProjectHelmDir())) { | ||
Path helmBinaryFile = helmDirContents.collect(Collectors.toList()).get(0); | ||
if (!helmBinaryFile.getFileName().toString().equals("helm")) { | ||
Files.move(helmBinaryFile, helmBinaryFile.resolveSibling("helm"), StandardCopyOption.REPLACE_EXISTING); | ||
} | ||
} catch (IOException e) { | ||
throw new IllegalStateException("Error when extracting Helm client binary", e); | ||
} | ||
return getProjectHelmDir().resolve("helm").toAbsolutePath().toString(); | ||
} | ||
|
||
private Path getCachedOrDownloadClientArchive(final String url, final String version, final boolean cacheEnabled) { | ||
Objects.requireNonNull(url); | ||
|
||
log.debug("Trying to load Helm client archive from cache (enabled: {}) or download it from {}.", cacheEnabled, | ||
url); | ||
Path archivePath; | ||
if (cacheEnabled) { | ||
Path cachePath = Paths.get(HelmConfig.binaryCachePath(), version, DigestUtils.md5Hex(url)); | ||
archivePath = cachePath.resolve("helm.tar.gz"); | ||
if (Files.exists(archivePath)) { | ||
// it is cached, removed immediately | ||
log.debug("Helm client archive is already in cache: {}.", archivePath.toAbsolutePath()); | ||
return archivePath; | ||
} | ||
log.debug("Helm client archive not found in cache, downloading it."); | ||
} else { | ||
archivePath = getProjectHelmDir().resolve("helm.tar.gz"); | ||
log.debug("Cache is disabled, downloading Helm client archive to {}.", archivePath.toAbsolutePath()); | ||
} | ||
|
||
try { | ||
Https.copyHttpsURLToFile(url, archivePath.toFile(), 20_000, 300_000); | ||
} catch (IOException ioe) { | ||
throw new IllegalStateException("Failed to download and extract helm binary from " + url, ioe); | ||
} | ||
return archivePath; | ||
} | ||
|
||
private String getHelmClientUrlBasedOnConfiguredHelmVersion(final String helmClientVersion) { | ||
String systemType = "linux"; | ||
if (SystemUtils.IS_OS_MAC) { | ||
systemType = "darwin"; | ||
} | ||
return String.format("%s/%s/helm-%s-amd64.tar.gz", OCP_4_HELM_BINARY_DOWNLOAD_URL, helmClientVersion, | ||
systemType); | ||
} | ||
|
||
private Path getProjectHelmDir() { | ||
Path dir = Paths.get("tmp/helm/"); | ||
|
||
try { | ||
Files.createDirectories(dir); | ||
} catch (IOException ioe) { | ||
throw new IllegalStateException("Failed to create directory " + dir.toAbsolutePath(), ioe); | ||
} | ||
|
||
return dir; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package cz.xtf.core.helm; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import org.apache.commons.lang3.ArrayUtils; | ||
|
||
import cz.xtf.core.config.OpenShiftConfig; | ||
import cz.xtf.core.openshift.CLIUtils; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@Slf4j | ||
public class HelmBinary { | ||
|
||
private final String path; | ||
private final String helmConfigPath; | ||
private final String kubeUsername; | ||
private final String kubeToken; | ||
private final String namespace; | ||
|
||
public HelmBinary(String path, String kubeUsername, String kubeToken, String namespace) { | ||
this.path = path; | ||
this.kubeUsername = kubeUsername; | ||
this.kubeToken = kubeToken; | ||
Path helmConfigFile = Paths.get(path).getParent().resolve(".config"); | ||
try { | ||
helmConfigFile = Files.createDirectories(helmConfigFile); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
this.helmConfigPath = helmConfigFile.toAbsolutePath().toString(); | ||
this.namespace = namespace; | ||
} | ||
|
||
public HelmBinary(String path, String helmConfigPath, String kubeUsername, String kubeToken, String namespace) { | ||
this.path = path; | ||
this.helmConfigPath = helmConfigPath; | ||
this.kubeUsername = kubeUsername; | ||
this.kubeToken = kubeToken; | ||
this.namespace = namespace; | ||
} | ||
|
||
public String execute(String... args) { | ||
Map<String, String> environmentVariables = new HashMap<>(); | ||
environmentVariables.put("HELM_CONFIG_HOME", helmConfigPath); | ||
environmentVariables.put("HELM_KUBEAPISERVER", OpenShiftConfig.url()); | ||
environmentVariables.put("HELM_KUBEASUSER", kubeUsername); | ||
environmentVariables.put("HELM_KUBETOKEN", kubeToken); | ||
environmentVariables.put("HELM_NAMESPACE", namespace); | ||
return CLIUtils.executeCommand(environmentVariables, ArrayUtils.addAll(new String[] { path }, args)); | ||
} | ||
|
||
} |
31 changes: 31 additions & 0 deletions
31
core/src/main/java/cz/xtf/core/helm/HelmBinaryManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package cz.xtf.core.helm; | ||
|
||
import cz.xtf.core.config.OpenShiftConfig; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@Slf4j | ||
class HelmBinaryManager { | ||
private final String helmBinaryPath; | ||
|
||
HelmBinaryManager(String helmBinaryPath) { | ||
this.helmBinaryPath = helmBinaryPath; | ||
} | ||
|
||
String getHelmBinaryPath() { | ||
return helmBinaryPath; | ||
} | ||
|
||
public HelmBinary adminBinary() { | ||
return getBinary(OpenShiftConfig.adminToken(), OpenShiftConfig.adminUsername(), OpenShiftConfig.namespace()); | ||
} | ||
|
||
public HelmBinary masterBinary() { | ||
return getBinary(OpenShiftConfig.masterToken(), OpenShiftConfig.masterUsername(), OpenShiftConfig.namespace()); | ||
} | ||
|
||
private static HelmBinary getBinary(String token, String username, String namespace) { | ||
String helmBinaryPath = HelmBinaryManagerFactory.INSTANCE.getHelmBinaryManager().getHelmBinaryPath(); | ||
return new HelmBinary(helmBinaryPath, username, token, namespace); | ||
|
||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
core/src/main/java/cz/xtf/core/helm/HelmBinaryManagerFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package cz.xtf.core.helm; | ||
|
||
import java.util.Arrays; | ||
|
||
public enum HelmBinaryManagerFactory { | ||
|
||
INSTANCE; | ||
|
||
private volatile HelmBinaryManager helmBinaryManager; | ||
|
||
HelmBinaryManager getHelmBinaryManager() { | ||
HelmBinaryManager localHelmBinaryManagerRef = helmBinaryManager; | ||
if (localHelmBinaryManagerRef == null) { | ||
synchronized (HelmBinaryManagerFactory.class) { | ||
localHelmBinaryManagerRef = helmBinaryManager; | ||
if (localHelmBinaryManagerRef == null) { | ||
for (HelmBinaryPathResolver resolver : Arrays.asList(new ConfiguredPathHelmBinaryResolver(), | ||
new ConfiguredVersionHelmBinaryPathResolver())) { | ||
String resolvedPath = resolver.resolve(); | ||
if (resolvedPath != null) { | ||
helmBinaryManager = localHelmBinaryManagerRef = new HelmBinaryManager(resolvedPath); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
} | ||
} | ||
return localHelmBinaryManagerRef; | ||
|
||
} | ||
|
||
} |
13 changes: 13 additions & 0 deletions
13
core/src/main/java/cz/xtf/core/helm/HelmBinaryPathResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package cz.xtf.core.helm; | ||
|
||
/** | ||
* Interface for resolving Helm client binary | ||
*/ | ||
interface HelmBinaryPathResolver { | ||
/** | ||
* Resolves Helm client binary path | ||
* | ||
* @return Helm client binary path | ||
*/ | ||
String resolve(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package cz.xtf.core.helm; | ||
|
||
public class HelmClients { | ||
|
||
public static HelmBinary adminBinary() { | ||
return HelmBinaryManagerFactory.INSTANCE.getHelmBinaryManager().adminBinary(); | ||
} | ||
|
||
public static HelmBinary masterBinary() { | ||
return HelmBinaryManagerFactory.INSTANCE.getHelmBinaryManager().masterBinary(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.