Skip to content

Commit

Permalink
feat: node transformer feature flags
Browse files Browse the repository at this point in the history
Introduce feature flags:
* PublicIPDiscovery enables the Cloud Controller Manager (CCM) to identify global/public IPs on the node.

Signed-off-by: Serge Logvinov <[email protected]>
  • Loading branch information
sergelogvinov committed May 6, 2024
1 parent 22e3984 commit 85e2022
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
- name: Lint
uses: golangci/golangci-lint-action@v5
with:
version: v1.57.1
version: v1.58.0
args: --timeout=5m --config=.golangci.yml
- name: Build
timeout-minutes: 10
Expand Down
7 changes: 4 additions & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,16 +143,17 @@ linters:
- errorlint
- exhaustruct
- exhaustivestruct
- err113
- forbidigo
- forcetypeassert
- funlen
- gas
- gochecknoglobals
- gochecknoinits
- gocognit
- godox
- goerr113
- gomnd
- gosec
- mnd
- ifshort
- ireturn # we return interfaces
- maintidx
Expand All @@ -175,7 +176,6 @@ linters:

# temporarily disabled linters
- copyloopvar
# https://github.com/golangci/golangci-lint/issues/4606
- intrange

# abandoned linters for which golangci shows the warning that the repo is archived by the owner
Expand All @@ -188,6 +188,7 @@ linters:
- deadcode
- ifshort
- perfsprint
- execinquery

disable-all: false
fast: false
Expand Down
48 changes: 31 additions & 17 deletions pkg/talos/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"strings"

"github.com/siderolabs/talos-cloud-controller-manager/pkg/transformer"
utilsnet "github.com/siderolabs/talos-cloud-controller-manager/pkg/utils/net"
"github.com/siderolabs/talos/pkg/machinery/resources/network"
"github.com/siderolabs/talos/pkg/machinery/resources/runtime"
Expand All @@ -21,29 +22,36 @@ import (
"k8s.io/utils/strings/slices"
)

