Repository navigation
Add clustersim command for manual MCM testing
#1152
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
base: master
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
|
|
@@ -6,7 +6,6 @@ | |
| /test | ||
| /logs | ||
| /hack/tools/bin | ||
| /pkg/simulatedprovider/bin | ||
|
|
||
| *.html | ||
| .vscode | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # Default command output directory | ||
| /gen | ||
| /bin |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,6 @@ KWOK_VERSION ?= v0.8.0 | |
| $(KWOKCTL): $(TOOLS_BIN_DIR) | ||
| GOBIN=$(abspath $(TOOLS_BIN_DIR)) go install sigs.k8s.io/kwok/cmd/{kwok,kwokctl}@$(KWOK_VERSION) | ||
|
|
||
|
|
||
| .PHONY: build | ||
| build: | ||
| @mkdir -p bin | ||
|
|
@@ -47,3 +46,8 @@ stop-simulated-cluster: $(KWOKCTL) | |
| .PHONY: test-integration | ||
| test-integration: | ||
| @(cd test/integration/controller; ginkgo -v --show-node-events --poll-progress-after=300s --poll-progress-interval=60s) | ||
|
|
||
| .PHONY: build-clustersim | ||
| build-clustersim: | ||
| @mkdir -p bin | ||
|
Member
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. a |
||
| go build -v -o bin/clustersim ./cmd/clustersim | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Default command output directory | ||
| /gen | ||
|
|
||
| # Command binary | ||
| clustersim |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| ## Clustersim | ||
|
|
||
|
Member
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. Please add pre-requisites for clustersim tool.
Member
Author
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 is because of old kwok version present on the system: I'll add a note in the README to ensure that the user cleans it up and checks that the version is atleast |
||
| It is a tool that can be used for manual MCM testing, allowing a developer to create an environment where they can deploy custom `MachineClass`es and `MachineDeployment`s in a virtual environment running both the MCM and the simulated provider processes. | ||
|
|
||
| The command line program contains a bunch of helper sub-commands allowing one to set-up the cluster in numerous ways before they actually run any processes. | ||
|
|
||
| ### `help` | ||
|
|
||
| ``` | ||
| ./bin/clustersim -h | ||
| Manages and sets up virtual cluster running simulated Machine Controller Manager. | ||
|
|
||
| Usage: | ||
| clustersim {--clusters name}... command [--dir /tmp] | ||
| clustersim [command] | ||
|
|
||
| Examples: | ||
| clustersim --clusters "test" setup | ||
|
|
||
| Available Commands: | ||
| build Builds the specified components (machine-controller-manager, simulated provider). | ||
| completion Generate the autocompletion script for the specified shell | ||
| copyshoot Fetches MachineDeployments and MachineClasses from specified shoot. | ||
| gencluster Generates MachineClasses and MachineDeployments with the specified parameters. | ||
| help Help about any command | ||
| setup Generates the launch configuration for the cluster components. | ||
| start Creates kwok cluster and starts specified components using their launch config. | ||
| stop Stops specified components using their pid and destroys the kwok cluster. | ||
|
|
||
| Flags: | ||
| --clusters strings comma separated list of cluster(s) to target (required) | ||
| --dir string optional flag to specify the directory for clusters data (default "./gen") | ||
| -h, --help help for clustersim | ||
| ``` | ||
|
|
||
| The main command takes two flags, one optional and one required. | ||
| - The flag to specify clusters' data directory is optional, and if unspecified falls back to `./gen` directory. | ||
| - The flag to list out the cluster names is required by all subcommands except the `build` command. | ||
|
|
||
| ### `build` | ||
|
|
||
| Builds the specified components, fallsback to building both `machine-controller-manager` and the `simulated-provider` if unspecifed. Requires a mandatory flag `source-dir` pointing to the `machine-controller-manager` source root directory. | ||
|
Member
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. It would be nice if
Member
Author
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. The only problem is this depends on the path from where the binary is being invoked, if its from the Do you still think we should have the default? |
||
|
|
||
| ``` | ||
| ./bin/clustersim build -h | ||
| Builds the specified components (machine-controller-manager, simulated provider). | ||
|
|
||
| Usage: | ||
| clustersim build {--source-dir ..} [--components mcm]... | ||
|
|
||
| Examples: | ||
| clustersim build --source-dir ../../../../ --components "mcm,mc" | ||
|
Member
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. It is not possible to build the ca tried Error: passed invalid component "ca", supported ones are [mcm mc]
Member
Author
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 had mentioned in the proposal that I didn't wish to add CA support for now. Wanted to keep the current task's scope restricted to just adding IT support and basic manual testing. This can be handled later unless you feel strongly that it should also be done now. (I'd also mentioned skipping copyshoot and gendata for current implementation but since it was somewhat necessary for testing with gardener data, I added those subcommands) |
||
|
|
||
| Flags: | ||
| -c, --components strings comma separated list of components to build (default [mcm,mc]) | ||
|
Member
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 suggest making a command |
||
| -h, --help help for build | ||
| --source-dir string machine-controller-manager source root directory path (required) | ||
| ``` | ||
|
|
||
| ### `setup` | ||
|
|
||
| Generates the launch configuration for the cluster components. **Requires** the `mcc.yaml` and the `mcd.yaml` files to already be present in the specified clusters' directories. These can be manually fetched by targeting a cluster or be constructed via the `gencluster` subcommand. | ||
|
|
||
| The launch configuration consists of the path for the components binaries and their corresponding launch flags. | ||
|
|
||
| ### `copyshoot` | ||
|
|
||
| Rather than manually fetching the data for a cluster for `setup`, `clustersim` also provides a gardener shoot specific `copyshoot` subcommand which can fetch the `MachineClass`es and `MachineDeployment`s of a live cluster in an automated fashion provided the user has the required permission to access the specified shoot's data. | ||
|
|
||
| It can also fetch the launch flags for the components from the actual cluster as well, and sanitizes the flags for the virtual cluster's usage. | ||
|
|
||
| ``` | ||
| ./bin/clustersim copyshoot -h | ||
| Fetches MachineDeployments and MachineClasses from specified shoot. | ||
|
|
||
| Usage: | ||
| clustersim copyshoot {--clusters name} {-l landscape} {-p project} {-s shoot} [-f true|false] | ||
|
|
||
| Flags: | ||
| -f, --fetch-config fetch component configuration from cluster (default true) | ||
| -h, --help help for copyshoot | ||
| -l, --landscape string gardener landscape name (required) | ||
| -p, --project string gardener project name (required) | ||
| -s, --shoot string gardener shoot name (required) | ||
| ``` | ||
|
|
||
| ### `gencluster` | ||
|
|
||
| In case a developer needs to quickly generate some dummy data for testing, a `gencluster` helper command is provided, which takes specified `zones` and `instances` and constructs MCCs and MCDs for their cross-product. Additionally it generates the required launch configuration as well. | ||
|
|
||
| ``` | ||
| ./bin/clustersim gencluster -h | ||
| Generates MachineClasses and MachineDeployments with the specified parameters. | ||
|
|
||
| Usage: | ||
| clustersim gencluster {--clusters name} {--zones zone}... {--instances inst}... | ||
|
Member
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 suggest supporting multiple |
||
|
|
||
| Flags: | ||
| -h, --help help for gencluster | ||
| -i, --instances strings comma separated list of instances to use (required) | ||
| -z, --zones strings comma separated list of zones to use (required) | ||
| ``` | ||
|
|
||
| It utilizes the templates present in [./templates](./templates) in order to construct the required mcc and mcd. And uses the data present in [./templates/instances.json](./templates/instances.json) to get the required `arch` and the `capacity` for the specified instances. | ||
|
|
||
| ### `start` | ||
|
|
||
| This runs the actual virtual cluster and deploys the MCC and MCD belonging to the clusters, it also creates two files per component that it runs (mcm, machine-controller): | ||
| - `<process>.pid`: denoting the PID for the component, used by the `stop` command to kill the process for the specified cluster. | ||
| - `<process>.log`: consisting of the components' log file. | ||
|
|
||
| ### `stop` | ||
|
|
||
| Kills the specified clusters' specified components and destroys the virtual cluster. | ||
|
|
||
| ``` | ||
| ./bin/clustersim stop -h | ||
| Stops specified components using their pid and destroys the kwok cluster. | ||
|
|
||
| Usage: | ||
| clustersim stop {--clusters name}... [--components mcm]... [--killall true|false] | ||
|
|
||
| Examples: | ||
| clustersim --clusters "test" stop | ||
|
|
||
| Flags: | ||
| -c, --components strings comma separated list of components to stop (default [mcm,mc]) | ||
| -h, --help help for stop | ||
| --killall stop all components and destroy all clusters (default true) | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "context" | ||
| "fmt" | ||
| "os" | ||
| "os/exec" | ||
| "path/filepath" | ||
| "slices" | ||
|
|
||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
||
| type BuildFlags struct { | ||
| SourceDir string | ||
| Components []string | ||
| } | ||
|
|
||
| var buildFlags BuildFlags | ||
|
|
||
| const ( | ||
| mcmCmdFile = "cmd/machine-controller-manager/controller_manager.go" | ||
| providerCmdFile = "cmd/machine-controller/main.go" | ||
| ) | ||
|
|
||
| var buildCmd = &cobra.Command{ | ||
| Use: "build {--source-dir ..} [--components mcm]...", | ||
| Short: "Builds the specified components (machine-controller-manager, simulated provider).", | ||
| Example: `clustersim build --source-dir ../../../../ --components "mcm,mc"`, | ||
| DisableFlagsInUseLine: true, | ||
| PreRunE: func(cmd *cobra.Command, _ []string) error { | ||
| if buildFlags.SourceDir == "" { | ||
| return fmt.Errorf("required flag --source-dir not passed") | ||
| } | ||
|
|
||
| if err := validateComponents(buildFlags.Components); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| binDir := filepath.Join(getClustersDir(cmd), "bin") | ||
| return os.MkdirAll(binDir, 0750) | ||
| }, | ||
| RunE: func(cmd *cobra.Command, _ []string) error { | ||
| cmd.SilenceUsage = true | ||
|
|
||
| ctx := cmd.Context() | ||
| binDir := filepath.Join(getClustersDir(cmd), "bin") | ||
|
|
||
| if slices.Contains(buildFlags.Components, componentMCM) { | ||
| outputPath := filepath.Join(binDir, binaryNameMCM) | ||
| err := goBuild(ctx, buildFlags.SourceDir, mcmCmdFile, outputPath) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } | ||
|
|
||
| if slices.Contains(buildFlags.Components, componentMC) { | ||
| providerPkgPath, err := getProviderRoot(buildFlags.SourceDir) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| outputPath := filepath.Join(binDir, binaryNameMC) | ||
| err = goBuild(ctx, providerPkgPath, providerCmdFile, outputPath) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } | ||
| return nil | ||
| }, | ||
| } | ||
|
|
||
| func init() { | ||
| buildCmd.PersistentFlags().StringSliceVarP( | ||
| &buildFlags.Components, "components", "c", allComponents, | ||
| "comma separated list of components to build", | ||
| ) | ||
| buildCmd.PersistentFlags().StringVar( | ||
| &buildFlags.SourceDir, "source-dir", "", | ||
| "machine-controller-manager source root directory path (required)", | ||
| ) | ||
| } | ||
|
|
||
| // goBuild invokes `go build -C dir -o binPath -v -buildvcs=true file` | ||
| func goBuild(ctx context.Context, dir, file, binPath string) error { | ||
| binPathAbs, err := filepath.Abs(binPath) | ||
| if err != nil { | ||
| return fmt.Errorf("cannot get absolute path for path %q: %w", binPath, err) | ||
| } | ||
|
|
||
| fmt.Printf("Building %q\n", binPath) | ||
| cmd := exec.CommandContext( | ||
| ctx, "go", "build", "-C", dir, "-o", binPathAbs, "-v", "-buildvcs=true", file, | ||
| ) | ||
| var stdout, stderr bytes.Buffer | ||
| cmd.Stdout = &stdout | ||
| cmd.Stderr = &stderr | ||
|
|
||
| err = cmd.Run() | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| if finfo, err := os.Stat(binPath); err != nil && finfo.IsDir() { | ||
|
Member
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. error here: if |
||
| return fmt.Errorf("did not find binary installed at expected path %q", binPath) | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func getProviderRoot(sourceDir string) (string, error) { | ||
| return filepath.Abs(filepath.Join(sourceDir, "pkg", "simulatedprovider")) | ||
| } | ||
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.
Can we please also duplicate this target (only this target in top level MCM
Makefile)