Last active
June 7, 2017 12:09
-
-
Save dstpierre/467651d7218475cf6523e2d445059783 to your computer and use it in GitHub Desktop.
Spinning a new DigitalOcean droplet, running a bash file that copy a Go binary and execute this binary on the new droplet and destroy the droplet via Go code
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" | |
| "io/ioutil" | |
| "log" | |
| "os" | |
| "os/exec" | |
| "path/filepath" | |
| "strconv" | |
| "strings" | |
| "time" | |
| "github.com/digitalocean/godo" | |
| "golang.org/x/oauth2" | |
| ) | |
| // TokenSource passes the personal access token from DO | |
| type TokenSource struct { | |
| AccessToken string | |
| } | |
| // Token returns the DO pat token | |
| func (t *TokenSource) Token() (*oauth2.Token, error) { | |
| token := &oauth2.Token{ | |
| AccessToken: t.AccessToken, | |
| } | |
| return token, nil | |
| } | |
| // start starts the engagement calculation process of: | |
| // 1. Creating a new droplet | |
| // 2. Deploying the app to the new machine | |
| // 3. Starts the process | |
| // 4. Destroy the machine | |
| func start() error { | |
| pat := os.Getenv("DO_KEY") | |
| tokenSource := &TokenSource{ | |
| AccessToken: pat, | |
| } | |
| oauthClient := oauth2.NewClient(context.Background(), tokenSource) | |
| client := godo.NewClient(oauthClient) | |
| dropletName := "ops1.roadmap.space" | |
| createRequest := &godo.DropletCreateRequest{ | |
| Name: dropletName, | |
| Region: "tor1", | |
| Size: "16gb", | |
| Image: godo.DropletCreateImage{ | |
| Slug: "ubuntu-16-04-x64", | |
| }, | |
| PrivateNetworking: true, | |
| SSHKeys: []godo.DropletCreateSSHKey{godo.DropletCreateSSHKey{Fingerprint: os.Getenv("DO_FP")}}, | |
| } | |
| ctx := context.TODO() | |
| // 1. Create the new droplet | |
| log.Println("1.", "creating new droplet") | |
| newDroplet, _, err := client.Droplets.Create(ctx, createRequest) | |
| if err != nil { | |
| return err | |
| } | |
| id := fmt.Sprintf("%d", newDroplet.ID) | |
| log.Println(" -> creating id file", id) | |
| err = ioutil.WriteFile(fmt.Sprintf("%s.todelete", id), []byte(id), 0666) | |
| if err != nil { | |
| return err | |
| } | |
| // let's wait for the droplet to get created | |
| time.Sleep((1 * time.Minute) + (30 * time.Second)) | |
| log.Println(" -> getting created droplet") | |
| ip := "" | |
| for c := 0; c < 3; c++ { | |
| dl, _, err := client.Droplets.Get(ctx, newDroplet.ID) | |
| if err != nil { | |
| return err | |
| } else if dl == nil { | |
| return err | |
| } | |
| tmp, err := dl.PrivateIPv4() | |
| if err != nil { | |
| return err | |
| } else if len(tmp) != 0 { | |
| log.Println(" -> private ip address is", tmp) | |
| ip = tmp | |
| break | |
| } | |
| time.Sleep(35 * time.Second) | |
| } | |
| // 2. deploy to new droplet and running the task | |
| log.Println("2.", "deploying app") | |
| out, err := exec.Command("/bin/bash", "./process.sh", ip).Output() | |
| if err != nil { | |
| return err | |
| } | |
| log.Println(" -> writing output of process exec") | |
| if err := ioutil.WriteFile(fmt.Sprintf("prc-%s.log", time.Now().Format("02")), out, 0666); err != nil { | |
| return err | |
| } | |
| log.Println("4.", "cleaning up") | |
| if err := end(); err != nil { | |
| return err | |
| } | |
| return nil | |
| } | |
| func end() error { | |
| log.Println(" -> opening current directory") | |
| d, err := os.Open("./") | |
| if err != nil { | |
| return err | |
| } | |
| defer d.Close() | |
| log.Println(" -> reading files") | |
| files, err := d.Readdir(-1) | |
| if err != nil { | |
| return err | |
| } | |
| for _, file := range files { | |
| if file.Mode().IsRegular() { | |
| if filepath.Ext(file.Name()) == ".todelete" { | |
| log.Println(" -> extracting droplet id") | |
| id, err := extractID(file.Name()) | |
| if err != nil { | |
| return err | |
| } | |
| log.Println(" -> destroying id", id) | |
| if err := destroy(id); err != nil { | |
| return err | |
| } | |
| log.Println(" -> removing todelete file", file.Name()) | |
| if err := os.Remove(file.Name()); err != nil { | |
| return err | |
| } | |
| } | |
| } | |
| } | |
| return nil | |
| } | |
| func extractID(s string) (int, error) { | |
| return strconv.Atoi(strings.Replace(s, ".todelete", "", -1)) | |
| } | |
| func destroy(id int) error { | |
| pat := os.Getenv("DO_KEY") | |
| tokenSource := &TokenSource{ | |
| AccessToken: pat, | |
| } | |
| oauthClient := oauth2.NewClient(context.Background(), tokenSource) | |
| client := godo.NewClient(oauthClient) | |
| if _, err := client.Droplets.Delete(context.TODO(), id); err != nil { | |
| return err | |
| } | |
| return nil | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment