Repository: hetznercloud/hcloud-cloud-controller-manager
Pull request #471 (2023-07-18 06:43:58)

feat(helm): allow to set labels and annotations for podMonitor
This PR adds the ability to set labels and annotations to the podMonitor. Setting the label is usually necessary for the podMonitor to be picked up by the Prometheus Operator (https://github.com/prometheus-operator/prometheus-operator/issues/3636#issuecomment-796688902). Setting an annotation helps to defer the deployment of the custom resource if e.g. deploying with ArgoCD (https://argo-cd.readthedocs.io/en/stable/user-guide/sync-options/#skip-dry-run-for-new-custom-resources-types).


Patch:
diff --git a/chart/templates/podmonitor.yaml b/chart/templates/podmonitor.yaml
index 198e7436..b2cce3ad 100644
--- a/chart/templates/podmonitor.yaml
+++ b/chart/templates/podmonitor.yaml
@@ -5,6 +5,14 @@ kind: PodMonitor
 metadata:
   name: {{ include "hcloud-cloud-controller-manager.name" . }}
   namespace: {{ .Release.Namespace }}
+  labels:
+    {{- with $.Values.monitoring.podMonitor.labels }}
+      {{- toYaml . | nindent 4 }}
+    {{- end }}
+  annotations:
+    {{- range $key, $value := .Values.monitoring.podMonitor.annotations }}
+    {{ $key }}: {{ $value | quote }}
+    {{- end }}
 spec:
   {{- tpl (toYaml $.Values.monitoring.podMonitor.spec) $ | nindent 2 }}
   selector:
diff --git a/chart/values.yaml b/chart/values.yaml
index 2e2812c1..1d889ae1 100644
--- a/chart/values.yaml
+++ b/chart/values.yaml
@@ -35,11 +35,17 @@ monitoring:
     # When enabled (and metrics.enabled=true), a PodMonitor will be deployed to scrape metrics.
     # The PodMonitor [1] CRD must already exist in the target cluster.
     enabled: false
+    # PodMonitor Labels
+    labels: {}
+    #   release: kube-prometheus-stack
+    # PodMonitor Annotations
+    annotations: {}
     # PodMonitorSpec to be deployed. The "selector" field is set elsewhere and should *not* be used here.
     # https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.PodMonitorSpec
     spec:
       podMetricsEndpoints:
         - port: metrics
+    
 
 nameOverride: ~
 
diff --git a/go.mod b/go.mod
index eef435a8..be58a6fd 100644
--- a/go.mod
+++ b/go.mod
@@ -16,7 +16,6 @@ require (
 )
 
 require (
-	cloud.google.com/go/compute/metadata v0.2.3 // indirect
 	github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
 	github.com/NYTimes/gziphandler v1.1.1 // indirect
 	github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
@@ -91,8 +90,8 @@ require (
 	golang.org/x/text v0.11.0 // indirect
 	golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
-	google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd // indirect
-	google.golang.org/grpc v1.51.0 // indirect
+	google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
+	google.golang.org/grpc v1.53.0 // indirect
 	google.golang.org/protobuf v1.30.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
diff --git a/go.sum b/go.sum
index abeae176..f12d728e 100644
--- a/go.sum
+++ b/go.sum
@@ -20,9 +20,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf
 cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
 cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
 cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/compute v1.14.0 h1:hfm2+FfxVmnRlh6LpB7cg1ZNU+5edAHmW679JePztk0=
+cloud.google.com/go/compute v1.15.1 h1:7UGq3QknM33pw5xATlpzeoomNxsacIVvTqTTvbfajmE=
 cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
-cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
 cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
 cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
@@ -572,8 +571,8 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd h1:OjndDrsik+Gt+e6fs45z9AxiewiKyLKYpA45W5Kpkks=
-google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE=
+google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
+google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -590,8 +589,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
 google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
-google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
-google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
+google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
+google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/hcloud/routes.go b/hcloud/routes.go
index 4883dcd1..9221265d 100644
--- a/hcloud/routes.go
+++ b/hcloud/routes.go
@@ -35,9 +35,14 @@ func newRoutes(client *hcloud.Client, networkID int64) (*routes, error) {
 	}
 
 	return &routes{
-		client:      client,
-		network:     networkObj,
-		serverCache: &hcops.AllServersCache{LoadFunc: client.Server.All},
+		client:  client,
+		network: networkObj,
+		serverCache: &hcops.AllServersCache{
+			// client.Server.All will load ALL the servers in the project, even those
+			// that are not part of the Kubernetes cluster.
+			LoadFunc: client.Server.All,
+			Network:  networkObj,
+		},
 	}, nil
 }
 
diff --git a/internal/hcops/server.go b/internal/hcops/server.go
index 6a38031a..897cebf8 100644
--- a/internal/hcops/server.go
+++ b/internal/hcops/server.go
@@ -7,6 +7,8 @@ import (
 	"sync"
 	"time"
 
+	"k8s.io/klog/v2"
+
 	"github.com/hetznercloud/hcloud-cloud-controller-manager/internal/metrics"
 	"github.com/hetznercloud/hcloud-go/v2/hcloud"
 )
@@ -21,6 +23,9 @@ type AllServersCache struct {
 	LoadTimeout time.Duration
 	MaxAge      time.Duration
 
+	// If set, only IPs in this network will be considered for [ByPrivateIP]
+	Network *hcloud.Network
+
 	lastRefresh time.Time
 	byPrivIP    map[string]*hcloud.Server
 	byName      map[string]*hcloud.Server
@@ -102,9 +107,18 @@ func (c *AllServersCache) getCache(getSrv func() (*hcloud.Server, bool)) (*hclou
 	for _, srv := range srvs {
 		// Index servers by the IPs of their private networks
 		for _, n := range srv.PrivateNet {
+			if c.Network != nil {
+				if n.Network.ID != c.Network.ID {
+					// Only consider private IPs in the right network
+					continue
+				}
+			}
 			if n.IP == nil {
 				continue
 			}
+			if _, ok := c.byPrivIP[n.IP.String()]; ok {
+				klog.Warningf("Overriding AllServersCache entry for private ip %s with server %s\n", n.IP.String(), srv.Name)
+			}
 			c.byPrivIP[n.IP.String()] = srv
 		}
 
diff --git a/scripts/git-version.bash b/scripts/git-version.bash
deleted file mode 100755
index 5bc1a7d8..00000000
--- a/scripts/git-version.bash
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-
-# parse the current git commit hash
-COMMIT=`git rev-parse HEAD`
-
-# check if the current commit has a matching tag
-TAG=$(git describe --exact-match --abbrev=0 --tags ${COMMIT} 2> /dev/null || true)
-SUFFIX=''
-DETAIL=''
-
-# use the matching tag as the version, if available
-if [ -z "$TAG" ]; then
-  TAG=$(git describe --abbrev=0)
-  COMMITS=$(git --no-pager log ${TAG}..HEAD --oneline)
-  COMMIT_COUNT=$(echo -e "${COMMITS}" | wc -l)
-  COMMIT_COUNT_PADDING=$(printf %03d $COMMIT_COUNT)
-  SHORT_COMMIT_ID=$(git rev-parse --short HEAD)
-
-  SUFFIX='-dev'
-  DETAIL=".${COMMIT_COUNT_PADDING}.${SHORT_COMMIT_ID}"
-fi
-
-if [ -n "$(git diff --shortstat 2> /dev/null | tail -n1)" ]; then
-  SUFFIX="-dirty"
-fi
-
-
-VERSION="${TAG}${SUFFIX}${DETAIL}"
-echo $VERSION
diff --git a/skaffold.yaml b/skaffold.yaml
index f10feed2..049727d5 100644
--- a/skaffold.yaml
+++ b/skaffold.yaml
@@ -5,6 +5,7 @@ metadata:
 build:
   artifacts:
     - image: hetznercloud/hcloud-cloud-controller-manager
+      runtimeType: go
       docker:
         dockerfile: hack/Dockerfile
         cacheFrom:


Test patch:
diff --git a/internal/hcops/server_test.go b/internal/hcops/server_test.go
index 53c5b9b5..9ca9fe95 100644
--- a/internal/hcops/server_test.go
+++ b/internal/hcops/server_test.go
@@ -197,6 +197,52 @@ func TestAllServersCache_ClientError(t *testing.T) {
 	runAllServersCacheTests(t, "Not found", tmpl, cacheOps)
 }
 
+func TestAllServersCache_DuplicatePrivateIP(t *testing.T) {
+	// Regression test for https://github.com/hetznercloud/hcloud-cloud-controller-manager/issues/470
+
+	network := &hcloud.Network{
+		ID:   12345,
+		Name: "cluster-network",
+	}
+	srv := &hcloud.Server{
+		ID:   101010,
+		Name: "cluster-node",
+		PrivateNet: []hcloud.ServerPrivateNet{
+			{
+				IP:      net.ParseIP("10.0.0.4"),
+				Network: network,
+			},
+		},
+	}
+	srvInvalid := &hcloud.Server{
+		ID:   101012,
+		Name: "invalid-node",
+		PrivateNet: []hcloud.ServerPrivateNet{
+			{
+				IP: net.ParseIP("10.0.0.4"),
+				Network: &hcloud.Network{
+					ID:   54321,
+					Name: "invalid-network",
+				},
+			},
+		},
+	}
+
+	cacheOps := newAllServersCacheOps(t, srv)
+	tmpl := allServersCacheTestCase{
+		SetUp: func(t *testing.T, tt *allServersCacheTestCase) {
+			tt.Cache.Network = network
+
+			tt.ServerClient.
+				On("All", mock.Anything).
+				Return([]*hcloud.Server{srv, srvInvalid}, nil)
+		},
+		Expected: srv,
+	}
+
+	runAllServersCacheTests(t, "DuplicatePrivateIP", tmpl, cacheOps)
+}
+
 type allServersCacheOp func(c *hcops.AllServersCache) (*hcloud.Server, error)
 
 func newAllServersCacheOps(t *testing.T, srv *hcloud.Server) map[string]allServersCacheOp {
diff --git a/scripts/test.bash b/scripts/test.bash
deleted file mode 100755
index 9c730d5c..00000000
--- a/scripts/test.bash
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env bash
-
-set -eu
-
-diff -u <(echo -n) <(gofmt -d -s $(find . -type f -name '*.go' | grep -v ^./vendor))
-go vet ./...
-go test ./...