All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.fabric8.kubeapitest.binary.BinaryDownloader Maven / Gradle / Ivy

/*
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.fabric8.kubeapitest.binary;

import io.fabric8.kubeapitest.KubeAPITestException;
import io.fabric8.kubeapitest.Utils;
import io.fabric8.kubeapitest.binary.repo.BinaryRepo;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class BinaryDownloader {

  private static final Logger log = LoggerFactory.getLogger(BinaryDownloader.class);

  private static final String OBJECT_TAR_PREFIX = "kubebuilder-tools-";

  private final String kubeAPITestDir;
  private final BinaryRepo binaryRepo;
  private final OSInfo osInfoProvider;
  private static final Map versionLocks = new ConcurrentHashMap<>();

  public BinaryDownloader(String kubeAPITestDir, OSInfo osInfoProvider) {
    this.kubeAPITestDir = kubeAPITestDir;
    this.osInfoProvider = osInfoProvider;
    this.binaryRepo = new BinaryRepo(osInfoProvider);
  }

  BinaryDownloader(String kubeAPITestDir, BinaryRepo binaryRepo, OSInfo osInfoProvider) {
    this.kubeAPITestDir = kubeAPITestDir;
    this.binaryRepo = binaryRepo;
    this.osInfoProvider = osInfoProvider;
  }

  public File download(String version) {
    var lock = versionLocks.computeIfAbsent(version, v -> new ReentrantLock());
    var dirForVersion = dirForVersion(version);
    lock.lock();
    try {
      if (dirForVersion.exists()) {
        return dirForVersion;
      }
      new File(kubeAPITestDir, BinaryManager.BINARY_LIST_DIR).mkdirs();
      log.info("Downloading binaries with version: {}", version);
      var tempFile = binaryRepo.downloadVersionToTempFile(version);
      File dir = createDirForBinaries(version);
      extractFiles(tempFile, dir);
      log.debug("Binary downloaded and extracted");
      var deleted = tempFile.delete();
      if (!deleted) {
        log.warn("Unable to delete temp file: {}", tempFile.getPath());
      }
    } finally {
      lock.unlock();
    }
    return dirForVersion;
  }

  public File downloadLatest() {
    String latest = findLatestVersion();
    return download(latest);
  }

  public File downloadLatestWildcard(String wildcardVersion) {
    String latest = findLatestOfWildcard(wildcardVersion);
    return download(latest);
  }

  private void extractFiles(File tempFile, File dir) {
    try (TarArchiveInputStream tarIn = new TarArchiveInputStream(
        new GzipCompressorInputStream(new BufferedInputStream(new FileInputStream(tempFile))))) {
      var entry = tarIn.getNextTarEntry();
      while (entry != null) {
        if (!entry.isDirectory()) {
          File file = extractEntry(entry, dir, tarIn);
          if (!file.setExecutable(true)) {
            throw new KubeAPITestException("Cannot make the file executable: " + file.getPath());
          }
        }
        entry = tarIn.getNextTarEntry();
      }
    } catch (IOException e) {
      throw new KubeAPITestException(e);
    }
  }

  private File extractEntry(TarArchiveEntry entry, File dir, TarArchiveInputStream tarIn)
      throws IOException {
    String name = entry.getName();
    File targetFile;
    if (name.contains(Binaries.KUBECTL_BINARY_NAME)) {
      targetFile = new File(dir, Binaries.KUBECTL_BINARY_NAME);
    } else if (name.contains(Binaries.API_SERVER_BINARY_NAME)) {
      targetFile = new File(dir, Binaries.API_SERVER_BINARY_NAME);
    } else if (name.contains(Binaries.ETCD_BINARY_NAME)) {
      targetFile = new File(dir, Binaries.ETCD_BINARY_NAME);
    } else {
      throw new KubeAPITestException("Unexpected entry with name: " + entry.getName());
    }
    Files.copy(tarIn, targetFile.toPath());
    return targetFile;
  }

  private File createDirForBinaries(String version) {
    var dir = dirForVersion(version);
    if (!dir.mkdirs()) {
      throw new KubeAPITestException("Cannot created director: " + dir.getPath());
    }
    return dir;
  }

  private File dirForVersion(String version) {
    return new File(kubeAPITestDir, BinaryManager.BINARY_LIST_DIR + File.separator
        + version + Utils.platformSuffix(osInfoProvider));
  }

  public String findLatestVersion() {
    var allRelevantVersions = listAllRelevantVersions().sorted(Utils.SEMVER_COMPARATOR).collect(Collectors.toList());
    if (allRelevantVersions.isEmpty()) {
      throw new KubeAPITestException("Cannot find relevant version to download");
    }
    return allRelevantVersions.get(allRelevantVersions.size() - 1);
  }

  public String findLatestOfWildcard(String wildcardVersion) {
    var allRelevantVersions = listAllRelevantVersions()
        .filter(v -> v.startsWith(Utils.wildcardToPrefix(wildcardVersion)))
        .sorted(Utils.SEMVER_COMPARATOR).collect(Collectors.toList());
    if (allRelevantVersions.isEmpty()) {
      throw new KubeAPITestException(
          "Cannot find relevant version to download for wildcard version: " + wildcardVersion);
    }
    return allRelevantVersions.get(allRelevantVersions.size() - 1);
  }

  private Stream listAllRelevantVersions() {
    var objects = binaryRepo.listObjectNames();
    return objects.filter(o -> o.contains(osInfoProvider.getOSName())
        && o.contains(osInfoProvider.getOSArch()))
        .map(o -> {
          String stripped = o.replace(OBJECT_TAR_PREFIX, "");
          String version = stripped.substring(0, stripped.indexOf("-"));
          if (version.startsWith("v")) {
            version = version.substring(1);
          }
          return version;
        });
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy