Skip to content

Instantly share code, notes, and snippets.

@maripiyoko
Last active December 9, 2017 05:48
Show Gist options
  • Save maripiyoko/5ac9237cfb70d4d584361a7ced8f3d2d to your computer and use it in GitHub Desktop.
Save maripiyoko/5ac9237cfb70d4d584361a7ced8f3d2d to your computer and use it in GitHub Desktop.
gcp instance up, down, check status by GAE
runtime: go
api_version: go1
handlers:
- url: /.*
script: _go_app
package minecraft
import (
"fmt"
"net/http"
"encoding/json"
"golang.org/x/net/context"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
appengine "google.golang.org/appengine"
compute "google.golang.org/api/compute/v1"
"google.golang.org/appengine/urlfetch"
)
func init() {
http.HandleFunc("/minecraft", handler)
}
type SlackResponse struct {
Response_type string `json:"response_type"`
Text string `json:"text"`
}
func handler(w http.ResponseWriter, r *http.Request) {
project := "YOUR_GCP_PROJECT_NAME"
zone := "YOUR_GCP_ZONE"
instance := "YOUR_GCP_INSTANCE_NAME"
// check token
token := r.PostFormValue("token")
if token != "YOUR_SLACK_TOKEN" {
w.WriteHeader(http.StatusUnauthorized)
writeSlackMessage(w, "NG")
return
}
// check option either status | up | down
option := r.PostFormValue("text")
if option == "status" {
sendExternalIp(w, r, project, zone, instance)
} else if option == "up" {
startInstance(w, r, project, zone, instance)
} else if option == "down" {
stopInstance(w, r, project, zone, instance)
} else {
w.WriteHeader(http.StatusNotAcceptable)
writeSlackMessage(w, "invalid option")
}
}
func sendExternalIp(w http.ResponseWriter, r *http.Request, project string, zone string, instance string) {
ctx := appengine.NewContext(r)
s, err := NewComputeService(ctx, w)
if err != nil {
fmt.Fprint(w, err)
return
}
is := compute.NewInstancesService(s)
insList, err := is.List(project, zone).Do()
if err != nil {
fmt.Fprint(w, err)
return
}
for _, ins := range insList.Items {
name := ins.Name
status := ins.Status
if name == instance {
if status == "RUNNING" {
natIp := ins.NetworkInterfaces[0].AccessConfigs[0].NatIP
if natIp != "" {
message := fmt.Sprintf("Minecraft server is running on : %s:25565", natIp)
writeSlackMessage(w, message)
}
} else {
message := fmt.Sprintf("instance status is %s", status)
writeSlackMessage(w, message)
}
}
}
}
func startInstance(w http.ResponseWriter, r *http.Request, project string, zone string, instance string) {
ctx := appengine.NewContext(r)
s, err := NewComputeService(ctx, w)
if err != nil {
fmt.Fprint(w, err)
return
}
is := compute.NewInstancesService(s)
insList, err := is.List(project, zone).Do()
if err != nil {
fmt.Fprint(w, err)
return
}
for _, ins := range insList.Items {
name := ins.Name
status := ins.Status
if name == instance {
if status == "RUNNING" {
writeSlackMessage(w, "instance is already RUNNING")
} else {
_, err := is.Start(project, zone, instance).Do()
if err != nil {
fmt.Fprint(w, err)
return
}
writeSlackMessage(w, "Instance is starting now... wait for seconds..")
}
}
}
}
func stopInstance(w http.ResponseWriter, r *http.Request, project string, zone string, instance string) {
ctx := appengine.NewContext(r)
s, err := NewComputeService(ctx, w)
if err != nil {
fmt.Fprint(w, err)
return
}
is := compute.NewInstancesService(s)
insList, err := is.List(project, zone).Do()
if err != nil {
fmt.Fprint(w, err)
return
}
for _, ins := range insList.Items {
name := ins.Name
status := ins.Status
if name == instance {
if status != "RUNNING" {
message := fmt.Sprintf("instance status is %s", status)
writeSlackMessage(w, message)
} else {
_, err := is.Stop(project, zone, instance).Do()
if err != nil {
fmt.Fprint(w, err)
return
}
writeSlackMessage(w, "Instance is stopping now...")
}
}
}
}
func writeSlackMessage(w http.ResponseWriter, message string) {
slack_response := SlackResponse{"in_channel", message}
//io.WriteString(w, body)
json, err := json.Marshal(slack_response)
if err != nil {
fmt.Fprint(w, err)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(json)
}
func NewComputeService(ctx context.Context, w http.ResponseWriter) (*compute.Service, error) {
client := &http.Client{
Transport: &oauth2.Transport{
Source: google.AppEngineTokenSource(ctx, compute.ComputeScope),
Base: &urlfetch.Transport{Context: ctx},
},
}
s, err := compute.New(client)
if err != nil {
fmt.Fprint(w, err)
return nil, err
}
return s, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment