Use runpath for the kubectl binary

This commit is contained in:
Ole Markus With 2022-08-27 07:34:41 +02:00
parent e0ce9111a8
commit c307d3fc7b
2 changed files with 29 additions and 30 deletions

View File

@ -21,20 +21,26 @@ import (
"compress/gzip" "compress/gzip"
"crypto/sha256" "crypto/sha256"
"encoding/hex" "encoding/hex"
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
"path"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
"k8s.io/klog/v2" "k8s.io/klog/v2"
"sigs.k8s.io/kubetest2/pkg/artifacts"
"sigs.k8s.io/kubetest2/pkg/exec" "sigs.k8s.io/kubetest2/pkg/exec"
) )
// AcquireKubectl obtains kubectl and places it in a temporary directory // AcquireKubectl obtains kubectl and places it in rundir
func (t *Tester) AcquireKubectl() (string, error) { // If a kubectl already exists in rundir, it will be reused.
func (t *Tester) AcquireKubectl() error {
if _, err := os.Stat(KubectlPath()); errors.Is(err, os.ErrNotExist) {
klog.Infof("found kubectl in %s. Will reuse it.", KubectlPath())
}
// first, get the name of the latest release (e.g. v1.20.0-alpha.0) // first, get the name of the latest release (e.g. v1.20.0-alpha.0)
if t.TestPackageVersion == "" { if t.TestPackageVersion == "" {
cmd := exec.Command( cmd := exec.Command(
@ -44,10 +50,10 @@ func (t *Tester) AcquireKubectl() (string, error) {
) )
lines, err := exec.OutputLines(cmd) lines, err := exec.OutputLines(cmd)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to get latest release name: %s", err) return fmt.Errorf("failed to get latest release name: %w", err)
} }
if len(lines) == 0 { if len(lines) == 0 {
return "", fmt.Errorf("getting latest release name had no output") return fmt.Errorf("getting latest release name had no output")
} }
t.TestPackageVersion = lines[0] t.TestPackageVersion = lines[0]
@ -58,36 +64,31 @@ func (t *Tester) AcquireKubectl() (string, error) {
downloadDir, err := os.UserCacheDir() downloadDir, err := os.UserCacheDir()
if err != nil { if err != nil {
return "", fmt.Errorf("failed to get user cache directory: %v", err) return fmt.Errorf("failed to get user cache directory: %w", err)
} }
downloadPath := filepath.Join(downloadDir, clientTar) downloadPath := filepath.Join(downloadDir, clientTar)
if err := t.ensureClientTar(downloadPath, clientTar); err != nil { if err := t.ensureClientTar(downloadPath, clientTar); err != nil {
return "", err return err
} }
return t.extractBinaries(downloadPath) return t.extractBinaries(downloadPath)
} }
func (t *Tester) extractBinaries(downloadPath string) (string, error) { func (t *Tester) extractBinaries(downloadPath string) error {
// finally, search for the client package and extract it // finally, search for the client package and extract it
f, err := os.Open(downloadPath) f, err := os.Open(downloadPath)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to open downloaded tar at %s: %s", downloadPath, err) return fmt.Errorf("failed to open downloaded tar at %s: %w", downloadPath, err)
} }
defer f.Close() defer f.Close()
gzf, err := gzip.NewReader(f) gzf, err := gzip.NewReader(f)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to create gzip reader: %s", err) return fmt.Errorf("failed to create gzip reader: %w", err)
} }
tarReader := tar.NewReader(gzf) tarReader := tar.NewReader(gzf)
kubectlDir, err := os.MkdirTemp("", "kubectl")
if err != nil {
return "", err
}
// this is the expected path of the package inside the tar // this is the expected path of the package inside the tar
// it will be extracted to kubectlDir in the loop // it will be extracted to kubectlDir in the loop
kubectlPackagePath := "kubernetes/client/bin/kubectl" kubectlPackagePath := "kubernetes/client/bin/kubectl"
@ -97,28 +98,27 @@ func (t *Tester) extractBinaries(downloadPath string) (string, error) {
break break
} }
if err != nil { if err != nil {
return "", fmt.Errorf("error during tar read: %s", err) return fmt.Errorf("error during tar read: %w", err)
} }
if header.Name == kubectlPackagePath { if header.Name == kubectlPackagePath {
kubectlPath := path.Join(kubectlDir, "kubectl") kubectlPath := KubectlPath()
outFile, err := os.Create(kubectlPath) outFile, err := os.Create(kubectlPath)
if err != nil { if err != nil {
return "", fmt.Errorf("error creating file at %s: %s", kubectlPath, err) return fmt.Errorf("error creating file at %s: %w", kubectlPath, err)
} }
defer outFile.Close() defer outFile.Close()
if err := outFile.Chmod(0o700); err != nil { if err := outFile.Chmod(0o700); err != nil {
return "", fmt.Errorf("failed to make %s executable: %s", kubectlPath, err) return fmt.Errorf("failed to make %s executable: %w", kubectlPath, err)
} }
if _, err := io.Copy(outFile, tarReader); err != nil { if _, err := io.Copy(outFile, tarReader); err != nil {
return "", fmt.Errorf("error reading data from tar with header name %s: %s", header.Name, err) return fmt.Errorf("error reading data from tar with header name %s: %w", header.Name, err)
} }
return kubectlPath, nil return nil
} }
} }
return "", fmt.Errorf("failed to find %s in %s", kubectlPackagePath, downloadPath) return fmt.Errorf("failed to find %s in %s", kubectlPackagePath, downloadPath)
} }
// ensureClientTar checks if the kubernetes client tarball already exists // ensureClientTar checks if the kubernetes client tarball already exists
@ -193,3 +193,7 @@ func sha256sum(path string) (string, error) {
} }
return hex.EncodeToString(h.Sum(nil)), nil return hex.EncodeToString(h.Sum(nil)), nil
} }
func KubectlPath() string {
return artifacts.RunDir() + "/kubectl"
}

View File

@ -21,7 +21,6 @@ import (
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"strings" "strings"
"github.com/octago/sflags/gen/gpflag" "github.com/octago/sflags/gen/gpflag"
@ -42,15 +41,11 @@ type Tester struct {
} }
func (t *Tester) pretestSetup() error { func (t *Tester) pretestSetup() error {
kubectlPath, err := t.AcquireKubectl() err := t.AcquireKubectl()
if err != nil { if err != nil {
return fmt.Errorf("failed to get kubectl package from published releases: %s", err) return fmt.Errorf("failed to get kubectl package from published releases: %s", err)
} }
return nil
existingPath := os.Getenv("PATH")
newPath := fmt.Sprintf("%v:%v", filepath.Dir(kubectlPath), existingPath)
klog.Info("Setting PATH=", newPath)
return os.Setenv("PATH", newPath)
} }
// parseKubeconfig will get the current kubeconfig, and extract the specified field by jsonpath. // parseKubeconfig will get the current kubeconfig, and extract the specified field by jsonpath.