// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The scaleway command creates ARM servers on Scaleway.com.
package main

import (
	"bytes"
	"crypto/hmac"
	"crypto/md5"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"time"

	"go4.org/types"
	revtype "golang.org/x/build/types"
)

var (
	tokenDir    = flag.String("token-dir", filepath.Join(os.Getenv("HOME"), "keys"), "directory to read gobuilder-staging.key, gobuilder-master.key and go-scaleway.token from.")
	token       = flag.String("token", "", "API token. If empty, the file is read from $(token-dir)/go-scaleway.token. Googlers on the Go team can get the value from http://go/golang-scaleway-token")
	org         = flag.String("org", "1f34701d-668b-441b-bf08-0b13544e99de", "Organization ID (default is bradfitz@golang.org's account)")
	image       = flag.String("image", "13f4c905-3a4b-475a-aaba-a13168e2b6c7", "Disk image ID; default is the snapshot we made last")
	bootscript  = flag.String("bootscript", "5c8e4527-d166-4844-b6c6-087d7a6f5fb0", "Bootscript ID; empty means to use the default for the image. But our images don't have a correct default.")
	num         = flag.Int("n", 0, "Number of servers to create; if zero, defaults to a value as a function of --staging")
	tags        = flag.String("tags", "", "Comma-separated list of tags. The build key tags should be of the form 'buildkey_linux-arm_HEXHEXHEXHEXHEX'. If empty, it's automatic.")
	staging     = flag.Bool("staging", false, "If true, deploy staging instances (with staging names and tags) instead of prod.")
	listAll     = flag.Bool("list-all", false, "If true, list all (prod, staging, other) current Scaleway servers and stop without making changes.")
	list        = flag.Bool("list", false, "If true, list all prod (or staging, if -staging) servers, including missing ones.")
	fixInterval = flag.Duration("fix-interval", 10*time.Minute, "Interval to wait before running again (only applies to daemon mode)")
	daemonMode  = flag.Bool("daemon", false, "Run in daemon mode in a loop")
	ipv6        = flag.Bool("ipv6", false, "enable IPv6 on scaleway instances")
)

const (
	// ctype is the Commercial Type of server we use for the builders.
	ctype = "C1"

	scalewayAPIBase = "https://api.scaleway.com"
)

func main() {
	flag.Parse()
	if *tags == "" && !*listAll { // Tags aren't needed if -list-all flag is set.
		if *staging {
			*tags = defaultBuilderTags("gobuilder-staging.key")
		} else {
			*tags = defaultBuilderTags("gobuilder-master.key")
		}
	}
	if *num == 0 {
		if *staging {
			*num = 5
		} else {
			*num = 50
		}
	}
	if *token == "" {
		file := filepath.Join(*tokenDir, "go-scaleway.token")
		slurp, err := ioutil.ReadFile(file)
		if err != nil {
			if os.IsNotExist(err) {
				log.Fatalf("No --token flag specified and token file %s does not exist. Googlers on the Go team can get it via http://go/golang-scaleway-token", file)
			}
			log.Fatalf("No --token specified and error reading backup token file: %v", err)
		}
		*token = strings.TrimSpace(string(slurp))
	}

	// Loop over checkServers() in daemon mode.
	if *daemonMode {
		log.Printf("scaleway instance checker daemon running.")
	}
	for {
		checkServers()
		if !*daemonMode {
			return
		}
		time.Sleep(*fixInterval)
	}
}

