metallb-ip-floater/internal/hetzner.go
Tobias Trabelsi 6bdae933a8
Some checks are pending
ci/woodpecker/push/woodpecker Pipeline is pending
fix handling if floating ip is not yet assigned
2024-02-02 23:38:04 +01:00

100 lines
3.5 KiB
Go

package internal
import (
"context"
"errors"
"fmt"
"net"
"github.com/hetznercloud/hcloud-go/hcloud"
log "github.com/sirupsen/logrus"
)
func GetSpeakableNodes(cfg *Config) ([]string, error) {
client := hcloud.NewClient(hcloud.WithToken(cfg.HcloudToken))
server, _, err := client.Server.List(context.TODO(), hcloud.ServerListOpts{
ListOpts: hcloud.ListOpts{
LabelSelector: cfg.LabelSelector,
}})
if err != nil {
return nil, errors.New(fmt.Sprintf("Error listing Hetzner Nodes: %s", err.Error()))
}
ips := make([]string, len(server))
if server != nil {
for i, instance := range server {
log.WithFields(log.Fields{
"Caller": "GetSpeakableNodes",
}).Info(fmt.Sprintf("Found IP: %s", instance.PrivateNet[0].IP.String()))
ips[i] = instance.PrivateNet[0].IP.String()
}
} else {
return nil, errors.New(fmt.Sprintf("No Nodes found with label selector: %s", cfg.LabelSelector))
}
return ips, nil
}
func GetNodeID(cfg *Config, ip string) (hcloud.Server, error) {
// get can only be done via name or id: https://pkg.go.dev/github.com/hetznercloud/hcloud-go/v2/hcloud#ServerClient.Get
// we can iterate over all nodes and select the one that matches the IP we know from speaker: https://pkg.go.dev/github.com/hetznercloud/hcloud-go/v2/hcloud#ServerClient.List
client := hcloud.NewClient(hcloud.WithToken(cfg.HcloudToken))
serverList, _, err := client.Server.List(context.TODO(), hcloud.ServerListOpts{
ListOpts: hcloud.ListOpts{
Page: 1,
PerPage: 100,
},
Status: []hcloud.ServerStatus{hcloud.ServerStatusRunning},
})
if err != nil {
return hcloud.Server{}, errors.New(fmt.Sprintf("Could not get Server List from Hetzner: %s", err.Error()))
}
for _, server := range serverList {
log.WithFields(log.Fields{
"Caller": "GetNodeID",
}).Info(fmt.Sprintf("Checking Node %d for announcing IP", server.ID))
if server.PublicNet.IPv4.IP.Equal(net.ParseIP(ip)) {
log.WithFields(log.Fields{
"Caller": "GetNodeID",
}).Info(fmt.Sprintf("Match on Node %d", server.ID))
return *server, nil
}
for _, network := range server.PrivateNet {
if network.IP.Equal(net.ParseIP(ip)) {
log.WithFields(log.Fields{
"Caller": "GetNodeID",
}).Info(fmt.Sprintf("Match on Node %d", server.ID))
return *server, nil
}
}
}
return hcloud.Server{}, errors.New(fmt.Sprintf("Could not find correct server"))
}
func AttachFloatingIpToNode(cfg *Config, server hcloud.Server) error {
// get floating ip by name. name can be set to config https://github.com/hetznercloud/hcloud-go/blob/v2.3.0/hcloud/floating_ip.go#L117
client := hcloud.NewClient(hcloud.WithToken(cfg.HcloudToken))
floatingIP, _, err := client.FloatingIP.GetByName(context.TODO(), cfg.FloatingIPName)
if err != nil {
return errors.New(fmt.Sprintf("Could not find Floating IP by name: %s", err.Error()))
}
if floatingIP.Server != nil {
if floatingIP.Server.ID == server.ID {
log.WithFields(log.Fields{
"Caller": "AttachFloatingIpToNode",
}).Info(fmt.Sprintf("Floating IP %s already assigned to Node %s", cfg.FloatingIPName, server.Name))
return nil
}
}
_, _, err = client.FloatingIP.Assign(context.TODO(), floatingIP, &server)
if err != nil {
log.WithFields(log.Fields{
"Caller": "AttachFloatingIpToNode",
}).Error(fmt.Sprintf("Error response while attaching floating ip: %s", err.Error()))
}
log.WithFields(log.Fields{
"Caller": "AttachFloatingIpToNode",
}).Info(fmt.Sprintf("Attached floating ip %s to node %s", cfg.FloatingIPName, server.Name))
return err
}