From f74905831414b576881af46d0d962f3b80c51427 Mon Sep 17 00:00:00 2001 From: tithakka Date: Thu, 3 Oct 2024 13:42:37 -0700 Subject: [PATCH 1/6] Add instance addition script --- cmd/ocm-support/add/cmd.go | 18 +++ cmd/ocm-support/add/instances/cmd.go | 208 +++++++++++++++++++++++++++ cmd/ocm-support/root.go | 2 + 3 files changed, 228 insertions(+) create mode 100644 cmd/ocm-support/add/cmd.go create mode 100644 cmd/ocm-support/add/instances/cmd.go diff --git a/cmd/ocm-support/add/cmd.go b/cmd/ocm-support/add/cmd.go new file mode 100644 index 0000000..9e36a13 --- /dev/null +++ b/cmd/ocm-support/add/cmd.go @@ -0,0 +1,18 @@ +package add + +import ( + "github.com/openshift-online/ocm-support-cli/cmd/ocm-support/add/instances" + "github.com/spf13/cobra" +) + +// Cmd ... +var Cmd = &cobra.Command{ + Use: "add [COMMAND]", + Short: "Adds the given resource", + Long: "Adds the given resource", + Args: cobra.MinimumNArgs(1), +} + +func init() { + Cmd.AddCommand(instances.Cmd) +} diff --git a/cmd/ocm-support/add/instances/cmd.go b/cmd/ocm-support/add/instances/cmd.go new file mode 100644 index 0000000..4a60eff --- /dev/null +++ b/cmd/ocm-support/add/instances/cmd.go @@ -0,0 +1,208 @@ +package instances + +import ( + "bytes" + "errors" + "fmt" + "io" + "os" + "os/exec" + + "github.com/spf13/cobra" +) + +var Cmd = &cobra.Command{ + Use: "instances [branch-name] [csv-path]", + Long: "Add new instances in AMS and generates quota rules for them", + RunE: addInstances, + SilenceUsage: true, + Args: cobra.ExactArgs(2), +} + +var args struct { + dryRun bool +} + +func init() { + flags := Cmd.Flags() + flags.BoolVar(&args.dryRun, "dry-run", true, "When true, don't actually take any actions, just print the actions that would be taken") +} + +func addInstances(cmd *cobra.Command, argv []string) error { + branchName := argv[0] + csvPath := argv[1] + if branchName == "" { + return fmt.Errorf("branch name cannot be empty") + } + if csvPath == "" { + return fmt.Errorf("csv path cannot be empty") + } + + fmt.Println("Validating branch name", branchName) + err := CheckRefFormat(branchName) + if err != nil { + return fmt.Errorf("incorrect branch name: %v", err) + } + + fmt.Println("Validating csv path", csvPath) + err = CheckIfFileExists(csvPath) + if err != nil { + return fmt.Errorf("an error occurred while checking if the csv files exists: %v", err) + } + + fmt.Println("Creating temporary directory") + tempDir, err := os.MkdirTemp(os.TempDir(), branchName) + if err != nil { + return fmt.Errorf("an error occurred while creating temporary directory: %v", err) + } + + amsUpstreamRepo := "git@gitlab.cee.redhat.com:service/uhc-account-manager.git" + amsRepo := gitRepo{ + repoUrl: amsUpstreamRepo, + localPath: tempDir, + } + + fmt.Println("Cloning AMS repo at:", tempDir) + err = amsRepo.Clone() + if err != nil { + return fmt.Errorf("an error occurred while cloning AMS repo: %v", err) + } + + fmt.Println("Creating a new branch") + err = amsRepo.Branch(branchName) + if err != nil { + return fmt.Errorf("an error occurred while creating a new branch: %v", err) + } + + fmt.Println("Replacing instances file") + err = ReplaceFileContent(fmt.Sprintf("%s/config/quota-cloud-resources.csv", tempDir), csvPath) + if err != nil { + return fmt.Errorf("an error occurred while getting the head of the reference: %v", err) + } + + fmt.Println("Generating quota rules") + _, err = ExecuteCmd(fmt.Sprintf("cd %s && make generate-quota", tempDir)) + if err != nil { + return fmt.Errorf("an error occurred while generating quota rules: %v", err) + } + + fmt.Println("Staging changes") + err = amsRepo.StageAllFiles() + if err != nil { + return fmt.Errorf("an error occurred while staging the files: %v", err) + } + + fmt.Println("Committing changes") + err = amsRepo.Commit(fmt.Sprintf("Adding instances and quota rules for %s", branchName)) + if err != nil { + return fmt.Errorf("an error occurred committing the changes: %v", err) + } + + fmt.Println("Pushing changes to remote branch") + if args.dryRun { + fmt.Println("DRY RUN: Would push the changes to remote branch:", branchName) + return nil + } + err = amsRepo.Push("origin", branchName) + if err != nil { + return fmt.Errorf("an error occurred while pushing the changes: %v", err) + } + return nil +} + +func ReplaceFileContent(originalFilePath, filePathWithUpdatedText string) error { + originalFile, err := os.OpenFile(originalFilePath, os.O_WRONLY|os.O_TRUNC, 0666) + if err != nil { + return err + } + defer originalFile.Close() + + newFile, err := os.Open(filePathWithUpdatedText) + if err != nil { + return err + } + defer newFile.Close() + _, err = io.Copy(originalFile, newFile) + if err != nil { + return err + } + err = originalFile.Sync() + return err +} + +func CheckIfFileExists(filepath string) error { + if _, err := os.Stat(filepath); errors.Is(err, os.ErrNotExist) { + return err + } + return nil +} + +type gitRepo struct { + repoUrl string + localPath string +} + +func ExecuteCmd(command string) (string, error) { + fmt.Println(command) + app := "bash" + arg1 := "-c" + cmd := exec.Command(app, arg1, command) + var stdBuffer bytes.Buffer + mw := io.MultiWriter(os.Stdout, &stdBuffer) + cmd.Stdout = mw + cmd.Stderr = mw + err := cmd.Run() + if err != nil { + err := fmt.Errorf(fmt.Sprintf("%v : %s", err, stdBuffer.String())) + return "", err + } + return stdBuffer.String(), nil +} + +func CheckRefFormat(branchName string) error { + _, err := ExecuteCmd(fmt.Sprintf("git check-ref-format --branch %s", branchName)) + if err != nil { + return err + } + return nil +} + +func (g gitRepo) Clone() error { + _, err := ExecuteCmd(fmt.Sprintf("git clone %s %s", g.repoUrl, g.localPath)) + return err +} + +func (g gitRepo) RemoteAdd(remoteName, remoteUrl string) error { + _, err := ExecuteCmd(fmt.Sprintf("git -C %s remote add %s %s", g.localPath, remoteName, remoteUrl)) + return err +} + +func (g gitRepo) Branch(branchName string) error { + _, err := ExecuteCmd(fmt.Sprintf("git -C %s checkout -b %s", g.localPath, branchName)) + return err +} + +func (g gitRepo) StageFiles(files *[]string) error { + for _, file := range *files { + _, err := ExecuteCmd(fmt.Sprintf("git -C %s stage %s", g.localPath, file)) + if err != nil { + return err + } + } + return nil +} + +func (g gitRepo) StageAllFiles() error { + _, err := ExecuteCmd(fmt.Sprintf("git -C %s stage .", g.localPath)) + return err +} + +func (g gitRepo) Commit(message string) error { + _, err := ExecuteCmd(fmt.Sprintf("git -C %s commit -m \"%s\"", g.localPath, message)) + return err +} + +func (g gitRepo) Push(remote, remoteUrl string) error { + _, err := ExecuteCmd(fmt.Sprintf("git -C %s push %s %s", g.localPath, remote, remoteUrl)) + return err +} diff --git a/cmd/ocm-support/root.go b/cmd/ocm-support/root.go index 6980f19..a57ff96 100644 --- a/cmd/ocm-support/root.go +++ b/cmd/ocm-support/root.go @@ -17,6 +17,7 @@ limitations under the License. package main import ( + "github.com/openshift-online/ocm-support-cli/cmd/ocm-support/add" "os" "strings" @@ -86,6 +87,7 @@ func init() { rootCmd.AddCommand(get.Cmd) rootCmd.AddCommand(delete.Cmd) rootCmd.AddCommand(patch.Cmd) + rootCmd.AddCommand(add.Cmd) // Set the log level before each command runs. cobra.OnInitialize(initLogLevel) From 375d1d3530fa532e3b14858d3ab148fe9a72e9d5 Mon Sep 17 00:00:00 2001 From: tithakka Date: Thu, 3 Oct 2024 14:07:43 -0700 Subject: [PATCH 2/6] Update golangci lint --- .github/workflows/check-pull-request.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-pull-request.yaml b/.github/workflows/check-pull-request.yaml index 4901e5a..686178b 100644 --- a/.github/workflows/check-pull-request.yaml +++ b/.github/workflows/check-pull-request.yaml @@ -31,7 +31,7 @@ jobs: uses: golangci/golangci-lint-action@v2 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v1.52.2 + version: v1.61.0 # Optional: working directory, useful for monorepos # working-directory: somedir From 74d5a8cc0da037ae3e281c99e589bbaba629057a Mon Sep 17 00:00:00 2001 From: tithakka Date: Fri, 4 Oct 2024 09:30:33 -0700 Subject: [PATCH 3/6] Fix linter --- cmd/ocm-support/add/instances/cmd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/ocm-support/add/instances/cmd.go b/cmd/ocm-support/add/instances/cmd.go index 4a60eff..80840d4 100644 --- a/cmd/ocm-support/add/instances/cmd.go +++ b/cmd/ocm-support/add/instances/cmd.go @@ -153,7 +153,7 @@ func ExecuteCmd(command string) (string, error) { cmd.Stderr = mw err := cmd.Run() if err != nil { - err := fmt.Errorf(fmt.Sprintf("%v : %s", err, stdBuffer.String())) + err := fmt.Errorf("%v : %s", err, stdBuffer.String()) return "", err } return stdBuffer.String(), nil From 49dc289a4b0d5c23456dca7e31164cb6a7d4e509 Mon Sep 17 00:00:00 2001 From: tithakka Date: Fri, 4 Oct 2024 12:27:47 -0700 Subject: [PATCH 4/6] Move command as sync-cloud-resources --- cmd/ocm-support/add/cmd.go | 18 ------------------ cmd/ocm-support/root.go | 4 ++-- .../instances => sync-cloud-resources}/cmd.go | 15 ++++++++------- 3 files changed, 10 insertions(+), 27 deletions(-) delete mode 100644 cmd/ocm-support/add/cmd.go rename cmd/ocm-support/{add/instances => sync-cloud-resources}/cmd.go (90%) diff --git a/cmd/ocm-support/add/cmd.go b/cmd/ocm-support/add/cmd.go deleted file mode 100644 index 9e36a13..0000000 --- a/cmd/ocm-support/add/cmd.go +++ /dev/null @@ -1,18 +0,0 @@ -package add - -import ( - "github.com/openshift-online/ocm-support-cli/cmd/ocm-support/add/instances" - "github.com/spf13/cobra" -) - -// Cmd ... -var Cmd = &cobra.Command{ - Use: "add [COMMAND]", - Short: "Adds the given resource", - Long: "Adds the given resource", - Args: cobra.MinimumNArgs(1), -} - -func init() { - Cmd.AddCommand(instances.Cmd) -} diff --git a/cmd/ocm-support/root.go b/cmd/ocm-support/root.go index a57ff96..6fdfdd5 100644 --- a/cmd/ocm-support/root.go +++ b/cmd/ocm-support/root.go @@ -17,7 +17,6 @@ limitations under the License. package main import ( - "github.com/openshift-online/ocm-support-cli/cmd/ocm-support/add" "os" "strings" @@ -29,6 +28,7 @@ import ( "github.com/openshift-online/ocm-support-cli/cmd/ocm-support/delete" "github.com/openshift-online/ocm-support-cli/cmd/ocm-support/get" "github.com/openshift-online/ocm-support-cli/cmd/ocm-support/patch" + "github.com/openshift-online/ocm-support-cli/cmd/ocm-support/sync-cloud-resources" "github.com/openshift-online/ocm-support-cli/cmd/ocm-support/version" ) @@ -87,7 +87,7 @@ func init() { rootCmd.AddCommand(get.Cmd) rootCmd.AddCommand(delete.Cmd) rootCmd.AddCommand(patch.Cmd) - rootCmd.AddCommand(add.Cmd) + rootCmd.AddCommand(sync_cloud_resources.Cmd) // Set the log level before each command runs. cobra.OnInitialize(initLogLevel) diff --git a/cmd/ocm-support/add/instances/cmd.go b/cmd/ocm-support/sync-cloud-resources/cmd.go similarity index 90% rename from cmd/ocm-support/add/instances/cmd.go rename to cmd/ocm-support/sync-cloud-resources/cmd.go index 80840d4..8e303f1 100644 --- a/cmd/ocm-support/add/instances/cmd.go +++ b/cmd/ocm-support/sync-cloud-resources/cmd.go @@ -1,4 +1,4 @@ -package instances +package sync_cloud_resources import ( "bytes" @@ -12,9 +12,10 @@ import ( ) var Cmd = &cobra.Command{ - Use: "instances [branch-name] [csv-path]", - Long: "Add new instances in AMS and generates quota rules for them", - RunE: addInstances, + Use: "sync-cloud-resources [branch-name] [csv-path]", + Short: "Syncs cloud resources in AMS and generates quota rules for them", + Long: "Syncs cloud resources in AMS and generates quota rules for them", + RunE: syncCloudResources, SilenceUsage: true, Args: cobra.ExactArgs(2), } @@ -28,7 +29,7 @@ func init() { flags.BoolVar(&args.dryRun, "dry-run", true, "When true, don't actually take any actions, just print the actions that would be taken") } -func addInstances(cmd *cobra.Command, argv []string) error { +func syncCloudResources(cmd *cobra.Command, argv []string) error { branchName := argv[0] csvPath := argv[1] if branchName == "" { @@ -74,7 +75,7 @@ func addInstances(cmd *cobra.Command, argv []string) error { return fmt.Errorf("an error occurred while creating a new branch: %v", err) } - fmt.Println("Replacing instances file") + fmt.Println("Replacing cloud resources file") err = ReplaceFileContent(fmt.Sprintf("%s/config/quota-cloud-resources.csv", tempDir), csvPath) if err != nil { return fmt.Errorf("an error occurred while getting the head of the reference: %v", err) @@ -93,7 +94,7 @@ func addInstances(cmd *cobra.Command, argv []string) error { } fmt.Println("Committing changes") - err = amsRepo.Commit(fmt.Sprintf("Adding instances and quota rules for %s", branchName)) + err = amsRepo.Commit(fmt.Sprintf("Syncinc cloud resources and quota rules for %s", branchName)) if err != nil { return fmt.Errorf("an error occurred committing the changes: %v", err) } From 8b7f5e25c9ae6b03cc28df318318bedbad1128b0 Mon Sep 17 00:00:00 2001 From: tithakka Date: Fri, 4 Oct 2024 13:26:08 -0700 Subject: [PATCH 5/6] Fixed typo and improved dry run help message --- cmd/ocm-support/sync-cloud-resources/cmd.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/ocm-support/sync-cloud-resources/cmd.go b/cmd/ocm-support/sync-cloud-resources/cmd.go index 8e303f1..bcd283e 100644 --- a/cmd/ocm-support/sync-cloud-resources/cmd.go +++ b/cmd/ocm-support/sync-cloud-resources/cmd.go @@ -26,7 +26,7 @@ var args struct { func init() { flags := Cmd.Flags() - flags.BoolVar(&args.dryRun, "dry-run", true, "When true, don't actually take any actions, just print the actions that would be taken") + flags.BoolVar(&args.dryRun, "dry-run", true, "If false, it commits the generated cloud resources and quota rule changes to the remote branch at https://gitlab.cee.redhat.com/service/uhc-account-manager") } func syncCloudResources(cmd *cobra.Command, argv []string) error { @@ -94,7 +94,7 @@ func syncCloudResources(cmd *cobra.Command, argv []string) error { } fmt.Println("Committing changes") - err = amsRepo.Commit(fmt.Sprintf("Syncinc cloud resources and quota rules for %s", branchName)) + err = amsRepo.Commit(fmt.Sprintf("Syncing cloud resources and quota rules for %s", branchName)) if err != nil { return fmt.Errorf("an error occurred committing the changes: %v", err) } From 1b583fd1f051c062de655d059b26c2acc58bcd64 Mon Sep 17 00:00:00 2001 From: tithakka Date: Mon, 7 Oct 2024 08:25:23 -0700 Subject: [PATCH 6/6] Removed SilenceUsage to help text when running the command incorrectly --- cmd/ocm-support/sync-cloud-resources/cmd.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cmd/ocm-support/sync-cloud-resources/cmd.go b/cmd/ocm-support/sync-cloud-resources/cmd.go index bcd283e..16da150 100644 --- a/cmd/ocm-support/sync-cloud-resources/cmd.go +++ b/cmd/ocm-support/sync-cloud-resources/cmd.go @@ -12,12 +12,11 @@ import ( ) var Cmd = &cobra.Command{ - Use: "sync-cloud-resources [branch-name] [csv-path]", - Short: "Syncs cloud resources in AMS and generates quota rules for them", - Long: "Syncs cloud resources in AMS and generates quota rules for them", - RunE: syncCloudResources, - SilenceUsage: true, - Args: cobra.ExactArgs(2), + Use: "sync-cloud-resources [branch-name] [csv-path]", + Short: "Syncs cloud resources in AMS and generates quota rules for them", + Long: "Syncs cloud resources in AMS and generates quota rules for them", + RunE: syncCloudResources, + Args: cobra.ExactArgs(2), } var args struct {