Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions build/ci-Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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 && \
Expand Down
12 changes: 4 additions & 8 deletions tests/e2e/backup_restore_cli_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package e2e_test
import (
"fmt"
"log"
"os/exec"
"strings"
"time"

Expand Down Expand Up @@ -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) {
Expand Down
171 changes: 171 additions & 0 deletions tests/e2e/lib/cli_common.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package lib

import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
)

Expand Down Expand Up @@ -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)
}
}
Comment on lines +175 to +183
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the curious this is what fixed CI

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well done @kaovilai and @Joeavaikath :)


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
}