projects/aws/image-builder/builder/manifests.go (168 lines of code) (raw):
package builder
import (
"archive/tar"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
releasev1 "github.com/aws/eks-anywhere/release/api/v1alpha1"
k8syaml "sigs.k8s.io/yaml"
)
// DownloadManifests connects to the internet, clones a fresh copy of eks-a-build-tooling repo
// and pulls EKS-A and EKS-D artifacts for all supported releases and creates an archive.
func (b *BuildOptions) DownloadManifests() error {
// Clone build tooling from the latest release branch
cwd, err := os.Getwd()
if err != nil {
return fmt.Errorf("Error retrieving current working directory: %v", err)
}
buildToolingRepoPath := getBuildToolingPath(cwd)
_, _, err = b.prepBuildToolingRepo(buildToolingRepoPath)
if err != nil {
return err
}
// Download eks-d manifests
manifestsPath := filepath.Join(cwd, "manifests")
if err = downloadEKSDManifests(manifestsPath); err != nil {
return err
}
// Download eks-a manifests
if err = downloadEKSAManifests(manifestsPath); err != nil {
return err
}
// Create tarball of the downloaded manifests
log.Println("Creating tarball of downloaded manifests")
if err = createTarball(manifestsTarballName, manifestsPath); err != nil {
return err
}
log.Printf("Manifest tarball %s was successfully created", manifestsTarballName)
// Clean up manifests directory
if err = os.RemoveAll(manifestsPath); err != nil {
return err
}
cleanup(buildToolingRepoPath)
return nil
}
func downloadEKSDManifests(outputPath string) error {
// Get all eksDReleases with their release numbers
eksDReleaseBranchesWithNumber, err := getEksDReleaseBranchesWithNumber()
if err != nil {
return err
}
// Create output directory path
if err = os.MkdirAll(outputPath, 0o755); err != nil {
return err
}
for branch, number := range eksDReleaseBranchesWithNumber {
manifestUrl := fmt.Sprintf("https://%s/kubernetes-%s/kubernetes-%s-eks-%s.yaml", eksDistroProdDomain, branch, branch, number)
manifestFileName := fmt.Sprintf(eksDistroManifestFileNameFormat, branch)
manifestFilePath := filepath.Join(outputPath, manifestFileName)
log.Printf("Downloading eks-d manifest for release branch %s, release number %s", branch, number)
if err := downloadFile(manifestFilePath, manifestUrl); err != nil {
return err
}
}
return nil
}
func downloadEKSAManifests(outputPath string) error {
// Download Release manifest
releaseManifestUrl, err := getEksAReleasesManifestURL(false)
if err != nil {
return err
}
// Create output directory path
if err = os.MkdirAll(outputPath, 0o755); err != nil {
return err
}
releaseManifestPath := filepath.Join(outputPath, eksAnywhereManifestFileName)
log.Printf("Downloading eks-a release manifest")
if err := downloadFile(releaseManifestPath, releaseManifestUrl); err != nil {
return err
}
// Download all the bundles from release manifest
releaseManifestData, err := os.ReadFile(releaseManifestPath)
if err != nil {
return err
}
releases := &releasev1.Release{}
if err = k8syaml.Unmarshal(releaseManifestData, releases); err != nil {
return err
}
for _, r := range releases.Spec.Releases {
bundleName := fmt.Sprintf(eksAnywhereBundlesFileNameFormat, r.Version)
bundleFilePath := filepath.Join(outputPath, bundleName)
log.Printf("Downloading eks-a bundles manifest for eks-a version: %s", r.Version)
if err = downloadFile(bundleFilePath, r.BundleManifestUrl); err != nil {
return err
}
}
return nil
}
// extractTarball extracts the provided tarball onto the path
func extractTarball(tarball, path string) error {
tarFile, err := os.Open(tarball)
if err != nil {
return err
}
defer tarFile.Close()
// Create a new directory to extract the tarball into.
if err = os.RemoveAll(path); err != nil {
return err
}
err = os.MkdirAll(path, 0o755)
if err != nil {
return err
}
// Create a tar reader for the tarball.
tarReader := tar.NewReader(tarFile)
// Iterate over the tarball's entries.
for {
// Get the next header from the tarball.
header, err := tarReader.Next()
if err == io.EOF {
// We've reached the end of the tarball.
break
}
if err != nil {
return err
}
// Create a new file for the tar entry.
outFile, err := os.Create(filepath.Join(path, header.Name))
if err != nil {
return err
}
defer outFile.Close()
// Copy the tar entry's contents to the new file.
_, err = io.Copy(outFile, tarReader)
if err != nil {
return err
}
outFile.Chmod(os.FileMode(header.Mode))
}
return nil
}
func extractAndPrepManifestTarball(tarballFile, privateEksDServerDomain, privateEksAServerDomain string) error {
log.Println("Manifest tarball provided, extracting to directory")
manifestDir, err := getManifestRoot()
if err != nil {
return fmt.Errorf("Error retrieving manifest root")
}
if err = extractTarball(tarballFile, manifestDir); err != nil {
return fmt.Errorf("Error extracting tarball: %v", err)
}
// Replacing eks-a bundles manifest hostname
// These endpoints are used for artifacts like containerd, crictl & etcdadm
// Find all eks-a bundles manifest and replace hostname
files, err := os.ReadDir(manifestDir)
if err != nil {
return err
}
for _, file := range files {
if !file.IsDir() {
// Find EKS-D Manifests and replace prod distro domain with private server's
absFilePath := filepath.Join(manifestDir, file.Name())
eksDManifestFilePattern := strings.ReplaceAll(eksDistroManifestFileNameFormat, "%s", "*")
eksDMatch, err := filepath.Match(eksDManifestFilePattern, file.Name())
if err != nil {
return err
}
if eksDMatch {
log.Printf("Replacing EKS-D domain name in file: %s\n", file.Name())
if err = replaceStringInFile(absFilePath, fmt.Sprintf("https://%s", eksDistroProdDomain), privateEksDServerDomain); err != nil {
return err
}
}
// Find EKS-A Bundles Manifests and replace prod anywhere domain with private server's
eksABundlesManifestFilePattern := strings.ReplaceAll(eksAnywhereBundlesFileNameFormat, "%s", "*")
eksAMatch, err := filepath.Match(eksABundlesManifestFilePattern, file.Name())
if err != nil {
return err
}
fmt.Printf("File: %s, Match: %t, Pattern: %s\n", file.Name(), eksAMatch, eksABundlesManifestFilePattern)
if eksAMatch {
log.Printf("Replacing EKS-A domain name in file: %s\n", file.Name())
if err = replaceStringInFile(absFilePath, fmt.Sprintf("https://%s", eksAnywhereAssetsProdDomain), privateEksAServerDomain); err != nil {
return err
}
}
}
}
return nil
}