func checkServers() {
	timer := time.AfterFunc(5*time.Minute, func() { panic("Timeout running checkServers.") })
	defer timer.Stop()

	cl := &Client{Token: *token}
	serverList, err := cl.Servers()
	if err != nil {
		log.Fatal(err)
	}
	var names []string
	servers := map[string]*Server{}
	for _, s := range serverList {
		servers[s.Name] = s
		names = append(names, s.Name)
	}
	sort.Strings(names)
	if *listAll {
		for _, name := range names {
			s := servers[name]
			fmt.Printf("%s: %v, id=%v, state=%s, created=%v, modified=%v, image=%v\n",
				name, s.PublicIP, s.ID, s.State, s.CreationDate, s.ModificationDate, s.Image)
		}
		return
	}
	for i := 1; i <= *num; i++ {
		name := serverName(i)
		if _, ok := servers[name]; !ok {
			servers[name] = &Server{Name: name}
			names = append(names, name)
		}
	}
	sort.Strings(names)

	for name, revBuilder := range getConnectedMachines() {
		if _, ok := servers[name]; !ok {
			log.Printf("Machine connected to farmer.golang.org is unknown to scaleway: %v; ignoring", name)
			continue
		}
		servers[name].Connected = revBuilder
	}

	if *list {
		for _, name := range names {
			s := servers[name]
			status := "NOT_CONNECTED"
			if s.Connected != nil {
				status = "ok"
			}
			fmt.Printf("%s: %s, %v, id=%v, state=%s, created=%v, modified=%v, image=%v\n",
				name, status, s.PublicIP, s.ID, s.State, s.CreationDate, s.ModificationDate, s.Image)
		}
	}

	for i := 1; i <= *num; i++ {
		name := serverName(i)
		server := servers[name]

		if server.Image != nil && server.Image.ID != *image {
			log.Printf("server %s, state %q, running wrong image %s (want %s)", name, server.State, server.Image.ID, *image)
			switch server.State {
			case "running":
				log.Printf("powering off %s ...", name)
				if err := cl.PowerOff(server.ID); err != nil {
					log.Printf("PowerOff(%q (%q)): %v", server.ID, name, err)
				}
			case "stopped":
				log.Printf("deleting %s ...", name)
				if err := cl.Delete(server.ID); err != nil {
					log.Printf("Delete(%q (%q)): %v", server.ID, name, err)
				}
			}
		}

		if server.Connected != nil {
			continue
		}

		if server.State == "running" {
			if time.Time(server.ModificationDate).Before(time.Now().Add(15 * time.Minute)) {
				log.Printf("rebooting old running-but-disconnected %q server...", name)
				err := cl.serverAction(server.ID, "reboot")
				log.Printf("reboot(%q): %v", name, err)
				continue
			}
			// Started recently. Maybe still booting.
			continue
		}
		if server.State != "" {
			log.Printf("server %q in state %q; not creating", name, server.State)
			continue
		}
		tags := strings.Split(*tags, ",")
		if *staging {
			tags = append(tags, "staging")
		}
		body, err := json.Marshal(createServerRequest{
			Org:            *org,
			Name:           name,
			Image:          *image,
			CommercialType: ctype,
			Tags:           tags,
			EnableIPV6:     *ipv6,
			BootType:       "bootscript", // the "local" boot mode doesn't work on C1,
			Bootscript:     *bootscript,
		})
		if err != nil {
			log.Fatal(err)
		}
		log.Printf("sending createServerRequest: %s", body)
		// TODO: update to their new API path format that includes the zone.
		req, err := http.NewRequest("POST", scalewayAPIBase+"/servers", bytes.NewReader(body))
		if err != nil {
			log.Fatal(err)
		}
		req.Header.Set("Content-Type", "application/json")
		req.Header.Set("X-Auth-Token", *token)
		res, err := http.DefaultClient.Do(req)
		if err != nil {
			log.Fatal(err)
		}
		if res.StatusCode == http.StatusOK {
			log.Printf("created %v", i)
		} else {
			slurp, _ := ioutil.ReadAll(io.LimitReader(res.Body, 4<<10))
			log.Printf("creating number %v, %s: %s", i, res.Status, slurp)
		}
		res.Body.Close()
	}

	serverList, err = cl.Servers()
	if err != nil {
		log.Fatal(err)
	}
	for _, s := range serverList {
		if strings.HasSuffix(s.Name, "-prep") || strings.HasSuffix(s.Name, "-hand") {
			continue
		}
		if s.State == "stopped" {
			log.Printf("Powering on %s (%s) = %v", s.Name, s.ID, cl.PowerOn(s.ID))
		}
	}
}

type createServerRequest struct {
	Org            string   `json:"organization"`
	Name           string   `json:"name"`
	Image          string   `json:"image"`
	CommercialType string   `json:"commercial_type"`
	Tags           []string `json:"tags"`
	EnableIPV6     bool     `json:"enable_ipv6,omitempty"`
	BootType       string   `json:"boot_type,omitempty"` // local, bootscript, rescue; the default of local doesn't work on C1 machines
	Bootscript     string   `json:"bootscript,omitempty"`
}

type Client struct {
	Token string
}

