[WIP] first commit, not done yet
This commit is contained in:
commit
ca9c90cf3c
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# databases
|
||||
*.json
|
9
backend/common/common.go
Normal file
9
backend/common/common.go
Normal file
@ -0,0 +1,9 @@
|
||||
package common
|
||||
|
||||
import "time"
|
||||
|
||||
type Server struct {
|
||||
Name string `json:"name"`
|
||||
Created time.Time `json:"started_at"`
|
||||
Deployed bool `json:"deployed"`
|
||||
}
|
107
backend/hetzner/servers.go
Normal file
107
backend/hetzner/servers.go
Normal file
@ -0,0 +1,107 @@
|
||||
package hetzner
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.stinnesbeck.com/go/jynx/backend/common"
|
||||
"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 DestroyServer(s *hcloud.Server) error {
|
||||
client := connect()
|
||||
serverResponse, response, err := client.Server.DeleteWithResult(context.Background(), s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.PrintInfo(*serverResponse, *response)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ListServers() ([]common.Server, error) {
|
||||
client := connect()
|
||||
servers, err := client.Server.All(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var managedServers []common.Server
|
||||
|
||||
for i := range servers {
|
||||
// only look at servers, that we created
|
||||
if !strings.HasPrefix(servers[i].Name, os.Getenv("HCLOUD_PREFIX")) {
|
||||
continue
|
||||
}
|
||||
|
||||
// append this server to our managed servers
|
||||
managedServers = append(managedServers, common.Server{
|
||||
Name: servers[i].Name,
|
||||
Created: servers[i].Created,
|
||||
Deployed: true,
|
||||
})
|
||||
}
|
||||
|
||||
return managedServers, nil
|
||||
}
|
||||
|
||||
func AddServer(s common.Server) error {
|
||||
client := connect()
|
||||
woodpeckerHost := os.Getenv("WOODPECKER_HOSTNAME")
|
||||
agentSecret := os.Getenv("WOODPECKER_AGENT_SECRET")
|
||||
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", woodpeckerHost, agentSecret, 1, s.Name)
|
||||
|
||||
userdata := fmt.Sprintf("#cloud-config\nruncmd:\n\t- %s", AgentCMD)
|
||||
fmt.Println(userdata)
|
||||
labels := make(map[string]string)
|
||||
labels["created_by"] = "jynx"
|
||||
labels["created"] = fmt.Sprintf("%d", time.Now().Unix())
|
||||
|
||||
// sshkeys, err := client.SSHKey.All(context.Background())
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
var sshkeys []*hcloud.SSHKey
|
||||
|
||||
sshkeys, err := getSSHKeys("stefan", "nils")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
serverOpts := hcloud.ServerCreateOpts{
|
||||
Name: s.Name,
|
||||
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,
|
||||
}
|
||||
os.Exit(0)
|
||||
result, response, err := client.Server.Create(context.Background(), serverOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
io.ReadAll(response.Body)
|
||||
log.PrintInfo(fmt.Sprintf("%+v\n%+v\n", result, response.Response.Body))
|
||||
return nil
|
||||
}
|
38
backend/hetzner/sshKeys.go
Normal file
38
backend/hetzner/sshKeys.go
Normal file
@ -0,0 +1,38 @@
|
||||
package hetzner
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hetznercloud/hcloud-go/hcloud"
|
||||
)
|
||||
|
||||
func getSSHKeys(names ...string) ([]*hcloud.SSHKey, error) {
|
||||
// if no names were provided return nil object
|
||||
if len(names) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// connect to hcloud client
|
||||
client := connect()
|
||||
|
||||
// get all ssh keys from hcloud
|
||||
keys, err := client.SSHKey.All(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// variable to hold found keys
|
||||
var foundKeys []*hcloud.SSHKey
|
||||
|
||||
// check if name is found in keys
|
||||
for i := range keys {
|
||||
for j := range names {
|
||||
if keys[i].Name == names[j] {
|
||||
foundKeys = append(foundKeys, keys[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return found keys
|
||||
return foundKeys, nil
|
||||
}
|
99
ci/woodpecker/woodpecker.go
Normal file
99
ci/woodpecker/woodpecker.go
Normal file
@ -0,0 +1,99 @@
|
||||
package woodpecker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.stinnesbeck.com/go/log"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
Host string `json:"host"`
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
type Stats struct {
|
||||
PendingJobs uint `json:"woodpecker_pending_jobs"`
|
||||
RunningJobs uint `json:"woodpecker_running_jobs"`
|
||||
IdlingWorkers uint `json:"woodpecker_worker_count"`
|
||||
}
|
||||
|
||||
// NewServer returns a Server object for host
|
||||
func NewServer(host string, token string) Server {
|
||||
switch {
|
||||
case strings.HasPrefix(host, "http://"), strings.HasPrefix(host, "https://"):
|
||||
return Server{
|
||||
Host: host,
|
||||
Token: token,
|
||||
}
|
||||
default:
|
||||
log.PrintError("host needs to start with 'http://' or 'https://'")
|
||||
os.Exit(1)
|
||||
return Server{}
|
||||
}
|
||||
}
|
||||
|
||||
func (s Server) GetStats() (*Stats, error) {
|
||||
// prepare request
|
||||
req, err := http.NewRequest(http.MethodGet, s.Host+"/metrics/", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// add authorization header
|
||||
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", s.Token))
|
||||
|
||||
c := http.DefaultClient
|
||||
response, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(b), "\n")
|
||||
|
||||
r := regexp.MustCompile(`^((woodpecker_)(worker_count|pending_jobs|running_jobs)) (\d+)`)
|
||||
|
||||
var stats Stats
|
||||
|
||||
for i := range lines {
|
||||
// skip rest of loop if this line doesn't match regex
|
||||
if !r.MatchString(lines[i]) {
|
||||
continue
|
||||
}
|
||||
|
||||
// line matches regex
|
||||
matches := r.FindStringSubmatch(lines[i])
|
||||
|
||||
// assign stats to struct
|
||||
switch matches[3] {
|
||||
case "pending_jobs":
|
||||
stats.PendingJobs = parseStringToUint(matches[4])
|
||||
case "running_jobs":
|
||||
stats.RunningJobs = parseStringToUint(matches[4])
|
||||
case "worker_count":
|
||||
stats.IdlingWorkers = parseStringToUint(matches[4])
|
||||
}
|
||||
}
|
||||
|
||||
return &stats, nil
|
||||
}
|
||||
|
||||
// parseStringToUint parses a string and returns the resulting uint
|
||||
func parseStringToUint(s string) uint {
|
||||
num, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
log.PrintError("can't parse string to uint,", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return uint(num)
|
||||
}
|
70
db/db.go
Normal file
70
db/db.go
Normal file
@ -0,0 +1,70 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"git.stinnesbeck.com/go/jynx/backend/common"
|
||||
"git.stinnesbeck.com/go/jynx/backend/hetzner"
|
||||
)
|
||||
|
||||
func Read() ([]common.Server, error) {
|
||||
// open file for reading, create it when necessary
|
||||
f, err := os.OpenFile("db.json", os.O_RDONLY|os.O_CREATE, os.ModePerm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
servers, err := hetzner.ListServers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// close file when we are done
|
||||
defer f.Close()
|
||||
|
||||
// read file as byte array
|
||||
b, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(b) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// parse byte array to []common.Server
|
||||
var serversFromDB []common.Server
|
||||
if err := json.Unmarshal(b, &serversFromDB); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// merge servers from db and hcloud
|
||||
servers = append(servers, serversFromDB...)
|
||||
|
||||
// return read in servers
|
||||
return servers, nil
|
||||
}
|
||||
|
||||
func Save(servers []common.Server) error {
|
||||
// open file with provided flags, create it when necessary
|
||||
f, err := os.OpenFile("db.json", os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// close file when we are done
|
||||
defer f.Close()
|
||||
|
||||
// Marshal data as JSON and put into byte array
|
||||
b, err := json.MarshalIndent(servers, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// write byte array to file
|
||||
_, err = f.Write(b)
|
||||
|
||||
return err
|
||||
}
|
26
go.mod
Normal file
26
go.mod
Normal file
@ -0,0 +1,26 @@
|
||||
module git.stinnesbeck.com/go/jynx
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
git.stinnesbeck.com/go/log v0.0.1
|
||||
github.com/hetznercloud/hcloud-go v1.45.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/prometheus/client_golang v1.15.1 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.42.0 // indirect
|
||||
github.com/prometheus/procfs v0.9.0 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/sys v0.7.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
)
|
49
go.sum
Normal file
49
go.sum
Normal file
@ -0,0 +1,49 @@
|
||||
git.stinnesbeck.com/go/log v0.0.1 h1:aH3jTgw6NZiJXxNrxE6XiTF3ymsIg+HIGH4A6PPpIcA=
|
||||
git.stinnesbeck.com/go/log v0.0.1/go.mod h1:9Op2dPZAALo1sHUSaZa/6Gs6YyU1qM/e2RNZg6RXtyE=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/hetznercloud/hcloud-go v1.45.1 h1:nl0OOklFfQT5J6AaNIOhl5Ruh3fhmGmhvZEqHbibVuk=
|
||||
github.com/hetznercloud/hcloud-go v1.45.1/go.mod h1:aAUGxSfSnB8/lVXHNEDxtCT1jykaul8kqjD7f5KQXF8=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI=
|
||||
github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
|
||||
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
||||
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
|
||||
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
|
||||
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
|
||||
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
62
main.go
Normal file
62
main.go
Normal file
@ -0,0 +1,62 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"git.stinnesbeck.com/go/jynx/ci/woodpecker"
|
||||
"git.stinnesbeck.com/go/jynx/scaler"
|
||||
"git.stinnesbeck.com/go/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
checkEnv()
|
||||
|
||||
w := woodpecker.NewServer(
|
||||
"https://woodpecker.fftdf.de",
|
||||
os.Getenv("WOODPECKER_PROMETHEUS_AUTH_TOKEN"),
|
||||
)
|
||||
|
||||
interval := time.Duration(5)
|
||||
if i := os.Getenv("SCALER_POLL_INTERVAL"); i != "" {
|
||||
envInterval, err := strconv.Atoi(i)
|
||||
if err != nil {
|
||||
log.PrintError("can't parse SCALER_POLL_INTERVAL", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// overwrite default interval with the one provided by env variable
|
||||
interval = time.Duration(envInterval)
|
||||
}
|
||||
|
||||
ticker := time.Tick(interval * time.Second)
|
||||
|
||||
// start scaler once
|
||||
if err := scaler.Start(&w); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// start scaler every tick
|
||||
for range ticker {
|
||||
if err := scaler.Start(&w); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkEnv() {
|
||||
switch "" {
|
||||
case os.Getenv("WOODPECKER_HOSTNAME"):
|
||||
log.PrintError("WOODPECKER_HOSTNAME not set")
|
||||
case os.Getenv("WOODPECKER_AGENT_SECRET"):
|
||||
log.PrintError("WOODPECKER_AGENT_SECRET not set")
|
||||
os.Exit(1)
|
||||
case os.Getenv("HCLOUD_PREFIX"):
|
||||
log.PrintError("HCLOUD_PREFIX not set")
|
||||
os.Exit(1)
|
||||
case os.Getenv("WOODPECKER_PROMETHEUS_AUTH_TOKEN"):
|
||||
log.PrintError("WOODPECKER_PROMETHEUS_AUTH_TOKEN not set")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
59
scaler/scaler.go
Normal file
59
scaler/scaler.go
Normal file
@ -0,0 +1,59 @@
|
||||
package scaler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.stinnesbeck.com/go/jynx/backend/common"
|
||||
"git.stinnesbeck.com/go/jynx/backend/hetzner"
|
||||
"git.stinnesbeck.com/go/jynx/ci/woodpecker"
|
||||
"git.stinnesbeck.com/go/jynx/db"
|
||||
"git.stinnesbeck.com/go/log"
|
||||
)
|
||||
|
||||
func Start(w *woodpecker.Server) error {
|
||||
log.PrintDebug("Starting autoscaler")
|
||||
stats, err := w.GetStats()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// read info from database
|
||||
servers, err := db.Read()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var newServers int
|
||||
|
||||
if stats.PendingJobs == 0 || stats.IdlingWorkers+stats.RunningJobs+uint(len(servers)) >= stats.PendingJobs {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.PrintInfo("starting", stats.PendingJobs, "workers")
|
||||
|
||||
newServers += int(stats.PendingJobs)
|
||||
var ScaleUpServers []common.Server
|
||||
|
||||
for i := 0; i < newServers; i++ {
|
||||
name := fmt.Sprintf("jynx-worker-%d", i+1)
|
||||
|
||||
ScaleUpServers = append(ScaleUpServers, common.Server{
|
||||
Name: name,
|
||||
Created: time.Now(),
|
||||
})
|
||||
if err := hetzner.AddServer(ScaleUpServers[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// save servers to database
|
||||
servers = append(servers, ScaleUpServers...)
|
||||
if err := db.Save(servers); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.PrintInfo(stats.RunningJobs, "running jobs,", stats.PendingJobs, "pending jobs,", stats.IdlingWorkers, "idling workers,", len(servers), "servers starting up")
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user