Created
June 21, 2019 14:28
-
-
Save rverma-nikiai/4b468c9231994caa59e9d7d037295d62 to your computer and use it in GitHub Desktop.
terrafrom upgrade gist
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "context" | |
| "fmt" | |
| "github.com/fako1024/topo" | |
| "github.com/google/go-github/v26/github" | |
| "golang.org/x/oauth2" | |
| "log" | |
| "os" | |
| "os/exec" | |
| "regexp" | |
| "strings" | |
| "time" | |
| ) | |
| var client *github.Client | |
| var ctx = context.Background() | |
| const ( | |
| token = "github-api-token" | |
| sourceOwner = "rverma-nikiai" | |
| prRepoOwner = "cloudposse" | |
| ) | |
| type Repo struct { | |
| name string | |
| url string | |
| owner string | |
| } | |
| var re = regexp.MustCompile(`::([^\[\]]*)\?`) | |
| func getReposInUse() map[string]Repo { | |
| localRepos := make(map[string]Repo) | |
| mods := []string{ | |
| "git::https://github.com/cloudposse/terraform-aws-acm-request-certificate.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-iam-chamber-s3-role.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-cloudfront-cdn.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-cloudfront-s3-cdn.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-cloudtrail-s3-bucket.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-cloudtrail.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-dynamodb-autoscaler.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-dynamodb.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-elasticache-redis.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-elasticsearch.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-iam-account-settings.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-iam-chamber-user.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-iam-role.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-iam-s3-user.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-iam-system-user.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-key-pair.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-kms-key.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-multi-az-subnets.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-rds-cluster.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-route53-alias.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-route53-cluster-hostname.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-route53-cluster-zone.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-s3-bucket.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-s3-log-storage.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-s3-website.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-ses-lambda-forwarder.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-tfstate-backend.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-external-module-artifact.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-null-label.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-terraform-label.git?ref=master", | |
| "git::https://github.com/cloudposse/terraform-aws-iam-policy-document-aggregator.git?ref=master", | |
| } | |
| for _, s := range mods { | |
| repo := getRepo(s, prRepoOwner) | |
| localRepos[repo.name] = repo | |
| } | |
| ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) | |
| tc := oauth2.NewClient(ctx, ts) | |
| client = github.NewClient(tc) | |
| return localRepos | |
| } | |
| func getRepo(element string, owner string) Repo { | |
| moduleUrl := re.FindAllString(element, -1) | |
| repoUrl := strings.Trim(moduleUrl[0], "::") | |
| repoUrl = strings.Trim(repoUrl, "?") | |
| var name = repoUrl[len("https://github.com/"+owner+"/"):] | |
| name = name[:len(name)-4] | |
| return Repo{url: repoUrl, owner: prRepoOwner, name: name} | |
| } | |
| func forkRepoInUse() { | |
| for _, rx := range getReposInUse() { | |
| _, resp2, _ := client.Repositories.Get(ctx, sourceOwner, rx.name) | |
| if resp2.StatusCode >= 300 || resp2.StatusCode < 200 { | |
| fork, resp, _ := client.Repositories.CreateFork(ctx, rx.owner, rx.name, nil) | |
| if resp.StatusCode == 202 { | |
| time.Sleep(100) | |
| log.Printf("forked %s\n", *fork.Name) | |
| } | |
| } else { | |
| log.Printf("repo %s already exists", rx.name) | |
| } | |
| } | |
| } | |
| func syncReposInUse() { | |
| all := getReposInUse() | |
| for _, rx := range all { | |
| target := "/Users/rverma/exp/" + prRepoOwner + "/" + rx.name | |
| if _, err := os.Stat(target); os.IsNotExist(err) { | |
| url := strings.Replace(rx.url, prRepoOwner, sourceOwner, -1) | |
| log.Printf("cloning into %s:%s\n", target, url) | |
| cmd := exec.Command("git", "clone", url, target) | |
| err := cmd.Run() | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| } else { | |
| log.Printf("found locally %s\n", target) | |
| } | |
| } | |
| } | |
| func getOrderOfUpgrade() ([]string){ | |
| localRepos := []string{ | |
| "terraform-aws-acm-request-certificate", | |
| "terraform-aws-cloudfront-cdn", | |
| "terraform-aws-cloudfront-s3-cdn", | |
| "terraform-aws-cloudtrail", | |
| "terraform-aws-cloudtrail-s3-bucket", | |
| "terraform-aws-dynamic-subnets", | |
| "terraform-aws-dynamodb", | |
| "terraform-aws-dynamodb-autoscaler", | |
| "terraform-aws-elasticache-redis", | |
| "terraform-aws-elasticsearch", | |
| "terraform-aws-iam-account-settings", | |
| "terraform-aws-iam-chamber-s3-role", | |
| "terraform-aws-iam-chamber-user", | |
| "terraform-aws-iam-role", | |
| "terraform-aws-iam-s3-user", | |
| "terraform-aws-iam-system-user", | |
| "terraform-aws-key-pair", | |
| "terraform-aws-kms-key", | |
| "terraform-aws-multi-az-subnets", | |
| "terraform-aws-rds-cluster", | |
| "terraform-aws-route53-alias", | |
| "terraform-aws-route53-cluster-hostname", | |
| "terraform-aws-route53-cluster-zone", | |
| "terraform-aws-s3-bucket", | |
| "terraform-aws-s3-log-storage", | |
| "terraform-aws-s3-website", | |
| "terraform-aws-ses-lambda-forwarder", | |
| "terraform-aws-tfstate-backend", | |
| "terraform-aws-vpc", | |
| "terraform-external-module-artifact", | |
| "terraform-null-label", | |
| "terraform-aws-iam-policy-document-aggregator", | |
| } | |
| var stringDependencies []topo.Dependency | |
| for _, rx := range localRepos { | |
| target := "/Users/rverma/exp/" + prRepoOwner + "/" + rx | |
| cmd := exec.Command("bash", "-c", "grep -hr --exclude-dir=examples --include \\*.tf git::https://github.com/rverma . | awk '{ print $3 }'") | |
| cmd.Dir = target | |
| output, err := cmd.CombinedOutput() | |
| if err != nil { | |
| fmt.Println(fmt.Sprint(err) + ": " + string(output)) | |
| panic(err.Error()) | |
| } | |
| out := string(output) | |
| if out != "" { | |
| childrens := strings.Split(out, "\n") | |
| for _, child := range childrens { | |
| if child != "" { | |
| tmp := getRepo(strings.Trim(child, "\""), sourceOwner).name | |
| if rx != "" && tmp != "" && rx != "null" && tmp != "null"{ | |
| stringDependencies = append(stringDependencies, topo.Dependency{Child:rx,Parent:tmp}) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| // Getter function to convert original elements to a generic type | |
| getter := func(i int) topo.Type { | |
| return localRepos[i] | |
| } | |
| // Setter function to restore the original type of the data | |
| setter := func(i int, val topo.Type) { | |
| localRepos[i] = val.(string) | |
| } | |
| // Perform topological sort | |
| if err := topo.Sort(localRepos, stringDependencies, getter, setter); err != nil { | |
| fmt.Printf("Error performing topological sort on slice of strings: %s\n", err) | |
| os.Exit(1) | |
| } | |
| return localRepos | |
| } | |
| func upgrade(){ | |
| localRepos := []string{ | |
| "terraform-aws-acm-request-certificate", | |
| "terraform-null-label", | |
| "terraform-aws-s3-log-storage", | |
| "terraform-aws-route53-alias", | |
| "terraform-aws-cloudfront-cdn", | |
| "terraform-aws-cloudfront-s3-cdn", | |
| "terraform-aws-cloudtrail", | |
| "terraform-aws-cloudtrail-s3-bucket", | |
| "terraform-aws-dynamic-subnets", | |
| "terraform-aws-dynamodb-autoscaler", | |
| "terraform-aws-dynamodb", | |
| "terraform-aws-route53-cluster-hostname", | |
| "terraform-aws-elasticache-redis", | |
| "terraform-aws-elasticsearch", | |
| "terraform-aws-iam-account-settings", | |
| "terraform-aws-iam-system-user", | |
| "terraform-aws-iam-s3-user", | |
| "terraform-aws-s3-bucket", | |
| "terraform-aws-iam-policy-document-aggregator", | |
| "terraform-aws-kms-key", | |
| "terraform-aws-iam-role", | |
| "terraform-aws-iam-chamber-s3-role", | |
| "terraform-aws-iam-chamber-user", | |
| "terraform-aws-key-pair", | |
| "terraform-aws-multi-az-subnets", | |
| "terraform-aws-rds-cluster", | |
| "terraform-aws-route53-cluster-zone", | |
| "terraform-aws-s3-website", | |
| "terraform-external-module-artifact", | |
| "terraform-aws-ses-lambda-forwarder", | |
| "terraform-aws-tfstate-backend", | |
| "terraform-aws-vpc", | |
| } | |
| for _, rx := range localRepos { | |
| target := "/Users/rverma/exp/" + prRepoOwner + "/" + rx | |
| log.Printf("upgrading %s",rx) | |
| cmd := exec.Command("bash", "-c", "if [ -f versions.tf ]; then echo already upgraded; else rm -rf .terraform && terraform init && terraform 0.12upgrade --yes; fi;") | |
| cmd.Dir = target | |
| output, err := cmd.CombinedOutput() | |
| if err != nil { | |
| fmt.Println(fmt.Sprint(err) + ": " + string(output)) | |
| panic(err.Error()) | |
| } | |
| log.Printf(string(output)) | |
| log.Printf("pushing %s",rx) | |
| commit := exec.Command("bash", "-c", "git add -A . && git commit -m \"upgraded-tf\" && git push") | |
| commit.Dir = target | |
| outCommit, err2 := commit.CombinedOutput() | |
| if err != nil { | |
| fmt.Println(fmt.Sprint(err2) + ": " + string(outCommit)) | |
| panic(err.Error()) | |
| } | |
| log.Printf(string(outCommit)) | |
| } | |
| } | |
| func validate(){ | |
| localRepos := []string{ | |
| "terraform-aws-acm-request-certificate", | |
| "terraform-null-label", | |
| "terraform-aws-s3-log-storage", | |
| "terraform-aws-route53-alias", | |
| "terraform-aws-cloudfront-cdn", | |
| "terraform-aws-cloudfront-s3-cdn", | |
| "terraform-aws-cloudtrail", | |
| "terraform-aws-cloudtrail-s3-bucket", | |
| "terraform-aws-dynamic-subnets", | |
| "terraform-aws-dynamodb-autoscaler", | |
| "terraform-aws-dynamodb", | |
| "terraform-aws-route53-cluster-hostname", | |
| "terraform-aws-elasticache-redis", | |
| "terraform-aws-elasticsearch", | |
| "terraform-aws-iam-account-settings", | |
| "terraform-aws-iam-system-user", | |
| "terraform-aws-iam-s3-user", | |
| "terraform-aws-s3-bucket", | |
| "terraform-aws-iam-policy-document-aggregator", | |
| "terraform-aws-kms-key", | |
| "terraform-aws-iam-role", | |
| "terraform-aws-iam-chamber-s3-role", | |
| "terraform-aws-iam-chamber-user", | |
| "terraform-aws-key-pair", | |
| "terraform-aws-multi-az-subnets", | |
| "terraform-aws-rds-cluster", | |
| "terraform-aws-route53-cluster-zone", | |
| "terraform-aws-s3-website", | |
| "terraform-external-module-artifact", | |
| "terraform-aws-ses-lambda-forwarder", | |
| "terraform-aws-tfstate-backend", | |
| "terraform-aws-vpc", | |
| } | |
| for _, rx := range localRepos { | |
| target := "/Users/rverma/exp/" + prRepoOwner + "/" + rx | |
| log.Printf("validating %s",rx) | |
| //cmd := exec.Command("bash", "-c", "rm -rf .terraform && terraform init") | |
| cmd := exec.Command("bash", "-c", "terraform validate") | |
| cmd.Dir = target | |
| cmd.Env = os.Environ() | |
| cmd.Env = append(cmd.Env, "TF_VAR_region=ap-south-1") | |
| output, err := cmd.CombinedOutput() | |
| if err != nil { | |
| fmt.Println(fmt.Sprint(err) + ": " + string(output)) | |
| //panic(err.Error()) | |
| } | |
| log.Printf(string(output)) | |
| } | |
| } | |
| func createPR() { | |
| localRepos := []string{ | |
| //"terraform-null-label", | |
| "terraform-aws-s3-log-storage", | |
| "terraform-aws-route53-alias", | |
| "terraform-aws-cloudfront-cdn", | |
| "terraform-aws-cloudfront-s3-cdn", | |
| "terraform-aws-cloudtrail", | |
| "terraform-aws-cloudtrail-s3-bucket", | |
| "terraform-aws-dynamic-subnets", | |
| "terraform-aws-dynamodb-autoscaler", | |
| "terraform-aws-dynamodb", | |
| "terraform-aws-route53-cluster-hostname", | |
| "terraform-aws-elasticache-redis", | |
| "terraform-aws-elasticsearch", | |
| "terraform-aws-iam-account-settings", | |
| "terraform-aws-iam-system-user", | |
| "terraform-aws-iam-s3-user", | |
| "terraform-aws-s3-bucket", | |
| "terraform-aws-iam-policy-document-aggregator", | |
| "terraform-aws-kms-key", | |
| "terraform-aws-iam-role", | |
| "terraform-aws-iam-chamber-s3-role", | |
| "terraform-aws-iam-chamber-user", | |
| "terraform-aws-key-pair", | |
| "terraform-aws-multi-az-subnets", | |
| "terraform-aws-rds-cluster", | |
| "terraform-aws-route53-cluster-zone", | |
| "terraform-aws-s3-website", | |
| "terraform-external-module-artifact", | |
| "terraform-aws-ses-lambda-forwarder", | |
| "terraform-aws-tfstate-backend", | |
| "terraform-aws-vpc", | |
| } | |
| queue := make(chan string, len(localRepos)) | |
| for _,x := range localRepos { | |
| queue <- x | |
| } | |
| close(queue) | |
| for prRepo := range queue { | |
| target := "/Users/rverma/exp/" + prRepoOwner + "/" + prRepo | |
| ss := exec.Command("bash","-c", "hub pull-request -m \"upgrade 0.12\" -b \"cloudposse:master\" -h \"rverma-nikiai:master\"") | |
| ss.Dir = target | |
| output, err := ss.CombinedOutput() | |
| if err != nil { | |
| fmt.Println(fmt.Sprint(err) + ": " + string(output)) | |
| panic(err.Error()) | |
| } | |
| log.Printf(string(output)) | |
| } | |
| } | |
| func main() { | |
| //forkRepoInUse() | |
| //syncReposInUse() | |
| //fmt.Printf(strings.Join(getOrderOfUpgrade(),"\n")) | |
| //upgrade() | |
| //validate() | |
| createPR() | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment