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