-
Notifications
You must be signed in to change notification settings - Fork 116
Deploy flags e2e #2755
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
Deploy flags e2e #2755
Changes from 11 commits
afbba82
6a6fb04
7a7ec4f
f22428f
e491435
0c7e5df
f8f9225
b2f2222
a741643
47f4a46
12c704f
438fe47
abdc06a
23bb74c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,7 @@ import ( | |
|
|
||
| const ( | ||
| subnetEVMMainnetChainID = 11 | ||
| poaValidatorManagerOwner = "0x2e6FcBb9d4E17eC4cF67eddfa7D32eabC4cdCFc6" | ||
| PoaValidatorManagerOwner = "0x2e6FcBb9d4E17eC4cF67eddfa7D32eabC4cdCFc6" | ||
| bootstrapFilepathFlag = "--bootstrap-filepath" | ||
| avalancheGoPath = "--avalanchego-path" | ||
| localNodeClusterName = "testLocalNode" | ||
|
|
@@ -35,12 +35,12 @@ func CreateSubnetEvmConfigNonSOV(subnetName string, genesisPath string) (string, | |
| return mapping[utils.LatestEVM2AvagoKey], mapping[utils.LatestAvago2EVMKey] | ||
| } | ||
|
|
||
| func CreateSubnetEvmConfigSOV(subnetName string, genesisPath string) (string, string) { | ||
| func CreateSubnetEvmConfigSOVWithGenesisPath(subnetName string, genesisPath string, validatorManagerOwner string) (string, string) { | ||
| mapper := utils.NewVersionMapper() | ||
| mapping, err := utils.GetVersionMapping(mapper) | ||
| gomega.Expect(err).Should(gomega.BeNil()) | ||
| // let's use a SubnetEVM version which has a guaranteed compatible avago | ||
| CreateSubnetEvmConfigWithVersionSOV(subnetName, genesisPath, mapping[utils.LatestEVM2AvagoKey]) | ||
| CreateSubnetEvmConfigGenesisPathWithVersionSOV(subnetName, genesisPath, mapping[utils.LatestEVM2AvagoKey], validatorManagerOwner) | ||
| return mapping[utils.LatestEVM2AvagoKey], mapping[utils.LatestAvago2EVMKey] | ||
| } | ||
|
|
||
|
|
@@ -85,7 +85,7 @@ func CreateSubnetEvmConfigWithVersionNonSOV(subnetName string, genesisPath strin | |
| gomega.Expect(exists).Should(gomega.BeTrue()) | ||
| } | ||
|
|
||
| func CreateSubnetEvmConfigWithVersionSOV(subnetName string, genesisPath string, version string) { | ||
| func CreateSubnetEvmConfigGenesisPathWithVersionSOV(subnetName string, genesisPath string, version string, validatorManagerOwner string) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we need a generic function that just take the command name, the non flag args, and a map for flags, and |
||
| // Check config does not already exist | ||
| exists, err := utils.SubnetConfigExists(subnetName) | ||
| gomega.Expect(err).Should(gomega.BeNil()) | ||
|
|
@@ -101,9 +101,9 @@ func CreateSubnetEvmConfigWithVersionSOV(subnetName string, genesisPath string, | |
| subnetName, | ||
| "--proof-of-authority", | ||
| "--validator-manager-owner", | ||
| poaValidatorManagerOwner, | ||
| validatorManagerOwner, | ||
| "--proxy-contract-owner", | ||
| poaValidatorManagerOwner, | ||
| validatorManagerOwner, | ||
| "--" + constants.SkipUpdateFlag, | ||
| "--icm=false", | ||
| "--evm-token", | ||
|
|
@@ -217,7 +217,7 @@ func CreateCustomVMConfigNonSOV(subnetName string, genesisPath string, vmPath st | |
| gomega.Expect(exists).Should(gomega.BeTrue()) | ||
| } | ||
|
|
||
| func CreateCustomVMConfigSOV(subnetName string, genesisPath string, vmPath string) { | ||
| func CreateCustomVMConfigSOV(subnetName string, genesisPath string, vmPath string, validatorManagerOwner string) { | ||
| // Check config does not already exist | ||
| exists, err := utils.SubnetConfigExists(subnetName) | ||
| gomega.Expect(err).Should(gomega.BeNil()) | ||
|
|
@@ -236,9 +236,9 @@ func CreateCustomVMConfigSOV(subnetName string, genesisPath string, vmPath strin | |
| genesisPath, | ||
| "--proof-of-authority", | ||
| "--validator-manager-owner", | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we also need to stop using flag constants here, and take those from cmd/flags |
||
| poaValidatorManagerOwner, | ||
| validatorManagerOwner, | ||
| "--proxy-contract-owner", | ||
| poaValidatorManagerOwner, | ||
| validatorManagerOwner, | ||
| "--custom", | ||
| subnetName, | ||
| "--custom-vm-path", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this cmd tree. probably this can have a default name, like test_table.json |
||
| "globalFlags": { | ||
| "local": true, | ||
| "skip-icm-deploy": true, | ||
| "skip-update-check": true | ||
| }, | ||
| "happyPath": [ | ||
| { | ||
| "name": "local_deploy", | ||
| "flags": {} | ||
| } | ||
| ], | ||
| "notHappyPath": [ | ||
| { | ||
| "name": "invalid_version", | ||
| "flags": { | ||
| "avalanchego-version": "invalid_version" | ||
| }, | ||
| "expectedError": "invalid version string" | ||
| } | ||
| ] | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| // Copyright (C) 2024, Ava Labs, Inc. All rights reserved. | ||
| // See the file LICENSE for licensing terms. | ||
|
|
||
| package deploy | ||
|
|
||
| import ( | ||
| "fmt" | ||
|
|
||
| "github.com/ava-labs/avalanche-cli/tests/e2e/commandse2e" | ||
|
|
||
| "github.com/ava-labs/avalanche-cli/tests/e2e/commands" | ||
| ginkgo "github.com/onsi/ginkgo/v2" | ||
| "github.com/onsi/gomega" | ||
| ) | ||
|
|
||
| const ( | ||
| deployTestJSONPath = "tests/e2e/commandse2e/blockchain/deploy/deploy_tests.json" | ||
| subnetName = "testSubnet" | ||
| ) | ||
|
|
||
| var ( | ||
| config *commandse2e.TestJSONConfig | ||
| err error | ||
| ) | ||
|
|
||
| const ewoqEVMAddress = "0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC" | ||
|
|
||
| var _ = ginkgo.Describe("[Blockchain Deploy Flags]", ginkgo.Ordered, func() { | ||
| _ = ginkgo.BeforeEach(func() { | ||
| // Create test subnet config | ||
| commands.CreateSubnetEvmConfigSOV(subnetName, ewoqEVMAddress, commands.PoA) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe this should be added to the json spec (how to setup required env) |
||
|
|
||
| // Read test configuration | ||
| config, err = commandse2e.ReadTestConfig(deployTestJSONPath) | ||
| gomega.Expect(err).Should(gomega.BeNil()) | ||
| }) | ||
|
|
||
| ginkgo.AfterEach(func() { | ||
| commands.CleanNetwork() | ||
| // Cleanup test subnet config | ||
| commands.DeleteSubnetConfig(subnetName) | ||
| }) | ||
| blockchainCmdArgs := []string{subnetName} | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should belong to the json test case IMO |
||
| ginkgo.It("should successfully deploy a blockchain", func() { | ||
| // Run each happy path test case | ||
| for _, testCase := range config.HappyPath { | ||
| ginkgo.By(fmt.Sprintf("Running test case: %s", testCase.Name)) | ||
| _, err = commandse2e.TestCommandWithJSONConfig( | ||
| commandse2e.BlockchainCmd, | ||
| "deploy", | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should be a constant on cmd/blockchaincmd/ |
||
| blockchainCmdArgs, | ||
| deployTestJSONPath, | ||
| &testCase, | ||
| ) | ||
| gomega.Expect(err).Should(gomega.BeNil()) | ||
| } | ||
| }) | ||
|
|
||
| ginkgo.It("should handle error cases", func() { | ||
| // Run each not happy path test case | ||
| for _, testCase := range config.NotHappyPath { | ||
| ginkgo.By(fmt.Sprintf("Running test case: %s", testCase.Name)) | ||
| _, err = commandse2e.TestCommandWithJSONConfig( | ||
| commandse2e.BlockchainCmd, | ||
| "deploy", | ||
| blockchainCmdArgs, | ||
| deployTestJSONPath, | ||
| &testCase, | ||
| ) | ||
| gomega.Expect(err).Should(gomega.HaveOccurred()) | ||
| } | ||
| }) | ||
| }) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| // Copyright (C) 2022, Ava Labs, Inc. All rights reserved. | ||
| // See the file LICENSE for licensing terms. | ||
| package commandse2e | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "errors" | ||
| "fmt" | ||
| "os" | ||
| "os/exec" | ||
|
|
||
| "github.com/ava-labs/avalanche-cli/tests/e2e/utils" | ||
| ) | ||
|
|
||
| // TestCase represents a single test case configuration | ||
| type TestCase struct { | ||
| Name string `json:"name"` | ||
| Flags map[string]string `json:"flags"` | ||
|
||
| ExpectedError string `json:"expectedError,omitempty"` | ||
|
||
| } | ||
|
|
||
| // TestJSONConfig represents the json configuration that contains cli command flag inputs | ||
| type TestJSONConfig struct { | ||
| GlobalFlags map[string]interface{} `json:"globalFlags"` | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CommonFlags? |
||
| HappyPath []TestCase `json:"happyPath"` | ||
| NotHappyPath []TestCase `json:"notHappyPath"` | ||
| } | ||
|
|
||
| // CommandGroup represents the different command groups available in the CLI | ||
| type CommandGroup string | ||
|
|
||
| const ( | ||
| BlockchainCmd CommandGroup = "blockchain" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would rather add this constant on cmd/blockchaincmd/ and import that here |
||
| ) | ||
|
|
||
| var avalancheBinaryPath = "./bin/avalanche" | ||
|
|
||
| // TestCommandWithJSONConfig tests a CLI command with flag inputs from a JSON file | ||
| func TestCommandWithJSONConfig(commandGroup CommandGroup, command string, args []string, configPath string, testCase *TestCase) (string, error) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice this is generic
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this should not take configPath as string and testCase as TestCase, it should either receive |
||
| // Build command arguments | ||
| cmdArgs := []string{string(commandGroup), command} | ||
|
|
||
| // Read and parse the JSON config file | ||
| configData, err := os.ReadFile(configPath) | ||
| if err != nil { | ||
| return "", fmt.Errorf("failed to read config file: %w", err) | ||
| } | ||
|
|
||
| var config TestJSONConfig | ||
| if err := json.Unmarshal(configData, &config); err != nil { | ||
| return "", fmt.Errorf("failed to parse config file: %w", err) | ||
| } | ||
|
|
||
| // Append any additional arguments | ||
| if len(args) > 0 { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should belong to the test case |
||
| cmdArgs = append(cmdArgs, args...) | ||
| } | ||
|
|
||
| // Create a map to store all flags, starting with global flags | ||
| allFlags := make(map[string]interface{}) | ||
| for flag, value := range config.GlobalFlags { | ||
| allFlags[flag] = value | ||
| } | ||
|
|
||
| // Override with test case specific flags if provided | ||
| if testCase != nil { | ||
| for flag, value := range testCase.Flags { | ||
| allFlags[flag] = value | ||
| } | ||
| } | ||
|
|
||
| // Add all flags to command arguments | ||
| for flag, value := range allFlags { | ||
| cmdArgs = append(cmdArgs, "--"+flag+"="+fmt.Sprintf("%v", value)) | ||
| } | ||
|
|
||
| // Execute the command | ||
| cmd := exec.Command(avalancheBinaryPath, cmdArgs...) | ||
| fmt.Println(cmd) | ||
| output, err := cmd.CombinedOutput() | ||
| if err != nil { | ||
| var ( | ||
| exitErr *exec.ExitError | ||
| stderr string | ||
| ) | ||
| if errors.As(err, &exitErr) { | ||
| stderr = string(exitErr.Stderr) | ||
| } | ||
| fmt.Println(string(output)) | ||
| utils.PrintStdErr(err) | ||
| fmt.Println(stderr) | ||
| return "", err | ||
| } | ||
|
|
||
| return string(output), nil | ||
| } | ||
|
|
||
| // ReadTestConfig reads and parses the test configuration from a JSON file | ||
| func ReadTestConfig(configPath string) (*TestJSONConfig, error) { | ||
| configData, err := os.ReadFile(configPath) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to read config file: %w", err) | ||
| } | ||
|
|
||
| var config TestJSONConfig | ||
| if err := json.Unmarshal(configData, &config); err != nil { | ||
| return nil, fmt.Errorf("failed to parse config file: %w", err) | ||
| } | ||
|
|
||
| return &config, nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure we want to start modifying CI at this stage