Skip to content

Commit

Permalink
Support deletion of projects by names & identifiers (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
puthrayaharness authored Mar 10, 2023
1 parent 3d9a08a commit ad55ad5
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 10 deletions.
13 changes: 13 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,19 @@ The following command creates a corresponding project for every app in the accou
HARNESS_MIGRATOR_AUTH=apiKey harness-upgrade --account ACCOUNT_ID --env ENV --org ORG --secret-scope SCOPE --connector-scope SCOPE --template-scope SCOPE project --export FOLDER_PATH create-bulk
```

### To remove projects
The following command removes projects from a given org in an account. You can provide the names or identifiers of the projects.

To remove projects by name use `--names`
```shell
HARNESS_MIGRATOR_AUTH=apiKey harness-upgrade --account ACCOUNT_ID --env ENV --org ORG project --names name1,name2 rm
```

To remove projects by identifier use `--identifiers`
```shell
HARNESS_MIGRATOR_AUTH=apiKey harness-upgrade --account ACCOUNT_ID --env ENV --org ORG project --identifiers identifier1,identifier2 rm
```

### To get account summary
```shell
HARNESS_MIGRATOR_AUTH=apiKey harness-upgrade --account ACCOUNT_ID --env ENV account-summary
Expand Down
10 changes: 10 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ func Get(reqUrl string, auth string) (respBodyObj ResponseBody, err error) {
return handleResp(req)
}

func Delete(reqUrl string, auth string) (respBodyObj ResponseBody, err error) {
req, err := http.NewRequest("DELETE", reqUrl, nil)
if err != nil {
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set(AuthHeaderKey(auth), auth)
return handleResp(req)
}

func handleResp(req *http.Request) (respBodyObj ResponseBody, err error) {
client := &http.Client{}
resp, err := client.Do(req)
Expand Down
2 changes: 1 addition & 1 deletion expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func getSecretKeyWithScope(key string) string {
func ReplaceCurrentGenExpressionsWithNextGen(*cli.Context) (err error) {
loadYamlFromFile(migrationReq.CustomExpressionsFile)

extensions := strings.Split(migrationReq.FileExtensions, ",")
extensions := Split(migrationReq.FileExtensions, ",")
for i, ext := range extensions {
extensions[i] = "." + ext
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module migrator
module harness-upgrade

go 1.19

Expand Down
11 changes: 11 additions & 0 deletions helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,14 @@ func ToCamelCase(s string) string {
}
return n.String()
}

func Split(str string, sep string) (result []string) {
if len(strings.TrimSpace(str)) == 0 {
return
}
result = strings.Split(str, sep)
for i, s := range result {
result[i] = strings.TrimSpace(s)
}
return
}
19 changes: 19 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ var migrationReq = struct {
FileExtensions string `survey:"fileExtensions"`
CustomExpressionsFile string `survey:"customExpressionsFile"`
ExportFolderPath string `survey:"export"`
Names string `survey:"names"`
Identifiers string `survey:"identifiers"`
All bool `survey:"all"`
AsPipelines bool `survey:"asPipelines"`
}{}
Expand Down Expand Up @@ -334,6 +336,16 @@ func main() {
DefaultText: ".",
Destination: &migrationReq.ExportFolderPath,
},
&cli.StringFlag{
Name: "identifiers",
Usage: "`IDENTIFIERS` of the projects",
Destination: &migrationReq.Identifiers,
},
&cli.StringFlag{
Name: "names",
Usage: "`NAMES` of the projects",
Destination: &migrationReq.Names,
},
},
Subcommands: []*cli.Command{
{
Expand All @@ -350,6 +362,13 @@ func main() {
return cliWrapper(bulkCreateProject, context)
},
},
{
Name: "rm",
Usage: "Remove projects",
Action: func(context *cli.Context) error {
return cliWrapper(bulkRemoveProject, context)
},
},
},
},
},
Expand Down
3 changes: 1 addition & 2 deletions pipelines.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
"strings"
)

func migratePipelines(*cli.Context) error {
Expand Down Expand Up @@ -41,7 +40,7 @@ func migratePipelines(*cli.Context) error {
log.Info("Importing the pipelines....")
var pipelineIds []string
if len(migrationReq.PipelineIds) > 0 {
pipelineIds = strings.Split(migrationReq.PipelineIds, ",")
pipelineIds = Split(migrationReq.PipelineIds, ",")
}
CreateEntities(getReqBody(Pipeline, Filter{
PipelineIds: pipelineIds,
Expand Down
90 changes: 89 additions & 1 deletion projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"gopkg.in/yaml.v3"
"path"
"path/filepath"
"strconv"
)

func createProject(*cli.Context) error {
Expand Down Expand Up @@ -40,7 +41,7 @@ func createProject(*cli.Context) error {

log.Info("Creating the project....")

_, err := Post(url, migrationReq.Auth, ProjectCreateBody{
_, err := Post(url, migrationReq.Auth, ProjectBody{
Project: ProjectDetails{
OrgIdentifier: migrationReq.OrgIdentifier,
Identifier: migrationReq.ProjectIdentifier,
Expand Down Expand Up @@ -144,3 +145,90 @@ func bulkCreateProject(*cli.Context) error {

return nil
}

func bulkRemoveProject(*cli.Context) error {
promptConfirm := PromptDefaultInputs()
promptConfirm = PromptOrgAndProject([]string{Org}) || promptConfirm
names := Split(migrationReq.Names, ",")
identifiers := Split(migrationReq.Identifiers, ",")
if len(names) == 0 && len(identifiers) == 0 {
log.Fatal("No names or identifiers for the projects provided. Aborting")
}
if len(names) > 0 && len(identifiers) > 0 {
log.Fatal("Both names and identifiers for the projects provided. Aborting")
}

n := len(identifiers)
if len(names) > 0 {
n = len(names)
}
if promptConfirm {
confirm := ConfirmInput("Are you sure you want to proceed with deletion of " + strconv.Itoa(n) + " projects?")
if !confirm {
log.Fatal("Aborting...")
}
}

if len(names) > 0 {
projects := getProjects()
for _, name := range names {
id := findProjectIdByName(projects, name)
if len(id) > 0 {
identifiers = append(identifiers, id)
}
}
log.Debugf("Valid identifers for the given names are - %s", identifiers)
}

for _, identifier := range identifiers {
deleteProject(identifier)
}
log.Info("Finished operation for all given projects")
return nil
}

func deleteProject(projectId string) {
url := fmt.Sprintf("%s/api/projects/%s?accountIdentifier=%s&orgIdentifier=%s", urlMap[migrationReq.Environment][NG], projectId, migrationReq.Account, migrationReq.OrgIdentifier)

log.Infof("Deleting the project with identifier %s", projectId)

_, err := Delete(url, migrationReq.Auth)

if err == nil {
log.Infof("Successfully deleted the project - %s", projectId)
} else {
log.Errorf("Failed to delete the project - %s", projectId)
}
}

func getProjects() []ProjectDetails {
url := fmt.Sprintf("%s/api/projects?accountIdentifier=%s&orgIdentifier=%s&pageSize=1000", urlMap[migrationReq.Environment][NG], migrationReq.Account, migrationReq.OrgIdentifier)
resp, err := Get(url, migrationReq.Auth)
if err != nil || resp.Status != "SUCCESS" {
log.Fatal("Failed to fetch projects", err)
}
byteData, err := json.Marshal(resp.Data)
if err != nil {
log.Fatal("Failed to fetch projects", err)
}
var projects ProjectListBody
err = json.Unmarshal(byteData, &projects)
if err != nil {
log.Fatal("Failed to fetch projects", err)
}
var projectDetails []ProjectDetails

for _, p := range projects.Projects {
projectDetails = append(projectDetails, p.Project)
}
return projectDetails
}

func findProjectIdByName(projects []ProjectDetails, projectName string) string {
for _, p := range projects {
if p.Name == projectName {
return p.Identifier
}
}
return ""
}
3 changes: 1 addition & 2 deletions triggers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
"strings"
)

func migrateTriggers(*cli.Context) error {
Expand Down Expand Up @@ -40,7 +39,7 @@ func migrateTriggers(*cli.Context) error {
// Migrating the triggers
var triggerIds []string
if len(migrationReq.TriggerIds) > 0 {
triggerIds = strings.Split(migrationReq.TriggerIds, ",")
triggerIds = Split(migrationReq.TriggerIds, ",")
}
log.Info("Importing the triggers....")
CreateEntities(getReqBody(Trigger, Filter{
Expand Down
6 changes: 5 additions & 1 deletion types.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,14 @@ type BulkCreateBody struct {
Org string `json:"orgIdentifier"`
}

type ProjectCreateBody struct {
type ProjectBody struct {
Project ProjectDetails `json:"project"`
}

type ProjectListBody struct {
Projects []ProjectBody `json:"content"`
}

type RequestBody struct {
DestinationDetails DestinationDetails `json:"destinationDetails"`
EntityType EntityType `json:"entityType"`
Expand Down
3 changes: 1 addition & 2 deletions workflows.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
"strings"
)

func migrateWorkflows(*cli.Context) error {
Expand Down Expand Up @@ -44,7 +43,7 @@ func migrateWorkflows(*cli.Context) error {
// Migrating the workflows
var workflowIds []string
if len(migrationReq.WorkflowIds) > 0 {
workflowIds = strings.Split(migrationReq.WorkflowIds, ",")
workflowIds = Split(migrationReq.WorkflowIds, ",")
}
log.Info("Importing the workflows....")
CreateEntities(getReqBody(Workflow, Filter{
Expand Down

0 comments on commit ad55ad5

Please sign in to comment.