diff --git a/build/ci-Dockerfile b/build/ci-Dockerfile index adc94aa445..3bf226e59f 100644 --- a/build/ci-Dockerfile +++ b/build/ci-Dockerfile @@ -5,14 +5,6 @@ WORKDIR /go/src/github.com/openshift/oadp-operator COPY ./ . -# Clone and install oadp-cli -RUN git clone https://github.com/migtools/oadp-cli.git /tmp/oadp-cli && \ - cd /tmp/oadp-cli && \ - make build && \ - cp kubectl-oadp /usr/local/bin/ && \ - chmod +x /usr/local/bin/kubectl-oadp; \ - rm -rf /tmp/oadp-cli - # Install kubectl RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && \ chmod +x kubectl && \ diff --git a/tests/e2e/backup_restore_cli_suite_test.go b/tests/e2e/backup_restore_cli_suite_test.go index b3bfb01f64..1de1187a20 100644 --- a/tests/e2e/backup_restore_cli_suite_test.go +++ b/tests/e2e/backup_restore_cli_suite_test.go @@ -3,7 +3,6 @@ package e2e_test import ( "fmt" "log" - "os/exec" "strings" "time" @@ -196,14 +195,11 @@ var _ = ginkgo.Describe("Backup and restore tests via OADP CLI", ginkgo.Label("c } ginkgo.BeforeAll(func() { - // Verify OADP CLI is available (should be installed in Docker image) - log.Print("Verifying OADP CLI is available...") - cmd := exec.Command("kubectl", "oadp", "version") - output, err := cmd.CombinedOutput() - if err != nil { - ginkgo.Fail(fmt.Sprintf("OADP CLI not available: %v, output: %s", err, string(output))) + + cliSetup := lib.NewOADPCLISetup() + if err := cliSetup.Install(); err != nil { + ginkgo.Fail(fmt.Sprintf("OADP CLI setup failed: %v", err)) } - log.Printf("OADP CLI available. Version: %s", string(output)) }) var _ = ginkgo.AfterEach(func(ctx ginkgo.SpecContext) { diff --git a/tests/e2e/lib/cli_common.go b/tests/e2e/lib/cli_common.go index 0ececbaf7b..eb54aa274f 100644 --- a/tests/e2e/lib/cli_common.go +++ b/tests/e2e/lib/cli_common.go @@ -1,8 +1,11 @@ package lib import ( + "fmt" "log" + "os" "os/exec" + "path/filepath" "strings" ) @@ -56,3 +59,171 @@ func ParsePhaseFromYAML(yamlOutput string) string { } return "" } + +type CLISetup struct { + repoURL string + installArgs []string + namespace string +} + +func NewOADPCLISetup() *CLISetup { + return &CLISetup{ + repoURL: "https://github.com/migtools/oadp-cli.git", + installArgs: []string{"build"}, + namespace: "openshift-adp", + } +} + +func (c *CLISetup) Install() error { + tmpDir, err := c.createTempDir() + if err != nil { + return err + } + defer os.RemoveAll(tmpDir) + + cloneDir := filepath.Join(tmpDir, "oadp-cli") + + steps := []struct { + name string + fn func() error + }{ + {"Cloning repository", func() error { return c.cloneRepo(cloneDir) }}, + {"Building and installing", func() error { return c.buildAndInstall(cloneDir) }}, + {"Verifying installation", func() error { return c.verifyInstallation() }}, + {"Configuring namespace", func() error { return c.configureNamespace() }}, + } + + for _, step := range steps { + log.Printf("OADP CLI Setup: %s...", step.name) + if err := step.fn(); err != nil { + return fmt.Errorf("%s failed: %w", step.name, err) + } + } + + log.Print("OADP CLI setup completed successfully") + return nil +} + +func (c *CLISetup) createTempDir() (string, error) { + tmpDir, err := os.MkdirTemp("", "oadp-cli-*") + if err != nil { + return "", fmt.Errorf("failed to create temp directory: %w", err) + } + return tmpDir, nil +} + +func (c *CLISetup) cloneRepo(cloneDir string) error { + return runCommand("git", []string{"clone", c.repoURL, cloneDir}, "") +} + +func (c *CLISetup) buildAndInstall(cloneDir string) error { + // Build the binary + log.Print("Building OADP CLI...") + if err := runCommand("make", c.installArgs, cloneDir); err != nil { + return fmt.Errorf("build failed: %w", err) + } + + // Verify the binary was created + binaryPath := filepath.Join(cloneDir, "kubectl-oadp") + if _, err := os.Stat(binaryPath); err != nil { + return fmt.Errorf("kubectl-oadp binary not found at %s: %w", binaryPath, err) + } + + // Try multiple target locations, starting with user-writable paths + targetPaths := []string{ + fmt.Sprintf("%s/bin/kubectl-oadp", os.Getenv("HOME")), + "/usr/local/bin/kubectl-oadp", + } + + var targetPath string + var moveErr error + + for _, tp := range targetPaths { + targetPath = tp + log.Printf("Attempting to move binary from %s to %s", binaryPath, targetPath) + + // Create directory if it doesn't exist (for ~/bin) + if targetPath == fmt.Sprintf("%s/bin/kubectl-oadp", os.Getenv("HOME")) { + binDir := filepath.Dir(targetPath) + if err := os.MkdirAll(binDir, 0755); err != nil { + log.Printf("Failed to create directory %s: %v", binDir, err) + continue + } + } + + if err := runCommand("mv", []string{binaryPath, targetPath}, ""); err != nil { + log.Printf("Failed to move to %s: %v", targetPath, err) + moveErr = err + continue + } + + // Success! + moveErr = nil + break + } + + if moveErr != nil { + return fmt.Errorf("failed to move binary to any location: %w", moveErr) + } + + // Make it executable + if err := runCommand("chmod", []string{"+x", targetPath}, ""); err != nil { + return fmt.Errorf("failed to make binary executable: %w", err) + } + + // If we installed to ~/bin, ensure it's in PATH + if targetPath == fmt.Sprintf("%s/bin/kubectl-oadp", os.Getenv("HOME")) { + homeBin := fmt.Sprintf("%s/bin", os.Getenv("HOME")) + currentPath := os.Getenv("PATH") + if !strings.Contains(currentPath, homeBin) { + newPath := fmt.Sprintf("%s:%s", homeBin, currentPath) + os.Setenv("PATH", newPath) + log.Printf("Added %s to PATH", homeBin) + } + } + + log.Printf("Successfully installed kubectl-oadp to %s", targetPath) + return nil +} + +func (c *CLISetup) verifyInstallation() error { + // Check current PATH + cmd := exec.Command("bash", "-c", "echo $PATH") + if output, err := cmd.CombinedOutput(); err == nil { + log.Printf("Current PATH: %s", string(output)) + } + + // Try to find kubectl-oadp binary + cmd = exec.Command("which", "kubectl-oadp") + if output, err := cmd.CombinedOutput(); err == nil { + log.Printf("kubectl-oadp found at: %s", string(output)) + } else { + log.Printf("kubectl-oadp not found in PATH: %v", err) + } + + // List kubectl plugins + cmd = exec.Command("kubectl", "plugin", "list") + if output, err := cmd.CombinedOutput(); err == nil { + log.Printf("Available kubectl plugins: %s", string(output)) + } + + return runCommand("kubectl", []string{"oadp", "version"}, "") +} + +func (c *CLISetup) configureNamespace() error { + return runCommand("kubectl", []string{"oadp", "client", "config", "set", fmt.Sprintf("namespace=%s", c.namespace)}, "") +} + +func runCommand(name string, args []string, dir string) error { + cmd := exec.Command(name, args...) + if dir != "" { + cmd.Dir = dir + } + + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("command '%s %s' failed: %v\nOutput: %s", + name, strings.Join(args, " "), err, string(output)) + } + return nil +}