package hetzner import ( "context" "fmt" "os" "strconv" "strings" "time" "git.stinnesbeck.com/go/log" "github.com/hetznercloud/hcloud-go/hcloud" ) func connect() *hcloud.Client { token := os.Getenv("HCLOUD_API_TOKEN") if token == "" { log.PrintError("please specify HCLOUD_API_TOKEN") os.Exit(1) } return hcloud.NewClient(hcloud.WithToken(token)) } func GetNewSuffix(servers []*hcloud.Server) (int, error) { // cop out if there are no servers yet if len(servers) == 0 { return 1, nil } // variable to hold highest number var highestNumber int // loop through all servers for i := range servers { serverNameSlice := strings.Split(servers[i].Name, "-") suffix, err := strconv.Atoi(serverNameSlice[len(serverNameSlice)-1]) if err != nil { return 0, err } // compare our current number agains the highest yet if suffix > highestNumber { highestNumber = suffix } } // return one number higher than highest number return highestNumber + 1, nil } // ListJynxServers lists all servers managed by Jynx hosted on Hetzner Cloud func ListJynxServers(prefix string) ([]*hcloud.Server, error) { // connect to the hcloud API client := connect() // get all servers servers, err := client.Server.All(context.Background()) if err != nil { return nil, err } // create object that holds all servers managed by Jynx var jynxServers []*hcloud.Server // loop through servers and filter out managed servers for _, server := range servers { if strings.HasPrefix(server.Name, prefix) { jynxServers = append(jynxServers, server) } } // return managed servers return jynxServers, nil } func CheckServerDeletions(servers []*hcloud.Server) error { interval := os.Getenv("SCALER_POLL_INTERVAL") if interval == "" { interval = "5" } pollIntervalSeconds, err := strconv.Atoi(interval) if err != nil { return err } if pollIntervalSeconds < 60 { pollIntervalSeconds = 60 } if pollIntervalSeconds > 3600 { pollIntervalSeconds %= 3600 } for _, server := range servers { safeInterval := time.Duration(3600-pollIntervalSeconds) * time.Second optimalDeleteTime := server.Created.Add(safeInterval).Local() log.PrintDebug(server.Name, "optimal delete time:", optimalDeleteTime) if time.Now().Local().Before(optimalDeleteTime) { continue } // optimal delete time has passed, delete the server if err := DeleteServer(server); err != nil { return err } } return nil } func DeleteServer(server *hcloud.Server) error { client := connect() log.PrintInfo("Deleting", server.Name) result, response, err := client.Server.DeleteWithResult(context.Background(), server) if err != nil { return err } log.PrintWarning(result.Action.Status) log.PrintWarning(response.StatusCode) return nil } func CreateServers(servers []string) error { // connect to hcloud API client := connect() // read in some environment variables woodpeckerHost := os.Getenv("WOODPECKER_HOSTNAME") agentSecret := os.Getenv("WOODPECKER_AGENT_SECRET") // loop through each server for _, server := range servers { // create unique AgentCMD for cloud init AgentCMD := fmt.Sprintf("docker run -d -v /var/run/docker.sock:/var/run/docker.sock -e WOODPECKER_GRPC_SECURE=false -e WOODPECKER_SERVER=%s -e WOODPECKER_AGENT_SECRET=%s -e WOODPECKER_MAX_PROCS=%d -e WOODPECKER_HOSTNAME=%s woodpeckerci/woodpecker-agent", woodpeckerHost, agentSecret, 1, server) userdata := fmt.Sprintf("#cloud-config\nruncmd:\n - %s", AgentCMD) labels := make(map[string]string) labels["created_by"] = "jynx" labels["created"] = fmt.Sprintf("%d", time.Now().Unix()) var sshkeys []*hcloud.SSHKey sshkeys, err := getSSHKeys("stefan", "nils") if err != nil { return nil } serverOpts := hcloud.ServerCreateOpts{ Name: server, StartAfterCreate: hcloud.Ptr(true), SSHKeys: sshkeys, Image: &hcloud.Image{Name: "docker-ce"}, ServerType: &hcloud.ServerType{Name: "cax11"}, Location: &hcloud.Location{Name: "fsn1"}, UserData: userdata, PublicNet: &hcloud.ServerCreatePublicNet{EnableIPv4: true}, Labels: labels, } _, _, err = client.Server.Create(context.Background(), serverOpts) if err != nil { return err } } return nil }