Skip to content

🧪 add tests/ infra#51

Open
midays wants to merge 7 commits intokonveyor-ecosystem:mainfrom
midays:add-e2e-test-setup
Open

🧪 add tests/ infra#51
midays wants to merge 7 commits intokonveyor-ecosystem:mainfrom
midays:add-e2e-test-setup

Conversation

@midays
Copy link

@midays midays commented Feb 4, 2026

  • Updated golang.org/x/mod to v0.32.0 and other indirect dependencies.
  • Introduced end-to-end tests for the kubectl migrate export command, including basic export functionality and error handling for invalid namespaces.
  • Added utility functions for managing Kubernetes namespaces and deployments.
  • Created a README for the export command tests outlining test scenarios and prerequisites.

Summary by CodeRabbit

  • Tests

    • Added a comprehensive end-to-end test suite for the export command and supporting test cases
    • Introduced test utilities for cluster management and command execution, plus automated setup routines
  • Documentation

    • Added end-to-end testing framework docs with setup, usage, and best practices
    • Added export command test documentation with scenarios and prerequisites
  • Chores

    • Updated Go module dependencies to newer versions
    • Added YAML-based test configuration template and updated ignore rules

- Updated `golang.org/x/mod` to v0.32.0 and other indirect dependencies.
- Introduced end-to-end tests for the `kubectl migrate export` command, including basic export functionality and error handling for invalid namespaces.
- Added utility functions for managing Kubernetes namespaces and deployments.
- Created a README for the export command tests outlining test scenarios and prerequisites.

Signed-off-by: mohamed idays <midays@redhat.com>
@midays midays changed the title 🧪 : Update dependencies and add end-to-end tests for export command 🧪 Update dependencies and add end-to-end tests for export command Feb 4, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

Adds a Ginkgo/Gomega end-to-end testing framework: new test suites for the export command, test utilities for command execution, cluster management and config loading, test wiring/setup, test documentation, a config template, .gitignore updates, and Go module dependency bumps.

Changes