func getNodeAddresses(config *cloudConfig, platform string, nodeIPs []string, ifaces []network.AddressStatusSpec) []v1.NodeAddress {
var publicIPv4s, publicIPv6s, publicIPs []string
func ipDescovery(nodeIPs []string, ifaces []network.AddressStatusSpec) (publicIPv4s, publicIPv6s []string) {
for _, iface := range ifaces {
if iface.LinkName == "kubespan" || iface.LinkName == "lo" {
continue
}

switch platform {
case "nocloud", "metal", "openstack":
for _, iface := range ifaces {
if iface.LinkName == "kubespan" {
ip := iface.Address.Addr()
if ip.IsGlobalUnicast() && !ip.IsPrivate() {
if slices.Contains(nodeIPs, ip.String()) {
continue
}

ip := iface.Address.Addr()
if ip.IsGlobalUnicast() && !ip.IsPrivate() {
if slices.Contains(nodeIPs, ip.String()) {
continue
}

if ip.Is6() {
publicIPv6s = append(publicIPv6s, ip.String())
} else {
publicIPv4s = append(publicIPv4s, ip.String())
}
if ip.Is6() {
publicIPv6s = append(publicIPv6s, ip.String())
} else {
publicIPv4s = append(publicIPv4s, ip.String())
}
}
}

return publicIPv4s, publicIPv6s
}

func getNodeAddresses(config *cloudConfig, platform string, features *transformer.NodeFeaturesFlagSpec, nodeIPs []string, ifaces []network.AddressStatusSpec) []v1.NodeAddress {
var publicIPv4s, publicIPv6s, publicIPs []string

switch platform {
// Those platforms don't expose public IPs information in metadata
case "nocloud", "metal", "openstack", "oracle":
publicIPv4s, publicIPv6s = ipDescovery(nodeIPs, ifaces)
default:
for _, iface := range ifaces {
if iface.LinkName == "external" {
Expand All @@ -62,6 +70,12 @@ func getNodeAddresses(config *cloudConfig, platform string, nodeIPs []string, if
}
}

if features != nil && features.PublicIPDiscovery {
ipv4, ipv6 := ipDescovery(nodeIPs, ifaces)
publicIPv4s = append(publicIPv4s, ipv4...)
publicIPv6s = append(publicIPv6s, ipv6...)
}

addresses := []v1.NodeAddress{}
for _, ip := range utilsnet.PreferedDualStackNodeIPs(config.Global.PreferIPv6, nodeIPs) {
addresses = append(addresses, v1.NodeAddress{Type: v1.NodeInternalIP, Address: ip})
Expand Down
39 changes: 38 additions & 1 deletion pkg/talos/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func TestGetNodeAddresses(t *testing.T) {
name string
cfg cloudConfig
platform string
features *transformer.NodeFeaturesFlagSpec
providedIP string
ifaces []network.AddressStatusSpec
expected []v1.NodeAddress
Expand Down Expand Up @@ -142,9 +143,45 @@ func TestGetNodeAddresses(t *testing.T) {
{Type: v1.NodeExternalIP, Address: "2001:1234::1"},
},
},
{
name: "gcp dualstack with public IPs",
cfg: cfg,
platform: "gcp",
providedIP: "192.168.0.1,fd15:1:2::192:168:0:1",
ifaces: []network.AddressStatusSpec{
{Address: netip.MustParsePrefix("192.168.0.1/24")},
{Address: netip.MustParsePrefix("fe80::e0b5:71ff:fe24:7e60/64")},
{Address: netip.MustParsePrefix("1.2.3.4/24"), LinkName: "external"},
{Address: netip.MustParsePrefix("2001:1234::123/64")},
},
expected: []v1.NodeAddress{
{Type: v1.NodeInternalIP, Address: "192.168.0.1"},
{Type: v1.NodeInternalIP, Address: "fd15:1:2:0:192:168:0:1"},
{Type: v1.NodeExternalIP, Address: "1.2.3.4"},
},
},
{
name: "gcp dualstack with public IPs and featureflag",
cfg: cfg,
platform: "gcp",
features: &transformer.NodeFeaturesFlagSpec{PublicIPDiscovery: true},
providedIP: "192.168.0.1,fd15:1:2::192:168:0:1",
ifaces: []network.AddressStatusSpec{
{Address: netip.MustParsePrefix("192.168.0.1/24")},
{Address: netip.MustParsePrefix("fe80::e0b5:71ff:fe24:7e60/64")},
{Address: netip.MustParsePrefix("1.2.3.4/24"), LinkName: "external"},
{Address: netip.MustParsePrefix("2001:1234::123/64")},
},
expected: []v1.NodeAddress{
{Type: v1.NodeInternalIP, Address: "192.168.0.1"},
{Type: v1.NodeInternalIP, Address: "fd15:1:2:0:192:168:0:1"},
{Type: v1.NodeExternalIP, Address: "1.2.3.4"},
{Type: v1.NodeExternalIP, Address: "2001:1234::123"},
},
},
} {
t.Run(tt.name, func(t *testing.T) {
addresses := getNodeAddresses(&tt.cfg, tt.platform, strings.Split(tt.providedIP, ","), tt.ifaces)
addresses := getNodeAddresses(&tt.cfg, tt.platform, tt.features, strings.Split(tt.providedIP, ","), tt.ifaces)

assert.Equal(t, tt.expected, addresses)
})
Expand Down
2 changes: 1 addition & 1 deletion pkg/talos/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud
return nil, fmt.Errorf("error getting interfaces list from the node %s: %w", node.Name, err)
}

addresses := getNodeAddresses(i.c.config, meta.Platform, nodeIPs, ifaces)
addresses := getNodeAddresses(i.c.config, meta.Platform, &nodeSpec.Features, nodeIPs, ifaces)

addresses = append(addresses, v1.NodeAddress{Type: v1.NodeHostName, Address: node.Name})

Expand Down
20 changes: 14 additions & 6 deletions pkg/transformer/transformer.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,20 @@ type NodeTerm struct {
Annotations map[string]string `yaml:"annotations,omitempty"`
Labels map[string]string `yaml:"labels,omitempty"`
PlatformMetadata map[string]string `yaml:"platformMetadata,omitempty"`
Features NodeFeaturesFlagSpec `yaml:"features,omitempty"`
}

// NodeSpec represents the transformed node specifcations.
type NodeSpec struct {
Annotations map[string]string
Labels map[string]string
Features NodeFeaturesFlagSpec
}

// NodeFeaturesFlagSpec represents the node features flags.
type NodeFeaturesFlagSpec struct {
// PublicIPDiscovery try to find public IP on the node
PublicIPDiscovery bool `yaml:"publicIPDiscovery,omitempty"`
}

var prohibitedPlatformMetadataKeys = []string{"hostname", "platform"}
Expand All @@ -36,6 +44,11 @@ func TransformNode(terms []NodeTerm, platformMetadata *runtime.PlatformMetadataS
return nil, nil
}

node := &NodeSpec{
Annotations: make(map[string]string),
Labels: make(map[string]string),
}

metadata := metadataFromStruct(platformMetadata)

for _, term := range terms {
Expand All @@ -45,11 +58,6 @@ func TransformNode(terms []NodeTerm, platformMetadata *runtime.PlatformMetadataS
}

if match {
node := &NodeSpec{
Annotations: make(map[string]string),
Labels: make(map[string]string),
}

if term.Annotations != nil {
for k, v := range term.Annotations {
t, err := executeTemplate(v, platformMetadata)
Expand Down Expand Up @@ -107,7 +115,7 @@ func TransformNode(terms []NodeTerm, platformMetadata *runtime.PlatformMetadataS
}
}

return nil, nil
return node, nil
}

func executeTemplate(tmpl string, data interface{}) (string, error) {
Expand Down

0 comments on commit 85e2022

Please sign in to comment.