Skip to content

Commit

Permalink
fix: use first host ip in public ipv6 network (#192)
Browse files Browse the repository at this point in the history
Since the public net ipv6 is a network (CIDR block), we must use the
next host IP in that network.
  • Loading branch information
jooola authored Jun 6, 2024
1 parent 5356543 commit 77bb637
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 9 deletions.
29 changes: 20 additions & 9 deletions builder/hcloud/step_create_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package hcloud
import (
"context"
"fmt"
"net/netip"
"os"
"sort"
"strings"
Expand Down Expand Up @@ -135,16 +136,11 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu
// instance id inside of the provisioners, used in step_provision.
state.Put(StateInstanceID, server.ID)

switch {
case !server.PublicNet.IPv4.IsUnspecified():
state.Put(StateServerIP, server.PublicNet.IPv4.IP.String())
case !server.PublicNet.IPv6.IsUnspecified():
state.Put(StateServerIP, server.PublicNet.IPv6.IP.String())
case len(server.PrivateNet) > 0:
state.Put(StateServerIP, server.PrivateNet[0].IP.String())
default:
return errorHandler(state, ui, "", fmt.Errorf("Could not find server ip"))
serverIP := firstAvailableIP(server)
if serverIP == "" {
return errorHandler(state, ui, "", fmt.Errorf("Could not find available ip"))
}
state.Put(StateServerIP, serverIP)

if c.UpgradeServerType != "" {
ui.Say("Upgrading server type...")
Expand Down Expand Up @@ -291,3 +287,18 @@ func getPrimaryIP(ctx context.Context, client *hcloud.Client, publicIP string) (
}
return hcloudPublicIP, "", nil
}

func firstAvailableIP(server *hcloud.Server) string {
switch {
case !server.PublicNet.IPv4.IsUnspecified():
return server.PublicNet.IPv4.IP.String()
case !server.PublicNet.IPv6.IsUnspecified():
network, ok := netip.AddrFromSlice(server.PublicNet.IPv6.IP)
if ok {
return network.Next().String()
}
case len(server.PrivateNet) > 0:
return server.PrivateNet[0].IP.String()
}
return ""
}
54 changes: 54 additions & 0 deletions builder/hcloud/step_create_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,3 +463,57 @@ func TestStepCreateServer(t *testing.T) {
},
})
}

func TestFirstAvailableIP(t *testing.T) {
testCases := []struct {
name string
server *hcloud.Server
want string
}{
{
name: "empty",
server: &hcloud.Server{},
want: "",
},
{
name: "public_ipv4",
server: &hcloud.Server{
PublicNet: hcloud.ServerPublicNetFromSchema(schema.ServerPublicNet{
IPv4: schema.ServerPublicNetIPv4{ID: 1, IP: "1.2.3.4"},
IPv6: schema.ServerPublicNetIPv6{ID: 2, IP: "2a01:4f8:1c19:1403::/64"},
}),
PrivateNet: []hcloud.ServerPrivateNet{
hcloud.ServerPrivateNetFromSchema(schema.ServerPrivateNet{Network: 3, IP: "10.0.0.1"}),
},
},
want: "1.2.3.4",
},
{
name: "public_ipv6",
server: &hcloud.Server{
PublicNet: hcloud.ServerPublicNetFromSchema(schema.ServerPublicNet{
IPv6: schema.ServerPublicNetIPv6{ID: 2, IP: "2a01:4f8:1c19:1403::/64"},
}),
PrivateNet: []hcloud.ServerPrivateNet{
hcloud.ServerPrivateNetFromSchema(schema.ServerPrivateNet{Network: 3, IP: "10.0.0.1"}),
},
},
want: "2a01:4f8:1c19:1403::1",
},
{
name: "private_ipv4",
server: &hcloud.Server{
PrivateNet: []hcloud.ServerPrivateNet{
hcloud.ServerPrivateNetFromSchema(schema.ServerPrivateNet{Network: 3, IP: "10.0.0.1"}),
},
},
want: "10.0.0.1",
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
result := firstAvailableIP(testCase.server)
assert.Equal(t, testCase.want, result)
})
}
}

0 comments on commit 77bb637

Please sign in to comment.