Cohort / File(s) Summary
Go modules / dependencies
go.mod
Bumped multiple golang.org/x/* modules; added indirect deps including github.com/onsi/ginkgo/v2, github.com/onsi/gomega, github.com/google/pprof, github.com/Masterminds/semver/v3, and github.com/go-task/slim-sprig/v3.
E2E test suites & docs
tests/e2e/export/export_suite_test.go, tests/e2e/export/export_test.go, tests/e2e/export/readme.md
Added Ginkgo-based export command test suite and a README describing test scenarios and prerequisites.
Test utilities: commands & cluster
tests/utils/command.go, tests/utils/cluster.go, tests/utils/helper_functions.go
New command execution helper (CommandResult, RunCommand, RunKubectl) and Cluster abstraction with methods for context-aware kubectl, connectivity checks, namespace creation/deletion, app deploy, and pod queries.
Test config & loader
tests/utils/config.go, tests/config.yaml.template
Added YAML config types and lazy-loading functions (GetConfig, LoadConfig) plus helper to instantiate Cluster from config. Included a config template.
Test wiring / setup
tests/setup.go, tests/readme.md
Global test setup exposing SrcCluster/TgtCluster and SetupClusters(); large README documenting E2E framework, usage, and best practices.
Repository ignores
.gitignore
Restored *.transform/ ignore and added tests/config.yaml to .gitignore.

Sequence Diagram(s)

sequenceDiagram
  participant Ginkgo as Ginkgo Test Runner
  participant Setup as tests.SetupClusters
  participant Config as tests/utils.LoadConfig
  participant ClusterSrc as SrcCluster (kubectl context)
  participant Kubectl as kubectl CLI
  participant KubeAPI as Kubernetes API

  Ginkgo->>Setup: BeforeSuite -> SetupClusters()
  Setup->>Config: load config.yaml
  Config-->>Setup: Config (source/target contexts)
  Setup->>ClusterSrc: NewClusterWithContext(source.name, source.context)
  ClusterSrc->>Kubectl: kubectl --context=<source.context> cluster-info
  Kubectl->>KubeAPI: request cluster-info
  KubeAPI-->>Kubectl: cluster-info response
  Kubectl-->>ClusterSrc: return result
  ClusterSrc-->>Setup: connectivity OK
  Ginkgo->>ClusterSrc: Run test -> CreateNamespace, DeployApp, RunKubectl(...)
  ClusterSrc->>Kubectl: kubectl --context=<source.context> apply/create/get
  Kubectl->>KubeAPI: CRUD operations
  KubeAPI-->>Kubectl: responses
  Kubectl-->>Ginkgo: command results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Suggested reviewers

  • istein1
  • stillalearner
  • RanWurmbrand

Poem

🐰 In burrows of code I nudge and tap,

Clusters wake with a friendly clap,
Namespaces bloom, tests hop along,
Ginkgo hums our migration song,
Hooray — the export passes, snap! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is vague and generic, using a folder name reference and an emoji without clearly conveying the specific changes or objectives of the pull request. Use a more descriptive title that explains the main purpose, such as 'Add end-to-end test infrastructure for export command' or 'Set up Ginkgo-based E2E testing with cluster utilities'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 84.62% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🧹 Recent nitpick comments
tests/utils/cluster.go (1)

30-37: Include richer command error context.

If kubectl writes to stdout or returns a process error, the current message can be empty. Include Stdout/Error for easier debugging.

♻️ Suggested tweak
     result := c.RunKubectl("cluster-info")
     if !result.Success() {
-        return fmt.Errorf("cannot connect to cluster %s (context: %s): %s", 
-            c.Name, c.Context, result.Stderr)
+        msg := result.Stderr
+        if msg == "" {
+            msg = result.Stdout
+        }
+        if result.Error != nil {
+            msg = fmt.Sprintf("%s (err: %v)", msg, result.Error)
+        }
+        return fmt.Errorf("cannot connect to cluster %s (context: %s): %s",
+            c.Name, c.Context, msg)
     }

As per coding guidelines, Pay special attention to error handling and resource cleanup.

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e65739 and dc96af5.

📒 Files selected for processing (4)
  • tests/e2e/export/export_test.go
  • tests/setup.go
  • tests/utils/cluster.go
  • tests/utils/helper_functions.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/e2e/export/export_test.go
  • tests/setup.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*

⚙️ CodeRabbit configuration file

**/*: This is a Kubernetes migration tool. Focus on Kubernetes best practices and Go idioms.
Pay special attention to error handling and resource cleanup.
Ensure all Kubernetes API calls are properly authenticated and authorized.

Files:

  • tests/utils/helper_functions.go
  • tests/utils/cluster.go
🧬 Code graph analysis (2)
tests/utils/helper_functions.go (2)
internal/plugin/plugin_helper.go (1)
  • isPluginInList (106-114)
internal/file/file_helper_test.go (1)
  • Name (66-72)
tests/utils/cluster.go (1)
tests/utils/command.go (2)
  • RunKubectl (48-50)
  • CommandResult (11-16)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test Unit
🔇 Additional comments (6)
tests/utils/cluster.go (6)

7-21: LGTM: Cluster struct and constructor are clear.


23-28: LGTM: context-aware kubectl wrapper is straightforward.


40-48: LGTM: namespace creation handles AlreadyExists.


51-57: LGTM: delete uses --ignore-not-found for idempotency.


60-62: LGTM: pod retrieval via JSON output is suitable for tests.