// Delete deletes a server. It needs to be powered off in "stopped" state first.
//
// This is currently unused. An earlier version of this tool used it briefly before
// changing to use the reboot action. We might want this later.
func (c *Client) Delete(serverID string) error {
	req, _ := http.NewRequest("DELETE", scalewayAPIBase+"/instance/v1/zones/fr-par-1/servers/"+serverID, nil)
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-Auth-Token", c.Token)
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusNoContent {
		slurp, _ := ioutil.ReadAll(io.LimitReader(res.Body, 1<<10))
		return fmt.Errorf("error deleting %s: %v, %s", serverID, res.Status, slurp)
	}
	return nil
}

func (c *Client) PowerOn(serverID string) error {
	return c.serverAction(serverID, "poweron")
}

func (c *Client) PowerOff(serverID string) error {
	return c.serverAction(serverID, "poweroff")
}

func (c *Client) serverAction(serverID, action string) error {
	req, _ := http.NewRequest("POST", scalewayAPIBase+"/servers/"+serverID+"/action", strings.NewReader(fmt.Sprintf(`{"action":"%s"}`, action)))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-Auth-Token", c.Token)
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if res.StatusCode/100 != 2 {
		return fmt.Errorf("error doing %q on %s: %v", action, serverID, res.Status)
	}
	return nil
}

func (c *Client) Servers() ([]*Server, error) {
	req, _ := http.NewRequest("GET", scalewayAPIBase+"/servers?per_page=100", nil)
	req.Header.Set("X-Auth-Token", c.Token)
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to get Server list: %v", res.Status)
	}
	if n, _ := strconv.Atoi(res.Header.Get("X-Total-Count")); n > 100 {
		// TODO: Get all pages, not just first one. See https://developer.scaleway.com/#header-pagination.
		return nil, fmt.Errorf("results (%d) don't fit in one page (100) and pagination isn't implemented", n)
	}
	var jres struct {
		Servers []*Server `json:"servers"`
	}
	err = json.NewDecoder(res.Body).Decode(&jres)
	return jres.Servers, err
}

type Server struct {
	ID               string         `json:"id"`
	Name             string         `json:"name"`
	PublicIP         *IP            `json:"public_ip"`
	PrivateIP        string         `json:"private_ip"`
	Tags             []string       `json:"tags"`
	State            string         `json:"state"`
	Image            *Image         `json:"image"`
	CreationDate     types.Time3339 `json:"creation_date"`
	ModificationDate types.Time3339 `json:"modification_date"`

	// Connected is non-nil if the server is connected to farmer.golang.org.
	// This does not come from the Scaleway API.
	Connected *revtype.ReverseBuilder `json:"-"`
}

type Image struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

func (im *Image) String() string {
	if im == nil {
		return "<no Image>"
	}
	return im.ID
}

type IP struct {
	ID      string `json:"id"`
	Address string `json:"address"`
}

func (ip *IP) String() string {
	if ip == nil {
		return "<no IP>"
	}
	return ip.Address
}

// defaultBuilderTags returns the default value of the "tags" flag.
// It returns a comma-separated list of builder tags (each of the form buildkey_$(BUILDER)_$(SECRETHEX)).
func defaultBuilderTags(baseKeyFile string) string {
	keyFile := filepath.Join(*tokenDir, baseKeyFile)
	slurp, err := ioutil.ReadFile(keyFile)
	if err != nil {
		log.Fatal(err)
	}
	var tags []string
	for _, builder := range []string{
		"host-linux-arm-scaleway",
	} {
		h := hmac.New(md5.New, bytes.TrimSpace(slurp))
		h.Write([]byte(builder))
		tags = append(tags, fmt.Sprintf("buildkey_%s_%x", builder, h.Sum(nil)))
	}
	return strings.Join(tags, ",")
}

func serverName(i int) string {
	if *staging {
		return fmt.Sprintf("scaleway-staging-%02d", i)
	}
	return fmt.Sprintf("scaleway-prod-%02d", i)
}

func getConnectedMachines() map[string]*revtype.ReverseBuilder {
	const reverseURL = "https://farmer.golang.org/status/reverse.json"
	res, err := http.Get(reverseURL)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		log.Fatalf("getting %s: %s", reverseURL, res.Status)
	}
	var jres revtype.ReverseBuilderStatus
	if err := json.NewDecoder(res.Body).Decode(&jres); err != nil {
		log.Fatalf("reading %s: %v", reverseURL, err)
	}
	st := jres.HostTypes["host-linux-arm-scaleway"]
	if st == nil {
		return nil
	}
	return st.Machines
}
