Skip to content

Commit

Permalink
feat (jkube-kit/common) : Add CLIDownloaderUtil to download cli binar…
Browse files Browse the repository at this point in the history
…ies (#2454)

Add CLIDownloaderUtil to download CLI binaries from remote sources.

Signed-off-by: Rohan Kumar <rohaan@redhat.com>
  • Loading branch information
rohanKanojia committed Nov 29, 2023
1 parent b3281a8 commit a75361d
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.kit.common.util;

import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.http.HttpClient;
import io.fabric8.kubernetes.client.http.HttpResponse;
import io.fabric8.kubernetes.client.utils.HttpClientUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import static org.apache.commons.io.FilenameUtils.removeExtension;
import static org.eclipse.jkube.kit.common.archive.ArchiveDecompressor.extractArchive;

public class CliDownloaderUtil {
private CliDownloaderUtil() { }

public static String downloadCli(String baseDownloadUrl, String cliBinaryPrefix, String cliArtifactName, File outputDirectory) throws IOException {
URL downloadUrl = new URL(String.format("%s/%s", baseDownloadUrl, cliArtifactName));
File targetExtractionDir = outputDirectory.toPath().resolve(removeExtension(cliArtifactName)).toFile();

downloadAndExtractTo(downloadUrl, targetExtractionDir);

return getCliBinaryPathFromExtractedDir(targetExtractionDir, cliBinaryPrefix);
}

private static void downloadAndExtractTo(URL downloadUrl, File target) throws IOException {
try (HttpClient client = HttpClientUtils.getHttpClientFactory().newBuilder(Config.empty()).build()) {
final HttpResponse<InputStream> response = client.sendAsync(
client.newHttpRequestBuilder().timeout(30, TimeUnit.MINUTES).url(downloadUrl).build(), InputStream.class)
.get();
if (!response.isSuccessful()) {
throw new IOException("Server returned (" + response.code() + ") while downloading " + downloadUrl);
}
try (InputStream is = response.body()) {
extractArchive(is, target);
}
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
throw new IOException("Download interrupted", ex);
} catch (IOException | ExecutionException e) {
throw new IOException("Failed to download URL " + downloadUrl + " to " + target + ": " + e, e);
}
}

private static String getCliBinaryPathFromExtractedDir(File targetExtractionDir, String binaryPrefix) {
String cliPath = null;
File[] cliArtifactList = targetExtractionDir.listFiles(f -> f.getName().startsWith(binaryPrefix));
if (cliArtifactList != null && cliArtifactList.length >= 1) {
cliPath = cliArtifactList[0].getAbsolutePath();
}
return cliPath;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.kit.common.util;

import org.eclipse.jkube.kit.common.TestHttpStaticServer;
import org.eclipse.jkube.kit.common.assertj.FileAssertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.io.File;
import java.io.IOException;

import static org.assertj.core.api.Assertions.assertThatIOException;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;

class CliDownloaderUtilTest {
@TempDir
private File temporaryFolder;

@Test
void downloadCLI_whenUnixArtifactProvided_thenDownloadAndExtract() throws IOException {
File remoteDirectory = new File(getClass().getResource("/downloadable-artifacts").getFile());
try (TestHttpStaticServer http = new TestHttpStaticServer(remoteDirectory)) {
// Given
String baseUrl = String.format("http://localhost:%d", http.getPort());

// When
String downloadPath = CliDownloaderUtil.downloadCli(baseUrl, "foo", "foo-v0.0.1-linux.tgz", temporaryFolder);

// Then
assertThat(downloadPath).contains("foo-v0.0.1-linux", "foo");
FileAssertions.assertThat(temporaryFolder)
.exists()
.fileTree()
.containsExactlyInAnyOrder("foo-v0.0.1-linux", "foo-v0.0.1-linux/foo");
}
}

@Test
void downloadCLI_whenZipArtifactProvided_thenDownloadAndExtract() throws IOException {
File remoteDirectory = new File(getClass().getResource("/downloadable-artifacts").getFile());
try (TestHttpStaticServer http = new TestHttpStaticServer(remoteDirectory)) {
// Given
String baseUrl = String.format("http://localhost:%d", http.getPort());

// When
String downloadPath = CliDownloaderUtil.downloadCli(baseUrl, "foo", "foo-v0.0.1-windows.zip", temporaryFolder);

// Then
assertThat(downloadPath).contains("foo-v0.0.1-windows", "foo.exe");
FileAssertions.assertThat(temporaryFolder)
.exists()
.fileTree()
.containsExactlyInAnyOrder("foo-v0.0.1-windows", "foo-v0.0.1-windows/foo.exe");
}
}

@Test
void downloadCLI_whenArtifactNotAvailable_thenThrowException() throws IOException {
File remoteDirectory = new File(getClass().getResource("/downloadable-artifacts").getFile());
try (TestHttpStaticServer http = new TestHttpStaticServer(remoteDirectory)) {
// Given
String baseUrl = String.format("http://localhost:%d", http.getPort());

// When + Then
assertThatIOException()
.isThrownBy(() -> CliDownloaderUtil.downloadCli(baseUrl, "idontexist", "idontexist-v0.0.1-linux.tgz", temporaryFolder))
.withMessageContaining("Failed to download");
}
}
}
Binary file not shown.
Binary file not shown.

0 comments on commit a75361d

Please sign in to comment.