diff --git a/command/agent/agent.go b/command/agent/agent.go index fcf4a57af3b..e93e452b39c 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -889,8 +889,28 @@ func convertClientConfig(agentConfig *Config) (*clientconfig.Config, error) { conf.CNIPath = agentConfig.Client.CNIPath conf.CNIConfigDir = agentConfig.Client.CNIConfigDir conf.BridgeNetworkName = agentConfig.Client.BridgeNetworkName - conf.BridgeNetworkAllocSubnet = agentConfig.Client.BridgeNetworkSubnet - conf.BridgeNetworkAllocSubnetIPv6 = agentConfig.Client.BridgeNetworkSubnetIPv6 + ipv4Subnet := agentConfig.Client.BridgeNetworkSubnet + if ipv4Subnet != "" { + ip, _, err := net.ParseCIDR(ipv4Subnet) + if err != nil { + return nil, fmt.Errorf("invalid bridge_network_subnet: %w", err) + } + if ip.To4() == nil { + return nil, fmt.Errorf("invalid bridge_network_subnet: %q is not an IPv4 address", ipv4Subnet) + } + conf.BridgeNetworkAllocSubnet = ipv4Subnet + } + ipv6Subnet := agentConfig.Client.BridgeNetworkSubnetIPv6 + if ipv6Subnet != "" { + ip, _, err := net.ParseCIDR(ipv6Subnet) + if err != nil { + return nil, fmt.Errorf("invalid bridge_network_subnet_ipv6: %w", err) + } + if ip.To16() == nil { + return nil, fmt.Errorf("invalid bridge_network_subnet_ipv6: %q is not an IPv6 address", ipv6Subnet) + } + conf.BridgeNetworkAllocSubnetIPv6 = ipv6Subnet + } conf.BridgeNetworkHairpinMode = agentConfig.Client.BridgeNetworkHairpinMode for _, hn := range agentConfig.Client.HostNetworks { diff --git a/command/agent/agent_test.go b/command/agent/agent_test.go index d1e261670c6..67b1cfa9a64 100644 --- a/command/agent/agent_test.go +++ b/command/agent/agent_test.go @@ -13,6 +13,7 @@ import ( "time" "github.com/hashicorp/nomad/ci" + clientconfig "github.com/hashicorp/nomad/client/config" cstructs "github.com/hashicorp/nomad/client/structs" "github.com/hashicorp/nomad/helper/pointer" "github.com/hashicorp/nomad/helper/testlog" @@ -677,6 +678,79 @@ func TestAgent_ServerConfig_RaftProtocol_3(t *testing.T) { } } +func TestConvertClientConfig(t *testing.T) { + ci.Parallel(t) + cases := []struct { + name string + // modConfig modifies the agent config before passing to convertClientConfig() + modConfig func(*Config) + // assert makes assertions about the resulting client config + assert func(*testing.T, *clientconfig.Config) + expectErr string + }{ + { + name: "default", + assert: func(t *testing.T, cc *clientconfig.Config) { + must.Eq(t, "global", cc.Region) + }, + }, + { + name: "ipv4 bridge subnet", + modConfig: func(c *Config) { + c.Client.BridgeNetworkSubnet = "10.0.0.0/24" + }, + assert: func(t *testing.T, cc *clientconfig.Config) { + must.Eq(t, "10.0.0.0/24", cc.BridgeNetworkAllocSubnet) + }, + }, + { + name: "invalid ipv4 bridge subnet", + modConfig: func(c *Config) { + c.Client.BridgeNetworkSubnet = "invalid-ip4" + }, + expectErr: "invalid bridge_network_subnet:", + }, + { + name: "ipv6 bridge subnet", + modConfig: func(c *Config) { + c.Client.BridgeNetworkSubnetIPv6 = "fd00:a110:c8::/120" + }, + assert: func(t *testing.T, cc *clientconfig.Config) { + must.Eq(t, "fd00:a110:c8::/120", cc.BridgeNetworkAllocSubnetIPv6) + }, + }, + { + name: "invalid ipv6 bridge subnet", + modConfig: func(c *Config) { + c.Client.BridgeNetworkSubnetIPv6 = "invalid-ip6" + }, + expectErr: "invalid bridge_network_subnet_ipv6:", + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + c := DefaultConfig() + + if tc.modConfig != nil { + tc.modConfig(c) + } + + // method under test + cc, err := convertClientConfig(c) + + if tc.expectErr != "" { + must.ErrorContains(t, err, tc.expectErr) + } else { + must.NoError(t, err) + } + + if tc.assert != nil { + tc.assert(t, cc) + } + }) + } +} + func TestAgent_ClientConfig_discovery(t *testing.T) { ci.Parallel(t) conf := DefaultConfig()