65-67: LGTM: String() formatting is fine.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@tests/e2e/export/export_test.go`:
- Line 10: Update the incorrect import path in the export_test.go import block:
replace "github.com/konveyor-ecosystem/kubectl-migrate/test/utils" with
"github.com/konveyor-ecosystem/kubectl-migrate/tests/utils" so the test uses the
correct utilities package (adjust the import string in the file containing the
Test export code).

In `@tests/utils/cluster.go`:
- Around line 70-84: Replace the custom string search implementations (functions
contains and findSubstring) with the standard library: remove findSubstring and
either delete contains and replace all calls to contains(s, substr) with
strings.Contains(s, substr) or keep contains as a thin wrapper that returns
strings.Contains(s, substr); also add the "strings" import. Update any call
sites that referenced contains to use strings.Contains (or the new wrapper) so
the code uses the standard, idiomatic implementation.
- Around line 7-23: The CheckKindCluster function accepts clusterName but never
uses it; update CheckKindCluster to inspect the output of
RunCommand("kind","get","clusters") (e.g., result.Output) and verify
strings.Contains(result.Output, clusterName), returning a clear error if the
named cluster is not present, then proceed to RunKubectl("cluster-info") as
before; add the "strings" import and keep existing error handling using
result.Error/result.Stderr and the RunCommand/RunKubectl helpers.
🧹 Nitpick comments (7)
tests/e2e/export/readme.md (1)

22-48: Documentation describes tests that are not yet implemented.

The readme documents three test scenarios (Basic Export, Invalid Namespace, Custom Kubeconfig) and test data (nginx, redis, configmaps), but export_test.go only implements the Basic Export test with a single nginx deployment. Consider either:

  1. Implementing the documented test scenarios, or
  2. Updating the documentation to reflect the current implementation and adding TODO comments for planned tests.

This mismatch could confuse contributors about test coverage.

go.mod (1)

72-73: Ginkgo/Gomega are direct test dependencies but marked as indirect.

These packages are imported directly in tests/e2e_suite_test.go and tests/e2e/export/export_test.go. While the current setup works because go mod tidy handles this based on package location, explicitly listing them as direct dependencies in a separate require block with a // test comment would improve clarity.

This is a minor suggestion for maintainability.

tests/e2e/export/export_test.go (3)

32-35: Static namespace name may cause parallel test conflicts.

Using a hardcoded namespace test-export-ns can cause test failures when multiple test runs execute in parallel on the same cluster. Consider generating a unique namespace name per test run.

♻️ Proposed fix using unique namespace names
+import (
+    "os"
+    "path/filepath"
+    "fmt"
+    "time"
     ...
+)

 BeforeEach(func() {
-    testNamespace = "test-export-ns"
+    testNamespace = fmt.Sprintf("test-export-ns-%d", time.Now().UnixNano())
     appName = "test-nginx"

45-50: Consider waiting for deployment readiness before export.

The test deploys an app and immediately proceeds without waiting for the deployment to become ready. While kubectl migrate export might not require ready pods, it's good practice to ensure resources are fully created. Additionally, the deployment might not export properly if the Kubernetes API hasn't fully reconciled the resources.

♻️ Add deployment readiness wait

Add a wait after deployment in DeployTestApp or here:

// After deploying test app, wait for it to be ready
err = utils.DeployTestApp(testNamespace, appName)
Expect(err).NotTo(HaveOccurred(), "Should deploy test app successfully")

// Wait for deployment to be ready (add this)
result := utils.RunKubectl("wait", "--for=condition=available", 
    "deployment/"+appName, "-n", testNamespace, "--timeout=60s")
Expect(result.Success()).To(BeTrue(), "Deployment should become ready")

59-76: Cleanup failures in AfterEach should not fail the test.

Using Expect in AfterEach can cause misleading test failures when cleanup fails but the actual test passed. Consider logging cleanup errors instead or using Eventually with a timeout for namespace deletion (which can take time).

♻️ More resilient cleanup
 AfterEach(func() {
     GinkgoWriter.Println("Cleaning up...")
     
     // Remove export directory
     if exportDir != "" {
-        err := os.RemoveAll(exportDir)
-        Expect(err).NotTo(HaveOccurred(), "Should remove export directory")
+        if err := os.RemoveAll(exportDir); err != nil {
+            GinkgoWriter.Printf("Warning: failed to remove export directory: %v\n", err)
+        }
         GinkgoWriter.Println("✓ Export directory removed")
     }
     
     // Delete test namespace
     if testNamespace != "" {
-        err := utils.DeleteNamespace(testNamespace)
-        Expect(err).NotTo(HaveOccurred(), "Should delete namespace")
+        if err := utils.DeleteNamespace(testNamespace); err != nil {
+            GinkgoWriter.Printf("Warning: failed to delete namespace: %v\n", err)
+        }
         GinkgoWriter.Printf("✓ Namespace %s deleted\n", testNamespace)
     }
 })
tests/utils/command.go (1)

18-45: Consider adding timeout support for command execution.

Commands can hang indefinitely if the underlying process never completes. For E2E tests, this could cause test suites to hang. Consider adding a context-based timeout option.

♻️ Add timeout support using context
+import (
+    "context"
+    "time"
     ...
+)

+// RunCommandWithTimeout executes a command with a timeout
+func RunCommandWithTimeout(timeout time.Duration, name string, args ...string) CommandResult {
+    ctx, cancel := context.WithTimeout(context.Background(), timeout)
+    defer cancel()
+    
+    cmd := exec.CommandContext(ctx, name, args...)
+    // ... rest of implementation
+}

 // RunCommand executes a shell command and returns the result
 func RunCommand(name string, args ...string) CommandResult {
-    cmd := exec.Command(name, args...)
+    // Default 5 minute timeout for E2E commands
+    return RunCommandWithTimeout(5*time.Minute, name, args...)
+}
tests/utils/cluster.go (1)

48-51: Avoid using latest tag for test images.

Using nginx:latest can lead to non-reproducible tests if the image changes. Pin to a specific version for consistent behavior.

♻️ Use a pinned image version
     result := RunKubectl("create", "deployment", appName,
-        "--image=nginx:latest",
+        "--image=nginx:1.25-alpine",
         "-n", namespace)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c63b230 and 05d76d8.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (6)
  • go.mod
  • tests/e2e/export/export_test.go
  • tests/e2e/export/readme.md
  • tests/e2e_suite_test.go
  • tests/utils/cluster.go
  • tests/utils/command.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*

⚙️ CodeRabbit configuration file

**/*: This is a Kubernetes migration tool. Focus on Kubernetes best practices and Go idioms.
Pay special attention to error handling and resource cleanup.
Ensure all Kubernetes API calls are properly authenticated and authorized.

Files:

  • tests/e2e_suite_test.go
  • tests/e2e/export/readme.md
  • tests/utils/command.go
  • tests/e2e/export/export_test.go
  • tests/utils/cluster.go
  • go.mod
🧬 Code graph analysis (2)
tests/e2e/export/export_test.go (2)
tests/utils/cluster.go (4)
  • CheckKindCluster (8-23)
  • CreateNamespace (26-35)
  • DeployTestApp (47-68)
  • DeleteNamespace (38-44)
tests/utils/command.go (1)
  • RunCommand (19-45)
tests/utils/cluster.go (1)
tests/utils/command.go (2)
  • RunCommand (19-45)
  • RunKubectl (48-50)
🔇 Additional comments (2)
tests/e2e_suite_test.go (1)

1-13: LGTM!

Standard Ginkgo test suite bootstrap following established conventions.

tests/utils/command.go (1)

52-55: LGTM!

The Success() method correctly checks both ExitCode == 0 and Error == nil, handling edge cases where the command might fail to execute entirely.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

- Updated `.gitignore` to include test configuration files.
- Removed obsolete `e2e_suite_test.go` file.
- Added comprehensive `readme.md` for the testing framework, detailing structure, prerequisites, and best practices.
- Introduced `shared.go` for global cluster setup and management.
- Created `export_suite_test.go` and `export_test.go` for export command tests, implementing a structured approach to testing.
- Enhanced utility functions for cluster management and configuration loading.

Signed-off-by: [Your Name] <[Your Email]>
Signed-off-by: mohamed idays <midays@redhat.com>
@midays midays changed the title 🧪 Update dependencies and add end-to-end tests for export command 🧪 add tests/ infra Feb 4, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@tests/readme.md`:
- Around line 15-33: Update the markdown fenced code blocks that show the
directory tree and the sample output to include a language identifier (use
"text") so markdownlint stops flagging them; specifically, change the opening
fences for the directory tree block (the block containing the tests/ tree) and
the sample output block (the CURRENT NAME CLUSTER listing) from ``` to ```text
in tests/readme.md around the snippets used by the README examples.

