Skip to content

Replace the shell script to install the env test binaries by a go model in the tool #1300

Closed
@camilamacedo86

Description

@camilamacedo86

Feature Request

Describe the problem you need a feature to resolve.

Currently, in Kubebuilder where the binaries are used we have :

# Run tests
ENVTEST_ASSETS_DIR=$(shell pwd)/testbin
test: generate fmt vet manifests
	mkdir -p ${ENVTEST_ASSETS_DIR}
	test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/{{ .ControllerRuntimeVersion }}/hack/setup-envtest.sh
	source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./... -coverprofile cover.out

Note that it is NOT intuitive for the users. As I user of Kubebuilder, I'd expected that the tool provides a much more readable, intuitive and understandable code to reduce the learning curve and keep its maintainability such as:

# Run tests
test: generate fmt vet manifests setup 
	go test ./... -coverprofile cover.out

# Setup the envtest setup local envinroment 
setup:
	sigs.k8s.io/controller-tools@versio; go run envtest_setup.go 

However, since was decide that the tool/module should be in the controller-runtime and not Kubebuilder then, it means that the script /hack/setup-envtest.sh would need to be replaced by a go module maybe from its /hack/tools.

Describe the solution you'd like.

Note that here we also might nat to consider address together the requirements described in #1234. However, in order to help who will work on this task, following the module that was done in the PR: kubernetes-sigs/kubebuilder#1711. It is very closer to the code that should be done here.

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"k8s.io/klog"
)

const (
	// defaultKubebuilderPath is the fixed value defined in the controller-runtime to looking for the
	// binaries.
	defaultKubebuilderPath = "/usr/local/kubebuilder/bin" // see that needs to be changed https://github.com/kubernetes-sigs/controller-runtime/issues/1234

	// kubernetesVersion defines the version used to download the binaries
	kubernetesVersion = "1.16.4"
)

func main() {
	klog.Info("Checking EnvTest binaries")
	assetsEnv := os.Getenv("KUBEBUILDER_ASSETS")
	if strings.TrimSpace(assetsEnv) != "" {
		klog.Infof("EnvTest binaries configured via KUBEBUILDER_ASSETS: %s", assetsEnv)
		os.Exit(0)
	}

	binPath := filepath.Join("..", "bin")
	if hasBinaries(binPath) {
		klog.Info("EnvTest binaries found in bin/")
		os.Exit(0)
	}

	klog.Infof("Downloading EnvTest tools")
	envtest_tools_archive_name := getEnvToolsArchiveName()
	envtest_tools_download_url := "https://storage.googleapis.com/kubebuilder-tools/" + envtest_tools_archive_name

	err := downloadFile(envtest_tools_archive_name, envtest_tools_download_url)
	if err != nil {
		klog.Fatalf("unable to download the file (%v) from (%v): %v", envtest_tools_archive_name, envtest_tools_download_url, err)

	}

	if _, err := os.Stat(binPath); os.IsNotExist(err) {
		klog.Infof("Creating bin/ directory")
		err = os.Mkdir(binPath, 0755)
		if err != nil {
			klog.Fatalf("error to create the bin/ directory : %s", err)
		}
	}

	cmd := exec.Command("tar", "-C", binPath, "--strip-components=2", "-zvxf", envtest_tools_archive_name)
	if err := cmd.Run(); err != nil {
		klog.Fatalf("error to untar bin %v: %v", filepath.Join(binPath, envtest_tools_archive_name), err)
	}

	cmd = exec.Command("rm", "-rf", envtest_tools_archive_name)
	if err := cmd.Run(); err != nil {
		klog.Fatal(err)
	}
	klog.Infof("EnvTest binaries are in the directory %v", binPath)
}

// getEnvToolsArchiveName will return the name of the env tools archive based or the arch and so
func getEnvToolsArchiveName() string {
	cmd := exec.Command("go", "env", "GOARCH")
	goarch, err := cmd.CombinedOutput()
	if err != nil {
		klog.Fatal(err)
	}

	cmd = exec.Command("go", "env", "GOOS")
	goos, err := cmd.CombinedOutput()
	if err != nil {
		klog.Fatal(err)
	}
	return fmt.Sprintf("kubebuilder-tools-%s-%s-%s.tar.gz", kubernetesVersion, strings.TrimSpace(string(goos)), strings.TrimSpace(string(goarch)))
}

// hasBinaries will return true when the envtest binaries are found
func hasBinaries(path string) bool {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return false
	}
	if _, err := os.Stat(filepath.Join(path, "etcd")); os.IsNotExist(err) {
		return false
	}
	if _, err := os.Stat(filepath.Join(path, "kube-apiserver")); os.IsNotExist(err) {
		return false
	}
	if _, err := os.Stat(filepath.Join(path, "kubectl")); os.IsNotExist(err) {
		return false
	}
	return true
}

// downloadFile will download a url to a local file.
func downloadFile(filepath string, url string) error {
	// Get the data
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// Create the file
	out, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer out.Close()

	// Write the body to file
	_, err = io.Copy(out, resp.Body)
	return err
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions