diff --git a/cmd/woodpecker-autoscaler/main.go b/cmd/woodpecker-autoscaler/main.go index 5a6e2b3..bd0e0fd 100644 --- a/cmd/woodpecker-autoscaler/main.go +++ b/cmd/woodpecker-autoscaler/main.go @@ -100,6 +100,11 @@ func main() { zerolog.SetGlobalLevel(lvl) } + // if debug or trace also log the caller + if zerolog.GlobalLevel() <= zerolog.DebugLevel { + log.Logger = log.With().Caller().Logger() + } + return nil }, Action: run, diff --git a/engine/stringmaps.go b/engine/stringmaps.go index 755d4c8..7b9b53e 100644 --- a/engine/stringmaps.go +++ b/engine/stringmaps.go @@ -1,15 +1,22 @@ package engine -import "strings" +import ( + "fmt" + "strings" +) -func SliceToMap(list []string, del string) map[string]string { +func SliceToMap(list []string, del string) (map[string]string, error) { m := make(map[string]string) for _, e := range list { parts := strings.Split(e, del) - m[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) + if len(parts) == 2 { + m[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) + } else { + return nil, fmt.Errorf("could not split '%s' into key value pair with '=' delimiter", e) + } } - return m + return m, nil } func MergeMaps(m1, m2 map[string]string) map[string]string { diff --git a/go.mod b/go.mod index 1938ff6..c32c582 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,13 @@ go 1.20 require ( github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf - github.com/hetznercloud/hcloud-go v1.41.0 + github.com/hetznercloud/hcloud-go/v2 v2.1.0 github.com/joho/godotenv v1.5.1 github.com/rs/zerolog v1.29.1 github.com/urfave/cli/v2 v2.25.3 github.com/woodpecker-ci/woodpecker v0.15.1-0.20230514144654-1f9d94356439 golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 - golang.org/x/net v0.10.0 + golang.org/x/net v0.12.0 golang.org/x/oauth2 v0.8.0 ) @@ -22,14 +22,14 @@ require ( 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_golang v1.16.0 // 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 + github.com/prometheus/procfs v0.10.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.30.0 // indirect ) diff --git a/go.sum b/go.sum index be104fb..ef1d053 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ 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.41.0 h1:KJGFRRc68QiVu4PrEP5BmCQVveCP2CM26UGQUKGpIUs= -github.com/hetznercloud/hcloud-go v1.41.0/go.mod h1:NaHg47L6C77mngZhwBG652dTAztYrsZ2/iITJKhQkHA= +github.com/hetznercloud/hcloud-go/v2 v2.1.0 h1:NJEQ9pdF8qerYav7ZH/tpzC/1+Q4UR7vIq/s/CmJ4Jk= +github.com/hetznercloud/hcloud-go/v2 v2.1.0/go.mod h1:4iUG2NG8b61IAwNx6UsMWQ6IfIf/i1RsG0BbsKAyR5Q= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -32,20 +32,20 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= 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/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/urfave/cli/v2 v2.25.3 h1:VJkt6wvEBOoSjPFQvOkv6iWIrsJyCrKGtCtxXWwmGeY= github.com/urfave/cli/v2 v2.25.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/woodpecker-ci/woodpecker v0.15.1-0.20230514144654-1f9d94356439 h1:3eSltRLPidNU1BrwpEj8G4snWT4mZraXIvX92r6Ddsw= @@ -56,8 +56,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 h1:5llv2sWeaMSnA3w2kS57ouQQ4pudlXrR0dCgw51QK9o= golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -65,12 +65,12 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -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/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= diff --git a/providers/hetznercloud/driver.go b/providers/hetznercloud/driver.go index c325879..fc4a8c7 100644 --- a/providers/hetznercloud/driver.go +++ b/providers/hetznercloud/driver.go @@ -7,7 +7,7 @@ import ( "strings" "text/template" - "github.com/hetznercloud/hcloud-go/hcloud" + "github.com/hetznercloud/hcloud-go/v2/hcloud" "github.com/urfave/cli/v2" "golang.org/x/exp/maps" @@ -127,7 +127,10 @@ func New(c *cli.Context, config *config.Config, name string) (engine.Provider, e d.UserData = userdata - labels := engine.SliceToMap(c.StringSlice("hetznercloud-labels"), "=") + labels, err := engine.SliceToMap(c.StringSlice("hetznercloud-labels"), "=") + if err != nil { + return nil, fmt.Errorf("%s: %w", d.Name, err) + } for _, key := range maps.Keys(labels) { if strings.HasPrefix(key, d.LabelPrefix) { return nil, fmt.Errorf("%s: %w: %s", d.Name, ErrIllegalLablePrefix, d.LabelPrefix) @@ -144,12 +147,17 @@ func (d *Driver) DeployAgent(ctx context.Context, agent *woodpecker.Agent) error userdataString, err := engine.RenderUserDataTemplate(d.Config, agent, d.UserData) if err != nil { - return fmt.Errorf("%s: %w", d.Name, err) + return fmt.Errorf("%s: RenderUserDataTemplate: %w", d.Name, err) } - image, _, err := d.client.Image.GetByName(ctx, d.Image) + serverType, _, err := d.client.ServerType.GetByName(ctx, d.ServerType) if err != nil { - return fmt.Errorf("%s: %w", d.Image, err) + return fmt.Errorf("%s: ServerTypeGetByName: %w", d.Name, err) + } + + image, _, err := d.client.Image.GetByNameAndArchitecture(ctx, d.Image, serverType.Architecture) + if err != nil { + return fmt.Errorf("%s: ImageGetByNameAndArchitecture: %w", d.Image, err) } if image == nil { return fmt.Errorf("%s: %w: %s", d.Name, ErrImageNotFound, d.Image) @@ -159,7 +167,7 @@ func (d *Driver) DeployAgent(ctx context.Context, agent *woodpecker.Agent) error for _, item := range d.SSHKeys { key, _, err := d.client.SSHKey.GetByName(ctx, item) if err != nil { - return fmt.Errorf("%s: %w", d.Image, err) + return fmt.Errorf("%s: SSHKeyGetByName: %w", d.Image, err) } if key == nil { return fmt.Errorf("%s: %w: %s", d.Name, ErrSSHKeyNotFound, item) @@ -171,7 +179,7 @@ func (d *Driver) DeployAgent(ctx context.Context, agent *woodpecker.Agent) error for _, item := range d.Networks { network, _, err := d.client.Network.GetByName(ctx, item) if err != nil { - return fmt.Errorf("%s: %w", d.Image, err) + return fmt.Errorf("%s: NetworkGetByName: %w", d.Image, err) } if network == nil { return fmt.Errorf("%s: %w: %s", d.Name, ErrNetworkNotFound, item) @@ -183,7 +191,7 @@ func (d *Driver) DeployAgent(ctx context.Context, agent *woodpecker.Agent) error for _, item := range d.Firewalls { fw, _, err := d.client.Firewall.GetByName(ctx, item) if err != nil { - return fmt.Errorf("%s: %w", d.Image, err) + return fmt.Errorf("%s: FirewallGetByName: %w", d.Image, err) } if fw == nil { return fmt.Errorf("%s: %w: %s", d.Name, ErrFirewallNotFound, item) @@ -198,20 +206,18 @@ func (d *Driver) DeployAgent(ctx context.Context, agent *woodpecker.Agent) error Location: &hcloud.Location{ Name: d.Location, }, - ServerType: &hcloud.ServerType{ - Name: d.ServerType, - }, - SSHKeys: sshKeys, - Networks: networks, - Firewalls: firewalls, - Labels: labels, + ServerType: serverType, + SSHKeys: sshKeys, + Networks: networks, + Firewalls: firewalls, + Labels: labels, PublicNet: &hcloud.ServerCreatePublicNet{ EnableIPv4: d.EnableIPv4, EnableIPv6: d.EnableIPv6, }, }) if err != nil { - return fmt.Errorf("%s: %w", d.Name, err) + return fmt.Errorf("%s: ServerCreate: %w", d.Name, err) } return nil