In `@tests/shared.go`:
- Around line 3-7: The test suite currently treats a missing tests/config.yaml
as a hard failure; update the test setup in tests/shared.go (the BeforeSuite or
init that loads config) to first check for the presence of "tests/config.yaml"
(using os.Stat or os.IsNotExist) and if it is missing call Ginkgo's Skip (Skip
or Skipf) so e2e setup is skipped instead of failing; ensure any opened
resources are only created after the file check so cleanup logic remains
correct.

In `@tests/utils/cluster.go`:
- Around line 77-96: In Cluster.DeployApp, if creating the service fails after a
successful deployment (i.e., the second RunKubectl call in DeployApp fails),
ensure you clean up the previously created deployment by invoking
c.RunKubectl("delete", "deployment", appName, "-n", namespace) (or the cluster's
deletion helper) before returning the error; if the delete itself errors, log or
append that delete error but preserve and return the original service-creation
failure to avoid leaving the deployment behind and to aid debugging.
🧹 Nitpick comments (1)
tests/utils/config.go (1)

86-120: Fail fast on unknown cluster types.

Defaulting to generic on typos can hide misconfiguration and lead to unexpected behavior.

✅ Suggested change
 func (c *Config) CreateSourceCluster() (*Cluster, error) {
-    clusterType := parseClusterType(c.Clusters.Source.Type)
+    clusterType, err := parseClusterType(c.Clusters.Source.Type)
+    if err != nil {
+        return nil, fmt.Errorf("invalid source cluster type: %w", err)
+    }
@@
 func (c *Config) CreateTargetCluster() (*Cluster, error) {
-    clusterType := parseClusterType(c.Clusters.Target.Type)
+    clusterType, err := parseClusterType(c.Clusters.Target.Type)
+    if err != nil {
+        return nil, fmt.Errorf("invalid target cluster type: %w", err)
+    }
@@
-func parseClusterType(typeStr string) ClusterType {
+func parseClusterType(typeStr string) (ClusterType, error) {
     switch typeStr {
     case "kind":
-        return ClusterTypeKind
+        return ClusterTypeKind, nil
     case "minikube":
-        return ClusterTypeMinikube
+        return ClusterTypeMinikube, nil
     case "openshift":
-        return ClusterTypeOpenShift
+        return ClusterTypeOpenShift, nil
+    case "generic":
+        return ClusterTypeGeneric, nil
     default:
-        return ClusterTypeGeneric
+        return "", fmt.Errorf("unknown cluster type %q", typeStr)
     }
 }
As per coding guidelines, Pay special attention to error handling and resource cleanup.

Also applies to: 122-134

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05d76d8 and e33e369.

📒 Files selected for processing (7)
  • .gitignore
  • tests/e2e/export/export_suite_test.go
  • tests/e2e/export/export_test.go
  • tests/readme.md
  • tests/shared.go
  • tests/utils/cluster.go
  • tests/utils/config.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/export/export_test.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*

⚙️ CodeRabbit configuration file

**/*: This is a Kubernetes migration tool. Focus on Kubernetes best practices and Go idioms.
Pay special attention to error handling and resource cleanup.
Ensure all Kubernetes API calls are properly authenticated and authorized.

Files:

  • tests/readme.md
  • tests/shared.go
  • tests/utils/config.go
  • tests/utils/cluster.go
  • tests/e2e/export/export_suite_test.go
🧬 Code graph analysis (4)
tests/shared.go (2)
tests/utils/cluster.go (1)
  • Cluster (18-23)
tests/utils/config.go (1)
  • GetConfig (37-44)
tests/utils/config.go (1)
tests/utils/cluster.go (7)
  • Cluster (18-23)
  • NewClusterWithContext (26-38)
  • ClusterType (8-8)
  • ClusterTypeKind (11-11)
  • ClusterTypeMinikube (12-12)
  • ClusterTypeOpenShift (13-13)
  • ClusterTypeGeneric (14-14)
tests/utils/cluster.go (1)
tests/utils/command.go (2)
  • RunKubectl (48-50)
  • CommandResult (11-16)
tests/e2e/export/export_suite_test.go (1)
tests/shared.go (1)
  • SetupClusters (17-51)
🪛 GitHub Actions: CI
tests/shared.go

[error] 25-25: Failed to load config.yaml: open tests/config.yaml: no such file or directory. (Command: make test-unit)

🪛 markdownlint-cli2 (0.20.0)
tests/readme.md

[warning] 16-16: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 74-74: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (7)
.gitignore (1)

36-43: LGTM for new test artifact ignores.

These patterns keep generated test outputs and configs out of version control.

tests/utils/cluster.go (4)

25-37: Constructor setup is clear.

The OpenShift flag derivation keeps the struct intent explicit.


40-55: Context-scoped kubectl invocation looks good.

Prepending the context and surfacing a clear connectivity error is solid.


57-75: Namespace create/delete flow is straightforward.

Handling “already exists” and using --ignore-not-found keeps operations idempotent for tests.


101-109: Helper methods are concise.

The accessors do what they say without extra complexity.

tests/utils/config.go (1)

36-43: Lazy config load is clear.

The sync.Once gate keeps repeated tests from re-reading the file.

tests/e2e/export/export_suite_test.go (1)

12-20: Suite wiring looks good.

Standard Ginkgo setup and shared cluster initialization are cleanly integrated.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +15 to +33
## Directory Structure
```
tests/
├── config.yaml # Cluster configuration (git-ignored)
├── config.yaml.template # Template for cluster configuration
├── shared.go # Global cluster variables and setup function
├── e2e_suite_test.go # Main test suite (optional)
├── utils/ # Testing utilities
│ ├── cluster.go # Cluster management (Cluster struct)
│ ├── command.go # Command execution utilities
│ └── config.go # Configuration loading
└── e2e/ # End-to-end test suites
├── export/
│ ├── export_suite_test.go # Export test suite setup
│ ├── export_test.go # Export test cases
│ └── README.md # Export test documentation
└── transform/
└── ...
```
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add languages to fenced code blocks.

Markdownlint flags the directory tree and sample output fences as missing a language.

✍️ Suggested fix
-```
+```text
 tests/
 ├── config.yaml              # Cluster configuration (git-ignored)
@@
-```
+```text
 CURRENT   NAME                  CLUSTER
 *         kind-src-cluster      kind-src-cluster
           kind-tgt-cluster      kind-tgt-cluster
-```
+```

Also applies to: 73-78

🧰 Tools
🪛 markdownlint-cli2 (0.20.0)

[warning] 16-16: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In `@tests/readme.md` around lines 15 - 33, Update the markdown fenced code blocks
that show the directory tree and the sample output to include a language
identifier (use "text") so markdownlint stops flagging them; specifically,
change the opening fences for the directory tree block (the block containing the
tests/ tree) and the sample output block (the CURRENT NAME CLUSTER listing) from
``` to ```text in tests/readme.md around the snippets used by the README
examples.

- Introduced a new `config.yaml.template` for easier test configuration setup.
- Updated `readme.md` to remove cluster type references, simplifying the configuration process.
- Refactored cluster creation logic in `utils/config.go` to streamline cluster initialization.
- Removed unnecessary cluster type handling from the `Cluster` struct and related functions.

Signed-off-by: [Your Name] <[Your Email]>
Signed-off-by: mohamed idays <midays@redhat.com>
- Removed the `DeployApp` function from `cluster.go` to streamline cluster management.
- Moved the `contains` helper function to a new file `helper_functions.go` for better organization and reusability.
- Updated the `GetPods` and `String` methods in `cluster.go` to maintain functionality after the refactor.

Signed-off-by: [Your Name] <[Your Email]>
Signed-off-by: mohamed idays <midays@redhat.com>
- Implemented a check in `setup.go` to verify the presence of `config.yaml` before running end-to-end tests.
- If the configuration file is missing, tests will be skipped with a detailed message on how to create the necessary configuration.

Signed-off-by: [Your Name] <[Your Email]>
Signed-off-by: mohamed idays <midays@redhat.com>
- Updated `setup.go` to improve the handling of missing `config.yaml` by providing a more informative skip message.
- Refactored the configuration loading logic to differentiate between file absence and other errors.
- Ensured that the cleanup process in `export_test.go` is correctly executed by uncommenting the namespace deletion.

Signed-off-by: [Your Name] <[Your Email]>
Signed-off-by: mohamed idays <midays@redhat.com>
// RunKubectl runs a kubectl command against this cluster
func (c *Cluster) RunKubectl(args ...string) CommandResult {
// Prepend --context flag to use this cluster
fullArgs := append([]string{"--context", c.Context}, args...)
Copy link
Contributor

Choose a reason for hiding this comment

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

Hi @midays, I have a suggestion :
The --context flag needs to be appended rather than prepended. kubectl plugins don't accept global flags before the plugin name:

kubectl --context kind-src migrate export ...
Error: flags cannot be placed before plugin name: --context

kubectl migrate export ... --context kind-src
→ Works correctly

Fix:
fullArgs := append(args, "--context", c.Context)

Copy link
Contributor

@aufi aufi left a comment

Choose a reason for hiding this comment

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

Thanks for the PR @midays!

I left some comments, mostly for discussion or to make me better understanding objectives of E2E test suite here.

Main points I'd suggest are:

  • Consider Cluster vs. Context naming (theoretically not a significant problem, but better use the same (and descriptive) naming across the project)
  • Consider kubectl cmd golang wrapper vs. k8s client-go (https://github.com/kubernetes/client-go) to setup test env ()
  • Add test setup/cleanup (e.g. automatically create namespace (context), load existing sample resources, tests, deleting namespaces etc.; not sure if config.yaml is needed)
  • Add the test target to Makefile along with https://github.com/konveyor-ecosystem/kubectl-migrate/blob/main/Makefile#L68 to execute E2E test suite
  • Add its exection into upstream CI/github workflow
  • (Not saying everything needs to come with this PR and I appreciate examples in README)

I migh have too developer-ish point of view, please keep me honest if some points don't make sense from QE perspective.


## Test Data

- Sample deployments: nginx, redis
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a question, do these deployments come from sample resources? (not sure about redis, maybe reference to sample resources directly).


// RunKubectl is a convenience wrapper for kubectl commands
func RunKubectl(args ...string) CommandResult {
return RunCommand("kubectl", args...)
Copy link
Contributor

Choose a reason for hiding this comment

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

Files in utils directory look to be a wrapper for kubectl command execution, thinking if it is better than using https://github.com/kubernetes/client-go that allows do the same, but as a lib, not separate command (providing methods like client.CoreV1().Namespaces().Create()).

The CLI wrapper code is probably more readable than the lib, but I'd guess it to be more fragile/less reliable. Anyway, defferring to your QE experience.

type Config struct {
Clusters struct {
Source ClusterConfig `yaml:"source"`
Target ClusterConfig `yaml:"target"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit, IIRC it was more common use Source&Dest (destination). No problem with Target too, just better use consistent naming.

// Cluster represents a Kubernetes cluster with its context and type
type Cluster struct {
Name string
Context string
Copy link
Contributor

Choose a reason for hiding this comment

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

Thinking on Cluster vs. Context. We will most likely migrate resources between contexts (regardless k8s cluster they run on). In kubectl CLI, there is a context name (string), that points to kube config file with more details on the context. It depends if we want store context names or if it is better have Cluster struct around it.


Avoid conflicts by using unique names:
```go
testNs := fmt.Sprintf("test-%d", GinkgoRandomSeed())
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

// CreateCluster creates a Cluster instance from a ClusterConfig
func (c *Config) CreateCluster(clusterConfig ClusterConfig) (*Cluster, error) {

cluster := NewClusterWithContext(
Copy link
Contributor

Choose a reason for hiding this comment

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

target:
name: "tgt_cluster" # Friendly name for the cluster
context: "kind-tgt-cluster" # Context name from 'kubectl config get-contexts'

Copy link
Contributor

Choose a reason for hiding this comment

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

Just thinking if hardcoding a YAML config file is the best way, other parts of code recommend dynamic/unique names creation for namespaces (which looks great to me, mentioned in README), hardcoding it into file looks to add an unnecesarry complexity to me. Please correct me if it is better from QE perspective.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

3 participants