Skip to content

Commit

Permalink
feat: add private network for all machines in a cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
apricote committed Jul 23, 2024
1 parent ee307db commit b378e33
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 9 deletions.
68 changes: 67 additions & 1 deletion platform/api/hetzner/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package hetzner
import (
"context"
"fmt"
"net"
"net/url"
"os"
"sort"
Expand Down Expand Up @@ -52,6 +53,8 @@ type Server struct{ *hcloud.Server }

type SSHKey struct{ *hcloud.SSHKey }

type Network struct{ *hcloud.Network }

// New returns a Hetzner API instance.
func New(opts *Options) (*API, error) {
client := hcloud.NewClient(
Expand Down Expand Up @@ -93,7 +96,7 @@ func New(opts *Options) (*API, error) {
}

// CreateServer using the Hetzner API.
func (a *API) CreateServer(ctx context.Context, name, userdata string, sshKey *SSHKey) (*Server, error) {
func (a *API) CreateServer(ctx context.Context, name, userdata string, sshKey *SSHKey, network *Network) (*Server, error) {
opts := hcloud.ServerCreateOpts{
Name: name,
ServerType: a.serverType,
Expand All @@ -104,6 +107,9 @@ func (a *API) CreateServer(ctx context.Context, name, userdata string, sshKey *S
if sshKey != nil {
opts.SSHKeys = []*hcloud.SSHKey{sshKey.SSHKey}
}
if network != nil {
opts.Networks = []*hcloud.Network{network.Network}
}

result, _, err := a.client.Server.Create(ctx, opts)
if err != nil {
Expand Down Expand Up @@ -160,6 +166,38 @@ func (a *API) DeleteSSHKey(ctx context.Context, key *SSHKey) error {
return err
}

func (a *API) CreateNetwork(ctx context.Context, name string) (*Network, error) {
_, ipnet, err := net.ParseCIDR("10.0.0.0/16")
if err != nil {
return nil, fmt.Errorf("parsing CIDR for network: %w", err)
}

network, _, err := a.client.Network.Create(ctx, hcloud.NetworkCreateOpts{
Name: name,
IPRange: ipnet,
Subnets: []hcloud.NetworkSubnet{{
Type: hcloud.NetworkSubnetTypeCloud,
IPRange: ipnet,
NetworkZone: a.location.NetworkZone,
}},
Labels: DefaultLabels,
})
if err != nil {
return nil, fmt.Errorf("creating network: %w", err)
}

return &Network{network}, nil
}

func (a *API) DeleteNetwork(ctx context.Context, network *Network) error {
_, err := a.client.Network.Delete(ctx, network.Network)
if err != nil {
return fmt.Errorf("deleting network: %w", err)
}

return nil
}

func (a *API) UploadImage(ctx context.Context, name, path, board string) (int64, error) {
opts := hcloudimages.UploadOptions{
ImageCompression: hcloudimages.CompressionBZ2,
Expand Down Expand Up @@ -212,6 +250,10 @@ func (a *API) GC(ctx context.Context, gracePeriod time.Duration) error {
return fmt.Errorf("failed to gc ssh keys: %w", err)
}

if err := a.gcNetworks(ctx, createdCutoff); err != nil {
return fmt.Errorf("failed to gc networks: %w", err)
}

return nil
}

Expand Down Expand Up @@ -294,6 +336,30 @@ func (a *API) gcSSHKeys(ctx context.Context, createdCutoff time.Time) error {
return nil
}

func (a *API) gcNetworks(ctx context.Context, createdCutoff time.Time) error {
networks, err := a.client.Network.AllWithOpts(ctx, hcloud.NetworkListOpts{
ListOpts: hcloud.ListOpts{
LabelSelector: labelSelector(DefaultLabels),
},
})
if err != nil {
return fmt.Errorf("failed to list current networks: %w", err)
}

for _, network := range networks {
if network.Created.After(createdCutoff) {
continue
}

_, err := a.client.Network.Delete(ctx, network)
if err != nil {
return fmt.Errorf("failed to delete network: %w", err)
}
}

return nil
}

// GetConsoleOutput returns the console output using API calls or other.
func (a *API) GetConsoleOutput(id string) (string, error) {
// Hetzner Cloud API does not have an easy way to retrieve this.
Expand Down
18 changes: 12 additions & 6 deletions platform/machine/hetzner/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ import (

type cluster struct {
*platform.BaseCluster
flight *flight
sshKey *hetzner.SSHKey
flight *flight
sshKey *hetzner.SSHKey
network *hetzner.Network
}

func (bc *cluster) NewMachine(userdata *conf.UserData) (platform.Machine, error) {
conf, err := bc.RenderUserData(userdata, map[string]string{
"$public_ipv4": "${COREOS_CUSTOM_PUBLIC_IPV4}",
"$private_ipv4": "${COREOS_CUSTOM_PRIVATE_IPV4}",
"$private_ipv4": "${COREOS_CUSTOM_PRIVATE_IPV4_0}",
})
if err != nil {
return nil, err
Expand All @@ -38,11 +39,9 @@ func (bc *cluster) NewMachine(userdata *conf.UserData) (platform.Machine, error)
conf.AddSystemdUnitDropin("coreos-metadata.service", "00-custom-metadata.conf", `[Service]
ExecStartPost=/usr/bin/sed -i "s/HETZNER/CUSTOM/" /run/metadata/flatcar
ExecStartPost=/usr/bin/sed -i "s/COREOS_COREOS/COREOS/" /run/metadata/flatcar
ExecStartPost=/usr/bin/sed -i "s/IPV4_PRIVATE/PRIVATE_IPV4/" /run/metadata/flatcar
ExecStartPost=/usr/bin/sed -i "s/IPV4_PUBLIC/PUBLIC_IPV4/" /run/metadata/flatcar
`)

instance, err := bc.flight.api.CreateServer(context.TODO(), bc.vmname(), conf.String(), bc.sshKey)
instance, err := bc.flight.api.CreateServer(context.TODO(), bc.vmname(), conf.String(), bc.sshKey, bc.network)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -92,5 +91,12 @@ func (bc *cluster) vmname() string {

func (bc *cluster) Destroy() {
bc.BaseCluster.Destroy()
if bc.network != nil {
if err := bc.flight.api.DeleteNetwork(context.TODO(), bc.network); err != nil {
plog.Errorf("deleting network %v: %v", bc.network.Name, err)
}

}

bc.flight.DelCluster(bc)
}
5 changes: 5 additions & 0 deletions platform/machine/hetzner/flight.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ func (bf *flight) NewCluster(rconf *platform.RuntimeConfig) (platform.Cluster, e
c.sshKey = bf.sshKey
}

c.network, err = bf.api.CreateNetwork(context.TODO(), bc.Name())
if err != nil {
return nil, fmt.Errorf("creating network for cluster: %w", err)
}

bf.AddCluster(c)

return c, nil
Expand Down
3 changes: 1 addition & 2 deletions platform/machine/hetzner/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ func (bm *machine) IP() string {
return bm.mach.Server.PublicNet.IPv4.IP.String()
}

// IP returns the private IP of the machine.
// Right now no machine has a private ip, should this be added?
// PrivateIP returns the private IP of the machine.
func (bm *machine) PrivateIP() string {
if len(bm.mach.Server.PrivateNet) > 0 {
return bm.mach.Server.PrivateNet[0].IP.String()
Expand Down

0 comments on commit b378e33

Please sign in to comment.