From be371fc77f13902aefe0f8ef9fa2ef9b4c9a9d14 Mon Sep 17 00:00:00 2001
From: Andrey Anastasov <98102124+andrerun@users.noreply.github.com>
Date: Fri, 15 Mar 2024 15:23:42 +0200
Subject: [PATCH 1/8] Apply review comments. Add debug support
---
Dockerfile | 6 +-
Makefile | 27 +++-
README.md | 22 +---
VERSION | 2 +-
example/custom-metrics-deployment.yaml | 19 ++-
example/custom-metrics-service.yaml | 7 +-
example/rbac.yaml | 2 +-
go.mod | 13 +-
hack/gardener-util/tools.mk | 2 +-
pkg/app/cli_options.go | 2 +-
pkg/ha/ha_service.go | 13 +-
pkg/ha/ha_service_test.go | 3 +
pkg/input/controller/pod/predicate.go | 4 +-
pkg/input/controller/secret/actuator.go | 2 +-
pkg/input/controller/secret/predicate.go | 2 +-
pkg/input/controller/secret/predicate_test.go | 6 +-
pkg/input/input_data_service_test.go | 5 +
pkg/input/metrics_scraper/pacemaker.go | 2 +-
pkg/input/metrics_scraper/pacemaker_test.go | 13 ++
.../metrics_scraper/scrape_queue_test.go | 23 ++++
pkg/input/metrics_scraper/scraper_test.go | 22 ++++
pkg/metrics_provider/metrics_provider.go | 2 +-
.../metrics_provider_service_test.go | 1 +
pkg/metrics_provider/metrics_provider_test.go | 5 +
pkg/util/gardener/options_test.go | 3 +
pkg/util/gardener/util.go | 4 +-
pkg/util/gardener/util_test.go | 10 +-
skaffold.yaml | 115 ++++++++++++++++++
28 files changed, 270 insertions(+), 67 deletions(-)
create mode 100644 skaffold.yaml
diff --git a/Dockerfile b/Dockerfile
index c598f4c6..5aea163e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,7 +4,6 @@ FROM golang:1.19.9 AS builder
WORKDIR /go/src/github.com/gardener/gardener-custom-metrics
COPY . .
RUN make install
-# RUN CGO_ENABLED=0 GO111MODULE=on GOFLAGS=-mod=vendor go build -a -o gardener-custom-metrics.exe cmd/main.go
############# base image # TODO: Andrey: P1: Move to distroless
FROM alpine:3.18.0 AS base
@@ -13,6 +12,5 @@ FROM alpine:3.18.0 AS base
FROM base AS gardener-custom-metrics
WORKDIR /
-COPY --from=builder /go/bin/gardener-custom-metrics /gardener-custom-metrics.exe
-# COPY --from=builder /go/src/github.com/gardener/gardener-custom-metrics/gardener-custom-metrics.exe .
-ENTRYPOINT ["/gardener-custom-metrics.exe"]
+COPY --from=builder /go/bin/gardener-custom-metrics /gardener-custom-metrics
+ENTRYPOINT ["/gardener-custom-metrics"]
diff --git a/Makefile b/Makefile
index 91830331..cb156418 100644
--- a/Makefile
+++ b/Makefile
@@ -12,9 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+BUILD_DATE := $(shell date '+%Y-%m-%dT%H:%M:%S%z' | sed 's/\([0-9][0-9]\)$$/:\1/g')
NAME := gardener-custom-metrics
-# IMAGE_REGISTRY_URI := eu.gcr.io/gardener-project/gardener/$(NAME)
-IMAGE_REGISTRY_URI := eu.gcr.io/sap-se-gcp-scp-k8s/$(NAME)
+IMAGE_REGISTRY_URI := eu.gcr.io/gardener-project/gardener
+# IMAGE_REGISTRY_URI := eu.gcr.io/sap-se-gcp-scp-k8s/$(NAME)
REPO_ROOT := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
VERSION := $(shell cat "$(REPO_ROOT)/VERSION")
EFFECTIVE_VERSION := $(VERSION)-$(shell git rev-parse HEAD)
@@ -30,6 +31,7 @@ ifneq ($(strip $(shell git status --porcelain 2>/dev/null)),)
EFFECTIVE_VERSION := $(EFFECTIVE_VERSION)-dirty
endif
+LD_FLAGS_DEBUG := "$(shell EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) $(REPO_ROOT)/hack/gardener-util/get-build-ld-flags.sh k8s.io/component-base $(REPO_ROOT)/VERSION $(EXTENSION_PREFIX)-$(NAME))"
LD_FLAGS := "-w $(shell EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) $(REPO_ROOT)/hack/gardener-util/get-build-ld-flags.sh k8s.io/component-base $(REPO_ROOT)/VERSION $(EXTENSION_PREFIX)-$(NAME))"
TOOLS_DIR := $(REPO_ROOT)/hack/gardener-util/tools
@@ -136,3 +138,24 @@ verify: check check-docforge format test
.PHONY: verify-extended
verify-extended: check-generate check check-docforge format test test-cov test-clean
+
+# skaffold dev and debug clean up deployed modules by default, disable this
+debug: export SKAFFOLD_CLEANUP = false
+# Artifacts might be already built when you decide to start debugging.
+# However, these artifacts do not include the gcflags which `skaffold debug` sets automatically, so delve would not work.
+# Disabling the skaffold cache for debugging ensures that you run artifacts with gcflags required for debugging.
+debug: export SKAFFOLD_CACHE_ARTIFACTS = false
+
+debug: export SOURCE_DATE_EPOCH = $(shell date -d $(BUILD_DATE) +%s)
+
+.PHONY: debug
+debug: $(SKAFFOLD)
+ @echo "LD_FLAGS: $(LD_FLAGS_DEBUG)"
+ @LD_FLAGS=$(LD_FLAGS) $(SKAFFOLD) debug
+ # TODO: Andrey: P1: code cleanup
+ # export SKAFFOLD_DEFAULT_REPO = localhost:5001
+ # export SKAFFOLD_PUSH = true
+
+ # skaffold dev triggers new builds and deployments immediately on file changes by default,
+ # this is too heavy in a large project like gardener, so trigger new builds and deployments manually instead.
+ # gardener%dev gardenlet%dev operator-dev: export SKAFFOLD_TRIGGER = manual
diff --git a/README.md b/README.md
index f57ab13e..8fdafd8e 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,6 @@
-pkg directory:
-```
-├── input - Takes care of source data: tracks seed's k8s contents, scrapes ShootKapis
-│ ├── controller
-│ │ ├── ...
-│ │ ├── pod
-│ │ │ └── ...
-│ │ └── secret
-│ │ └── ...
-│ ├── input_data_registry - Repository for the metrics source data
-│ │ └── input_data_registry.go
-│ └── input_data_service.go - Primary responsible for providing input data
-└── metrics_provider_service - Serves k8s metrics via HTTP
- ├── metrics_provider.go - Implements the provider interface required by the metrics server library
- └── metrics_provider_service.go - Primary responsible for serving K8s metrics
-```
\ No newline at end of file
+# gardener-custom-metrics
+[](https://reuse.software/)
+## Overview
+The `gardener-custom-metrics` component operates as a K8s API service, adding functionality to the seed kube-apiserver.
+It periodically scrapes the metrics endpoints of all shoot kube-apiserver pods on the seed. It implements the K8s custom
+metrics API and provides K8s metrics specific to Gardener, based on custom calculations.
diff --git a/VERSION b/VERSION
index 0a90cf07..2787740c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-v0.10.7-dev
\ No newline at end of file
+v0.10.11-dev
\ No newline at end of file
diff --git a/example/custom-metrics-deployment.yaml b/example/custom-metrics-deployment.yaml
index de158b5c..ee7edc56 100644
--- a/example/custom-metrics-deployment.yaml
+++ b/example/custom-metrics-deployment.yaml
@@ -1,7 +1,9 @@
apiVersion: apps/v1
kind: Deployment
metadata:
- name: gardener-custom-metrics
+ labels:
+ app: gardener-custom-metrics
+ name: gardener-custom-metrics-debug
namespace: garden
spec:
replicas: 1
@@ -9,23 +11,21 @@ spec:
matchLabels:
app: gardener-custom-metrics
gardener.cloud/role: gardener-custom-metrics
- resources.gardener.cloud/managed-by-xxx: gardener
+ resources.gardener.cloud/managed-by: gardener
template:
metadata:
labels:
app: gardener-custom-metrics
gardener.cloud/role: gardener-custom-metrics
- resources.gardener.cloud/managed-by-xxx: gardener
+ resources.gardener.cloud/managed-by: gardener
networking.gardener.cloud/from-seed: allowed
networking.gardener.cloud/to-dns: allowed
- networking.gardener.cloud/to-seed-apiserver: allowed
+ networking.gardener.cloud/to-runtime-apiserver: allowed
networking.resources.gardener.cloud/to-all-shoots-kube-apiserver-tcp-443: allowed
networking.gardener.cloud/to-apiserver: allowed
-
spec:
containers:
- - command:
- - ./gardener-custom-metrics.exe
+ - args:
- --secure-port=6443
- --tls-cert-file=/var/run/secrets/gardener.cloud/tls/tls.crt
- --tls-private-key-file=/var/run/secrets/gardener.cloud/tls/tls.key
@@ -44,7 +44,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- image: eu.gcr.io/sap-se-gcp-scp-k8s/gardener-custom-metrics/gardener-custom-metrics:v0.10.4-dev
+ image: eu.gcr.io/gardener-project/gardener/gardener-custom-metrics:v0.10.9-dev
imagePullPolicy: IfNotPresent
name: gardener-custom-metrics
ports:
@@ -72,13 +72,12 @@ spec:
securityContext:
seccompProfile:
type: RuntimeDefault
- serviceAccount: gardener-custom-metrics
serviceAccountName: gardener-custom-metrics
terminationGracePeriodSeconds: 30
volumes:
- name: gardener-custom-metrics-tls
secret:
- secretName: gardener-custom-metrics-tls
+ secretName: gardener-custom-metrics-tls-121d8b86 # TODO: Andrey: P1: This is dynamic
- name: kube-api-access-gardener
projected:
defaultMode: 420
diff --git a/example/custom-metrics-service.yaml b/example/custom-metrics-service.yaml
index 52e62965..270f00e8 100644
--- a/example/custom-metrics-service.yaml
+++ b/example/custom-metrics-service.yaml
@@ -13,11 +13,10 @@ spec:
protocol: TCP
targetPort: 6443
publishNotReadyAddresses: true
- selector:
- app: gardener-custom-metrics
- gardener.cloud/role: gardener-custom-metrics
- resources.gardener.cloud/managed-by-xxx: gardener
sessionAffinity: None
type: ClusterIP
+ # This service intentionally does not contain a pod selector. As a result, KCM does not perform any endpoint management.
+ # Endpoint management is instead done by the gardener-custom-metrics leader instance, which ensures a single endpoint,
+ # directing all traffic to the leader.
status:
loadBalancer: {}
\ No newline at end of file
diff --git a/example/rbac.yaml b/example/rbac.yaml
index b571a43e..e080bd6e 100644
--- a/example/rbac.yaml
+++ b/example/rbac.yaml
@@ -93,7 +93,7 @@ rules:
- ""
resources:
- secrets
- # resourceNames: [ "ca", "shoot-access-prometheus" ] # TODO: Andrey: P1: How to write code so we can use name-based restriction?
+ # resourceNames: [ "ca", "shoot-access-gardener-custom-metrics" ] # TODO: Andrey: P1: How to write code so we can use name-based restriction?
verbs:
- get
- list
diff --git a/go.mod b/go.mod
index f438f0a7..2b535378 100644
--- a/go.mod
+++ b/go.mod
@@ -1,14 +1,17 @@
module github.com/gardener/gardener-custom-metrics
-go 1.19
+go 1.21
require (
github.com/go-logr/logr v1.2.4
- github.com/spf13/cobra v1.6.1
+ github.com/onsi/ginkgo/v2 v2.11.0
+ github.com/onsi/gomega v1.27.8
+ github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
go.uber.org/zap v1.21.0
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
golang.org/x/time v0.3.0
+ golang.org/x/tools v0.9.3
k8s.io/api v0.23.17 // v0.24.0 // v0.24.4
k8s.io/apimachinery v0.23.17 // v0.24.0 // v0.24.4
k8s.io/apiserver v0.23.17 // v0.24.4
@@ -22,12 +25,6 @@ require (
sigs.k8s.io/metrics-server v0.6.4
)
-require (
- github.com/onsi/ginkgo/v2 v2.11.0
- github.com/onsi/gomega v1.27.8
- golang.org/x/tools v0.9.3
-)
-
require (
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/PuerkitoBio/purell v1.2.0 // indirect
diff --git a/hack/gardener-util/tools.mk b/hack/gardener-util/tools.mk
index a90a90cc..76572d15 100755
--- a/hack/gardener-util/tools.mk
+++ b/hack/gardener-util/tools.mk
@@ -61,7 +61,7 @@ HELM_VERSION ?= v3.11.2
KIND_VERSION ?= v0.18.0
KUBECTL_VERSION ?= v1.24.11
PROTOC_VERSION ?= 23.4
-SKAFFOLD_VERSION ?= v2.2.0
+SKAFFOLD_VERSION ?= v2.9.0
YQ_VERSION ?= v4.31.2
export TOOLS_BIN_DIR := $(TOOLS_BIN_DIR)
diff --git a/pkg/app/cli_options.go b/pkg/app/cli_options.go
index f6ed278a..db25a2af 100644
--- a/pkg/app/cli_options.go
+++ b/pkg/app/cli_options.go
@@ -139,7 +139,7 @@ func (c *CLIConfig) ManagerOptions() manager.Options {
// TODO: Andrey: P2: Enable after switching from prometheus' secret (which does not have 'name' label), to ours.
// It will prevent retrieving and caching unnecessary secrets.
//
- //nameRequirement, _ := labels.NewRequirement("name", selection.In, []string{"ca", "shoot-access-prometheus"})
+ //nameRequirement, _ := labels.NewRequirement("name", selection.In, []string{"ca", "shoot-access-gardener-custom-metrics"})
//selector := labels.NewSelector().Add(*nameRequirement)
//opts.NewCache = cache.BuilderWithOptions(cache.Options{
// SelectorsByObject: cache.SelectorsByObject{
diff --git a/pkg/ha/ha_service.go b/pkg/ha/ha_service.go
index da190924..bab4e163 100644
--- a/pkg/ha/ha_service.go
+++ b/pkg/ha/ha_service.go
@@ -8,6 +8,7 @@ import (
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/api/errors"
"sigs.k8s.io/controller-runtime/pkg/client"
ctlmgr "sigs.k8s.io/controller-runtime/pkg/manager"
@@ -16,7 +17,8 @@ import (
)
// HAService is the main type of the package. It takes care of concerns related to running the application in high
-// availability mode.
+// availability mode. When running in active/passive replication mode, HAService ensures that all requests go to the
+// active replica.
// HAService implements [ctlmgr.Runnable].
// For information about individual fields, see NewHAService().
type HAService struct {
@@ -61,10 +63,15 @@ func (ha *HAService) setEndpoints(ctx context.Context) error {
endpoints := corev1.Endpoints{}
err := ha.manager.GetClient().Get(ctx, client.ObjectKey{Namespace: ha.namespace, Name: app.Name}, &endpoints)
if err != nil {
- return fmt.Errorf("updating the service endpoint to point to the new leader: retrieving endpoints: %w", err)
+ if !errors.IsNotFound(err) {
+ return fmt.Errorf("updating the service endpoint to point to the new leader: retrieving endpoints: %w", err)
+ }
+
+ endpoints.ObjectMeta.Namespace = ha.namespace
+ endpoints.ObjectMeta.Name = app.Name
}
- endpoints.ObjectMeta.Labels = map[string]string{"app": app.Name}
+ endpoints.ObjectMeta.Labels = map[string]string{"app": app.Name, "resources.gardener.cloud/managed-by": "gardener"}
endpoints.Subsets = []corev1.EndpointSubset{{
Addresses: []corev1.EndpointAddress{{IP: ha.servingIPAddress}},
Ports: []corev1.EndpointPort{{Port: int32(ha.servingPort), Protocol: "TCP"}},
diff --git a/pkg/ha/ha_service_test.go b/pkg/ha/ha_service_test.go
index 47b522f1..6290313c 100644
--- a/pkg/ha/ha_service_test.go
+++ b/pkg/ha/ha_service_test.go
@@ -52,6 +52,7 @@ var _ = Describe("HAService", func() {
Expect(actual.Subsets[0].Ports).To(HaveLen(1))
Expect(actual.Subsets[0].Ports[0].Port).To(Equal(int32(testPort)))
})
+
It("should wait and retry with exponential backoff, if the service endpoints are missing, and succeed "+
"once they appear", func() {
@@ -98,6 +99,7 @@ var _ = Describe("HAService", func() {
Expect(actual.Subsets[0].Addresses).To(HaveLen(1))
Expect(actual.Subsets[0].Addresses[0].IP).To(Equal(testIPAddress))
})
+
It("should immediately abort retrying, if the context gets canceled", func() {
// Arrange
manager := testutil.NewFakeManager()
@@ -129,6 +131,7 @@ var _ = Describe("HAService", func() {
err = manager.GetClient().Get(context.Background(), kclient.ObjectKey{Namespace: testNs, Name: app.Name}, &actual)
Expect(err).To(HaveOccurred())
})
+
It("should use exponential backoff", func() {
// Arrange
diff --git a/pkg/input/controller/pod/predicate.go b/pkg/input/controller/pod/predicate.go
index 3b59607a..ef90b2ce 100644
--- a/pkg/input/controller/pod/predicate.go
+++ b/pkg/input/controller/pod/predicate.go
@@ -44,7 +44,7 @@ func isPodLabeledAsShootKapi(pod client.Object) bool {
}
func isKapiPod(pod *corev1.Pod) bool {
- return gutil.IsShootCPNamespace(pod.Namespace) && isPodLabeledAsShootKapi(pod)
+ return gutil.IsShootNamespace(pod.Namespace) && isPodLabeledAsShootKapi(pod)
}
// Is the object a shoot CP pod, containing one of shoot's kube-apiserver instances
@@ -74,7 +74,7 @@ func (p *podPredicate) Update(e event.UpdateEvent) (result bool) {
p.log.Error(nil, "Update event has no new object")
return false
}
- if !gutil.IsShootCPNamespace(e.ObjectNew.GetNamespace()) {
+ if !gutil.IsShootNamespace(e.ObjectNew.GetNamespace()) {
return false
}
diff --git a/pkg/input/controller/secret/actuator.go b/pkg/input/controller/secret/actuator.go
index e634d210..9773abcb 100644
--- a/pkg/input/controller/secret/actuator.go
+++ b/pkg/input/controller/secret/actuator.go
@@ -30,7 +30,7 @@ import (
const (
secretNameCA = "ca"
- secretNameAccessToken = "shoot-access-prometheus"
+ secretNameAccessToken = "shoot-access-gardener-custom-metrics"
)
// The secret actuator acts upon shoot secrets, maintaining the information necessary to scrape
diff --git a/pkg/input/controller/secret/predicate.go b/pkg/input/controller/secret/predicate.go
index 75cf142b..2a79cea3 100644
--- a/pkg/input/controller/secret/predicate.go
+++ b/pkg/input/controller/secret/predicate.go
@@ -49,7 +49,7 @@ func (p *secretPredicate) isRelevantSecret(obj client.Object) bool {
return false
}
- return gutil.IsShootCPNamespace(secret.Namespace) &&
+ return gutil.IsShootNamespace(secret.Namespace) &&
(secret.Name == secretNameCA || secret.Name == secretNameAccessToken)
}
diff --git a/pkg/input/controller/secret/predicate_test.go b/pkg/input/controller/secret/predicate_test.go
index b5877896..99c594c7 100644
--- a/pkg/input/controller/secret/predicate_test.go
+++ b/pkg/input/controller/secret/predicate_test.go
@@ -29,7 +29,7 @@ var _ = Describe("input.controler.secret.predicate", func() {
It("should return true if the event target is a shoot control plane secret, containing the shoot's "+
"kube-apiserver CA certificate or metrics scraping access token", func() {
- for _, name := range []string{"ca", "shoot-access-prometheus"} {
+ for _, name := range []string{"ca", "shoot-access-gardener-custom-metrics"} {
// Arrange
predicate := NewPredicate(logr.Discard())
oldSecret := newTestSecret(name)
@@ -47,7 +47,7 @@ var _ = Describe("input.controler.secret.predicate", func() {
}
})
It("should return false if the event target is not in a shoot namespace", func() {
- for _, name := range []string{"ca", "shoot-access-prometheus"} {
+ for _, name := range []string{"ca", "shoot-access-gardener-custom-metrics"} {
// Arrange
predicate := NewPredicate(logr.Discard())
oldSecret := newTestSecret(name)
@@ -66,7 +66,7 @@ var _ = Describe("input.controler.secret.predicate", func() {
}
})
It("should return true if the event target is not a secret", func() {
- for _, name := range []string{"ca", "shoot-access-prometheus"} {
+ for _, name := range []string{"ca", "shoot-access-gardener-custom-metrics"} {
// Arrange
predicate := NewPredicate(logr.Discard())
oldSecret := newTestSecret(name)
diff --git a/pkg/input/input_data_service_test.go b/pkg/input/input_data_service_test.go
index 27815ce5..10498811 100644
--- a/pkg/input/input_data_service_test.go
+++ b/pkg/input/input_data_service_test.go
@@ -54,6 +54,7 @@ var _ = Describe("input.inputDataService", func() {
Expect(ids.inputDataRegistry.(*input_data_registry.FakeInputDataRegistry).MinSampleGap).To(Equal(testMinSampleGap))
})
})
+
Describe("DataSource", func() {
It("should point to the same registry at the one supplied to the scraper", func() {
// Arrange
@@ -69,6 +70,7 @@ var _ = Describe("input.inputDataService", func() {
Expect(kapis[0].PodName()).To(Equal("pod"))
})
})
+
Describe("AddToManager", func() {
It("should add the scraper, pod controller, and secret controller to the manager", func() {
// Arrange
@@ -83,6 +85,7 @@ var _ = Describe("input.inputDataService", func() {
Expect(testutil.GetRunnables[*metrics_scraper.Scraper](fm)).To(HaveLen(1))
Expect(testutil.GetRunnables[controller.Controller](fm)).To(HaveLen(2))
})
+
It("should add apimachinery runtime types scheme to the manager", func() {
// Arrange
ids, _ := newInputDataService()
@@ -100,6 +103,7 @@ var _ = Describe("input.inputDataService", func() {
Expect(fm.Scheme.Recognizes(gvk)).To(BeTrue())
}
})
+
It("should create a new data registry and pass it to the scraper", func() {
// Arrange
ids, _ := newInputDataService()
@@ -124,6 +128,7 @@ var _ = Describe("input.inputDataService", func() {
Expect(registryPassedToScraperConstructor).NotTo(BeNil())
Expect(registryPassedToScraperConstructor == ids.inputDataRegistry).To(BeTrue())
})
+
It("should configure the scraper with the specified scrape period and flow control period", func() {
// Arrange
ids, _ := newInputDataService()
diff --git a/pkg/input/metrics_scraper/pacemaker.go b/pkg/input/metrics_scraper/pacemaker.go
index dcda7609..a4248c32 100644
--- a/pkg/input/metrics_scraper/pacemaker.go
+++ b/pkg/input/metrics_scraper/pacemaker.go
@@ -53,7 +53,7 @@ type pacemakerImpl struct {
// newPacemaker creates a rate limiter which maintains the rate of some repeating operation between a set minimum and
// maximum.
-// Withing the space between min and max, the exact rate is determined depending on whether the client is eager to
+// Within the space between min and max, the exact rate is determined depending on whether the client is eager to
// perform the operation. Eager requests are governed by "no more than max rate". Non-eager requests follow a
// "no less than min rate" schedule.
//
diff --git a/pkg/input/metrics_scraper/pacemaker_test.go b/pkg/input/metrics_scraper/pacemaker_test.go
index dfa965af..e35d42ed 100644
--- a/pkg/input/metrics_scraper/pacemaker_test.go
+++ b/pkg/input/metrics_scraper/pacemaker_test.go
@@ -51,6 +51,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
Expect(pm.config.RateDebtLimit).To(Equal(creationConfig.RateDebtLimit))
Expect(pm.config.RateSurplusLimit).To(Equal(creationConfig.RateSurplusLimit))
})
+
It("should create a pacemaker with zero debt", func() {
// Arrange
creationConfig := &pacemakerConfig{
@@ -66,6 +67,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
// Assert
Expect(pm.GetScrapePermission(false)).To(BeFalse())
})
+
It("should create a pacemaker with zero surplus", func() {
// Arrange
creationConfig := &pacemakerConfig{
@@ -81,6 +83,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
Expect(pm.GetScrapePermission(true)).To(BeFalse())
})
})
+
Describe("UpdateRate", func() {
It("should write the specified MinRate value to the pacemaker's configuration", func() {
// Arrange
@@ -92,6 +95,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
// Assert
Expect(pm.config.MinRate).To(Equal(float64(777)))
})
+
It("should write the specified RateDebtLimit value to the pacemaker's configuration", func() {
// Arrange
pm := newTestPacemakerWithTestWorthyConfiguration()
@@ -103,6 +107,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
Expect(pm.config.RateDebtLimit).To(Equal(777))
})
})
+
Describe("GetScrapePermission", func() {
Context("if the scrape is eager", func() {
Context("starting from a state of zero debt and surplus", func() {
@@ -118,6 +123,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
Expect(pm.GetScrapePermission(true)).To(BeFalse())
})
})
+
Context("starting from a state of exhausted surplus", func() {
It("should grant permission to as many calls, as correspond to MaxRate, and deny the next one", func() {
// Arrange
@@ -145,6 +151,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
Expect(pm.GetScrapePermission(true)).To(BeFalse())
})
})
+
Context("starting from a state of high debt", func() {
It("should allow RateSurplusLimit immediate calls, then deny the next call", func() {
@@ -168,6 +175,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
})
})
})
+
Context("if the scrape is not eager", func() {
Context("starting from a state of zero debt", func() {
It("after a period of inactivity which does not exceed the debt limit, should allow as many "+
@@ -194,6 +202,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
}
Expect(pm.GetScrapePermission(false)).To(BeFalse())
})
+
It("after a period of inactivity which exceeds the debt limit, should allow RateDebtLimit "+
"immediate calls, and deny the next one", func() {
@@ -218,6 +227,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
}
Expect(pm.GetScrapePermission(false)).To(BeFalse())
})
+
It("if time has not passed, should not allow any immediate calls", func() {
// Arrange
pm := newTestPacemaker(2, 4, 20, 10)
@@ -230,6 +240,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
})
})
})
+
Context("starting from a state of high debt", func() {
It("should allow as many immediate calls, as the value of the initial debt, if they don't exceed "+
"MaxRate, and then deny the next call if it is not eager", func() {
@@ -257,6 +268,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
Expect(pm.GetScrapePermission(false)).To(BeFalse())
}
})
+
It("should still be limited to MaxRate", func() {
// Arrange
secondsElapsed := 2
@@ -292,6 +304,7 @@ var _ = Describe("input.metrics_scraper.pacemakerImpl", func() {
}
})
})
+
It("should perform as expected in one complex scenario", func() {
// This one last test case does not follow the good practice of simplicity and testing just one thing.
// It uses a complex scenario, in attempt to catch potential issues missed by the above simple cases.
diff --git a/pkg/input/metrics_scraper/scrape_queue_test.go b/pkg/input/metrics_scraper/scrape_queue_test.go
index 37145a23..ecace90d 100644
--- a/pkg/input/metrics_scraper/scrape_queue_test.go
+++ b/pkg/input/metrics_scraper/scrape_queue_test.go
@@ -126,6 +126,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
Expect(pm.RateDebtLimit.Load()).To(BeZero())
Expect(int(pm.RateSurplusLimit.Load())).To(Equal(surplusLimit))
})
+
It("should subscribe the scrapeQueue for InputDataRegistry events, including events for objects already in the registry", func() {
// Arrange
@@ -138,6 +139,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
Expect(idr.ShouldWatcherNotifyOfPreexisting).To(BeTrue())
})
})
+
Describe("onKapiUpdated", func() {
Context("if the event is an add", func() {
It("should update the pacemaker with MinRate = ScrapeTargetCount / ScrapePeriod, DebtLimit = 0", func() {
@@ -159,6 +161,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
pacemaker.RateSurplusLimit.Load() == surplusLimit
}).Should(BeTrue())
})
+
It("should add the new target to the queue", func() {
// Arrange
sq, idr, _ := newTestScrapeQueue(1 * time.Minute)
@@ -179,6 +182,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
}).Should(BeTrue())
})
})
+
Context("if the event is a remove", func() {
It("should update the pacemaker with MinRate = ScrapeTargetCount / ScrapePeriod, DebtLimit = 0", func() {
// Arrange
@@ -202,6 +206,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
pacemaker.RateSurplusLimit.Load() == surplusLimit
}).Should(BeTrue())
})
+
It("should remove the new target from the queue", func() {
// Arrange
sq, idr, _ := newTestScrapeQueue(1 * time.Minute)
@@ -225,6 +230,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
return next != nil && next.PodName == podName+"2"
}).Should(BeTrue())
})
+
It("should have no effect if the target is missing", func() {
// Arrange
sq, idr, _ := newTestScrapeQueue(1 * time.Minute)
@@ -244,6 +250,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
}).Should(BeTrue())
})
})
+
Context("if the event is of unknown type", func() {
It("should have no effect", func() {
// Arrange
@@ -268,6 +275,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
})
})
})
+
Describe("GetNext", func() {
It("should return nil if the queue contains only targets which are missing from the registry", func() {
// Arrange
@@ -282,6 +290,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
// Assert
Expect(result).To(BeNil())
})
+
It("on a queue with multiple targets and a newly added target, should immediately request an eager scrape for the new target", func() {
// Arrange
sq, idr, pm := newTestScrapeQueue(1 * time.Minute)
@@ -300,6 +309,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
// Assert
Expect(next.PodName).To(Equal(podName + "2"))
})
+
It("should request a scrape operation from the scrape client, if the pacemaker grants permission", func() {
// Arrange
sq, idr, _ := newTestScrapeQueue(1 * time.Minute)
@@ -313,6 +323,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
// Assert
Expect(next).To(Not(BeNil()))
})
+
It("should not request a scrape operation from the scrape client, if the pacemaker denies permission", func() {
// Arrange
sq, idr, pm := newTestScrapeQueue(1 * time.Minute)
@@ -327,6 +338,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
// Assert
Expect(next).To(BeNil())
})
+
It("upon successful scrape, should record the scrape time in the data registry", func() {
// Arrange
sq, idr, _ := newTestScrapeQueue(1 * time.Minute)
@@ -341,6 +353,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
// Assert
Expect(idr.GetKapiData(nsName, podName).LastMetricsScrapeTime).To(Equal(testutil.NewTimeNowStub(2, 0, 0)()))
})
+
It("should not change the last scrape time for the Kapi, if the pacemaker denies permission", func() {
// Arrange
sq, idr, pm := newTestScrapeQueue(1 * time.Minute)
@@ -357,6 +370,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
// Assert
Expect(idr.GetKapiData(nsName, podName).LastMetricsScrapeTime).To(Equal(initialScrapeTime))
})
+
It("should return targets in a strictly cyclic order", func() {
// Arrange
sq, idr, _ := newTestScrapeQueue(1 * time.Minute)
@@ -384,6 +398,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
}
}
})
+
It("should return nil if there are only ineligible targets at the time of the call", func() {
// Arrange
sq, idr, pm := newTestScrapeQueue(1 * time.Minute)
@@ -402,6 +417,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
// Assert
Expect(next).To(BeNil())
})
+
It("should return nil, if the queue is empty", func() {
// Arrange
sq, _, _ := newTestScrapeQueue(1 * time.Minute)
@@ -414,6 +430,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
// Assert
Expect(next).To(BeNil())
})
+
It("should request an eager/lazy scrape from the pacemaker, depending on whether one scrape period has "+
"elapsed since the time the next target was last scraped", func() {
@@ -441,6 +458,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
Expect(sq.GetNext()).NotTo(BeNil()) // Eager again
Expect(sq.GetNext()).To(BeNil()) // Not eager
})
+
It("should skip targets which are missing from the registry, and return the first target which is not missing", func() {
// Arrange
sq, idr, pm := newTestScrapeQueue(1 * time.Minute)
@@ -462,6 +480,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
Expect(sq.GetNext()).To(BeNil()) // This should be back to the first target, thus not eager
})
})
+
Describe("DueCount", func() {
It("on an empty queue should return zero", func() {
// Arrange
@@ -473,6 +492,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
// Assert
Expect(due).To(BeZero())
})
+
It("should return zero if the queue contains only targets which are missing from the registry", func() {
// Arrange
sq, idr, _ := newTestScrapeQueue(1 * time.Minute)
@@ -487,6 +507,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
// Assert
Expect(due).To(BeZero())
})
+
It("should count targets exactly after one scraping period passes from their last scrape. It should count "+
"targets which have never been scraped, if, and only if the excludeUnscraped parameter is false", func() {
@@ -519,6 +540,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
Expect(sq.DueCount(thirdScrapeTime, true)).To(Equal(20))
})
})
+
Describe("Close", func() {
It("should terminate the scrapeQueue's subscription to InputDataRegistry events", func() {
// Arrange
@@ -531,6 +553,7 @@ var _ = Describe("input.metrics_scraper.scrapeQueueImpl", func() {
// Assert
Expect(idr.Watcher).To(BeNil())
})
+
It("should terminate the processing of InputDataRegistry events", func() {
// Arrange
sq, idr, _ := newTestScrapeQueue(1 * time.Minute)
diff --git a/pkg/input/metrics_scraper/scraper_test.go b/pkg/input/metrics_scraper/scraper_test.go
index 26bb6eb3..87f9aa85 100644
--- a/pkg/input/metrics_scraper/scraper_test.go
+++ b/pkg/input/metrics_scraper/scraper_test.go
@@ -122,6 +122,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Expect(scraper.queue.(*scrapeQueueImpl).scrapePeriod).To(Equal(scrapePeriod))
})
})
+
Describe("Start", func() {
It("should poll until context cancelled, and stop polling when the context is cancelled", func() {
// Arrange
@@ -160,6 +161,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Consistently(isRunning.Load).Should(BeFalse())
abortChan <- true
})
+
It("should not exit before all workers exit", func() {
// Arrange
scraper, idr, sq, _, ticker, _ := newTestScraper()
@@ -187,6 +189,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
scraper.activeWorkerCount.Add(-1)
Eventually(isRunning.Load).Should(BeFalse())
})
+
It("should close scrape queue before exiting", func() {
// Arrange
scraper, idr, sq, _, _, _ := newTestScraper()
@@ -206,6 +209,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Eventually(isRunning.Load).Should(BeFalse())
Expect(sq.IsClosed()).To(BeTrue())
})
+
It("upon first invocation with multiple targets, should start 2 workers, then, if no scrapes are "+
"recorded, double upon each ticker tick, until it gets capped to the number of targets", func() {
@@ -231,6 +235,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Consistently(metrics.WorkerProcCount.Load).Should(Equal(expected))
}
})
+
It("if last shift managed to scrape all of its targets, should attempt scraping with one less worker", func() {
// Arrange
scraper, idr, sq, _, ticker, metrics := newTestScraper()
@@ -252,6 +257,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Eventually(metrics.WorkerProcCount.Load).Should(Equal(int32(9)))
})
+
It("if last shift failed to scrape all of its targets, should increase worker count proportionally to "+
"last shift's throughput and current due target count", func() {
@@ -271,6 +277,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Eventually(metrics.WorkerProcCount.Load).Should(Equal(int32(6)))
Consistently(metrics.WorkerProcCount.Load).Should(Equal(int32(6)))
})
+
It("should consider leftover targets from last shift, when calculating this shift's worker count", func() {
// Arrange
// Last shift scraped 1 out of 6 targets with 6 workers. This shift has 3 new targets and 5 leftover
@@ -288,6 +295,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Eventually(metrics.WorkerProcCount.Load).Should(Equal(int32(8)))
Consistently(metrics.WorkerProcCount.Load).Should(Equal(int32(8)))
})
+
It("should respect maxShiftWorkerCount", func() {
// Arrange
// Last shift scraped 1 out of 6 targets with 6 workers. This shift has 10 new targets and 5 leftover
@@ -305,6 +313,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Eventually(metrics.WorkerProcCount.Load).Should(Equal(int32(10)))
Consistently(metrics.WorkerProcCount.Load).Should(Equal(int32(10)))
})
+
It("should respect minShiftWorkerCount", func() {
// Arrange
scraper, idr, sq, _, ticker, metrics := newTestScraper()
@@ -328,6 +337,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Eventually(metrics.WorkerProcCount.Load).Should(Equal(int32(1)))
Consistently(metrics.WorkerProcCount.Load).Should(Equal(int32(1)))
})
+
It("if the queue is empty, should slowly reduce the number of workers to 1", func() {
// Arrange
scraper, idr, sq, _, ticker, metrics := newTestScraper()
@@ -349,6 +359,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Eventually(scraper.activeWorkerCount.Load).Should(BeZero())
}
})
+
It("should respect maxActiveWorkerCount", func() {
// Arrange
scraper, idr, sq, _, ticker, metrics := newTestScraper()
@@ -367,6 +378,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Eventually(metrics.WorkerProcCount.Load).Should(Equal(int32(9)))
Consistently(metrics.WorkerProcCount.Load).Should(Equal(int32(9)))
})
+
It("should apply the specified scrapeFlowControlPeriod to the ticker it uses", func() {
// Arrange
schedulingPeriod := 100 * time.Millisecond
@@ -386,6 +398,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
// Assert
Eventually(fakeTicker.Period.Load).Should(Equal(int64(schedulingPeriod)))
})
+
It("should schedule scrape shifts when and only when the ticket ticks", func() {
// Arrange
scraper, idr, sq, _, ticker, metrics := newTestScraper()
@@ -406,6 +419,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
}
})
})
+
Describe("workerProc", func() {
It("polls the targets returned by GetNext(),until the context is cancelled", func() {
// Arrange
@@ -425,6 +439,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Consistently(client.WasScraped.Load).Should(BeFalse())
Expect(scraper.activeWorkerCount.Load()).To(BeZero())
})
+
It("if context has not been cancelled, polls the queue until GetNext() returns nil", func() {
// Arrange
scraper, idr, sq, client, _, _ := newTestScraper()
@@ -443,6 +458,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Consistently(client.WasScraped.Load).Should(BeFalse())
Expect(scraper.activeWorkerCount.Load()).To(BeZero())
})
+
It("if context has been cancelled, exits before scraping the queue", func() {
// Arrange
scraper, _, client, _, _ := arrangeWorkerTest()
@@ -456,6 +472,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Consistently(client.WasScraped.Load).Should(BeFalse())
Expect(scraper.activeWorkerCount.Load()).To(BeZero())
})
+
It("should scrape each target returned by the queue", func() {
// Arrange
scraper, idr, sq, _, _, _ := newTestScraper()
@@ -475,6 +492,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Expect(kapi.TotalRequestCountNew).To(Equal(fakeMetricsClientMetricsValue))
}
})
+
Context("when scraping a target", func() {
It("should have no effect if the kapi is missing from the registry", func() {
// Arrange
@@ -492,6 +510,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Expect(client.WasScraped.Load()).To(BeFalse())
Expect(idr.GetKapiData(target.Namespace, target.PodName)).To(BeNil())
})
+
It("should have no effect if the auth secret is missing from the registry", func() {
// Arrange
scraper, idr, client, testMetrics, target := arrangeWorkerTest()
@@ -509,6 +528,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Expect(idr.GetKapiData(target.Namespace, target.PodName).TotalRequestCountNew).To(BeZero())
Expect(idr.GetKapiData(target.Namespace, target.PodName).MetricsTimeNew).To(BeZero())
})
+
It("should have no effect if the CA certificate is missing from the registry", func() {
// Arrange
scraper, idr, client, testMetrics, target := arrangeWorkerTest()
@@ -526,6 +546,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
Expect(idr.GetKapiData(target.Namespace, target.PodName).TotalRequestCountNew).To(BeZero())
Expect(idr.GetKapiData(target.Namespace, target.PodName).MetricsTimeNew).To(BeZero())
})
+
It("should record the resulting metric value in the registry", func() {
// Arrange
scraper, idr, _, _, target := arrangeWorkerTest()
@@ -540,6 +561,7 @@ var _ = Describe("input.metrics_scraper.Scraper", func() {
return idr.GetKapiData(target.Namespace, target.PodName).TotalRequestCountNew
}).Should(Equal(fakeMetricsClientMetricsValue))
})
+
It("should use scrapePeriod / 2 as timeout for individual scrapes", func() {
// Arrange
scraper, _, client, _, _ := arrangeWorkerTest()
diff --git a/pkg/metrics_provider/metrics_provider.go b/pkg/metrics_provider/metrics_provider.go
index 92e5d5f7..ef21ee20 100644
--- a/pkg/metrics_provider/metrics_provider.go
+++ b/pkg/metrics_provider/metrics_provider.go
@@ -119,7 +119,7 @@ func (mp *MetricsProvider) getMetricByPredicate(
metricInfo provider.CustomMetricInfo) (*custom_metrics.MetricValueList, error) {
if metricInfo.Metric != metricName {
- return nil, nil
+ return &custom_metrics.MetricValueList{}, nil
}
kapis := mp.dataSource.GetShootKapis(namespace)
diff --git a/pkg/metrics_provider/metrics_provider_service_test.go b/pkg/metrics_provider/metrics_provider_service_test.go
index d61318e9..737e81f0 100644
--- a/pkg/metrics_provider/metrics_provider_service_test.go
+++ b/pkg/metrics_provider/metrics_provider_service_test.go
@@ -30,6 +30,7 @@ var _ = Describe("MetricsService", func() {
}
})
})
+
Describe("CompleteCLIConfiguration", func() {
It("should create a MetricsProvider based on the specified configuration", func() {
// Arrange
diff --git a/pkg/metrics_provider/metrics_provider_test.go b/pkg/metrics_provider/metrics_provider_test.go
index 13ce45e8..e17aa3bc 100644
--- a/pkg/metrics_provider/metrics_provider_test.go
+++ b/pkg/metrics_provider/metrics_provider_test.go
@@ -45,6 +45,7 @@ var _ = Describe("MetricsProvider", func() {
Expect(err).To(Succeed())
Expect(metricValue).To(BeNil())
})
+
It("should return metrics for the Kapi pod specified by the namespaced name", func() {
// Arrange
idr := input_data_registry.FakeInputDataRegistry{}
@@ -72,6 +73,7 @@ var _ = Describe("MetricsProvider", func() {
Expect(val.DescribedObject.APIVersion).To(Equal("v1"))
Expect(val.DescribedObject.Kind).To(Equal("Pod"))
})
+
It("should respect maxSampleAge", func() {
// Arrange
idr := input_data_registry.FakeInputDataRegistry{}
@@ -97,6 +99,7 @@ var _ = Describe("MetricsProvider", func() {
Expect(valStillGood).NotTo(BeNil())
Expect(valStillGood.DescribedObject.Name).To(Equal(testPodName + "2"))
})
+
It("should respect maxSampleGap", func() {
// Arrange
idr := input_data_registry.FakeInputDataRegistry{}
@@ -123,6 +126,7 @@ var _ = Describe("MetricsProvider", func() {
Expect(valGood.DescribedObject.Name).To(Equal(testPodName))
})
})
+
Describe("GetMetricBySelector", func() {
It("should return nothing if there are no Kapis", func() {
// Arrange
@@ -138,6 +142,7 @@ var _ = Describe("MetricsProvider", func() {
Expect(metricValue).NotTo(BeNil())
Expect(metricValue.Items).To(HaveLen(0))
})
+
It("should return only metrics for Kapi pods which match the selector", func() {
// Arrange
idr := input_data_registry.FakeInputDataRegistry{}
diff --git a/pkg/util/gardener/options_test.go b/pkg/util/gardener/options_test.go
index 607bc3f5..8de441de 100644
--- a/pkg/util/gardener/options_test.go
+++ b/pkg/util/gardener/options_test.go
@@ -60,6 +60,7 @@ var _ = Describe("RESTOptions", func() {
Expect(output.ForwardedKubeconfig).To(Equal(customKubeconfig))
Expect(output.ForwardedMasterUrl).To(Equal(kapiUrl))
})
+
It("should use the specified master URL and fall back to kubeconfig from environment variable", func() {
// Arrange
options, output := newRestOptions()
@@ -74,6 +75,7 @@ var _ = Describe("RESTOptions", func() {
Expect(output.ForwardedKubeconfig).To(Equal(envKubeconfig))
Expect(output.ForwardedMasterUrl).To(Equal(kapiUrl))
})
+
It("should fall back to in-cluster config", func() {
// Arrange
options, output := newRestOptions()
@@ -91,6 +93,7 @@ var _ = Describe("RESTOptions", func() {
Expect(output.ForwardedMasterUrl).To(Equal(inCluster))
Expect(output.ForwardedKubeconfig).To(Equal(inCluster))
})
+
It("should fall back to default kubeconfig location", func() {
// Arrange
options, output := newRestOptions()
diff --git a/pkg/util/gardener/util.go b/pkg/util/gardener/util.go
index 833232a0..e8795e96 100644
--- a/pkg/util/gardener/util.go
+++ b/pkg/util/gardener/util.go
@@ -7,9 +7,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller"
)
-// IsShootCPNamespace determines whether the format of specified name implies that it is a shoot namespace in a seed
+// IsShootNamespace determines whether the format of specified name implies that it is a shoot namespace in a seed
// cluster
-func IsShootCPNamespace(namespace string) bool {
+func IsShootNamespace(namespace string) bool {
return strings.HasPrefix(namespace, "shoot--")
}
diff --git a/pkg/util/gardener/util_test.go b/pkg/util/gardener/util_test.go
index d72e81d4..75420351 100644
--- a/pkg/util/gardener/util_test.go
+++ b/pkg/util/gardener/util_test.go
@@ -6,12 +6,12 @@ import (
)
var _ = Describe("uti/gardener", func() {
- Describe("IsShootCPNamespace", func() {
+ Describe("IsShootNamespace", func() {
It("should work expected on certain predefined values", func() {
- Expect(IsShootCPNamespace("shoot--my-shoot")).To(BeTrue())
- Expect(IsShootCPNamespace("shoot-my-shoot")).To(BeFalse())
- Expect(IsShootCPNamespace("")).To(BeFalse())
- Expect(IsShootCPNamespace("shoot--my--shoot")).To(BeTrue())
+ Expect(IsShootNamespace("shoot--my-shoot")).To(BeTrue())
+ Expect(IsShootNamespace("shoot-my-shoot")).To(BeFalse())
+ Expect(IsShootNamespace("")).To(BeFalse())
+ Expect(IsShootNamespace("shoot--my--shoot")).To(BeTrue())
})
})
})
diff --git a/skaffold.yaml b/skaffold.yaml
new file mode 100644
index 00000000..b8928fd6
--- /dev/null
+++ b/skaffold.yaml
@@ -0,0 +1,115 @@
+---
+apiVersion: skaffold/v4beta7
+kind: Config
+metadata:
+ name: gcmx
+build:
+ artifacts:
+ - image: eu.gcr.io/gardener-project/gardener/gardener-custom-metrics
+ ko:
+ dependencies:
+ paths:
+ - cmd/**
+ - example/**
+ - pkg/**
+ - vendor/**
+ - VERSION
+ ldflags:
+ - '{{.LD_FLAGS}}'
+ main: ./cmd/gardener-custom-metrics
+profiles:
+ - name: debug
+ activation:
+ - command: debug
+ manifests:
+ rawYaml:
+ - example/custom-metrics-deployment.yaml
+# kustomize:
+# paths:
+# - example/provider-local/seed-kind2/skaffold
+ deploy:
+ kubectl: {}
+
+# TODO: Andrey: P1: cleanup
+# patches:
+# - op: add
+# path: /deploy/helm/releases/0/setValues
+# value:
+# replicaCount: 1
+# config.leaderElection.leaderElect: false
+# config.server.healthProbes.enable: false
+# - name: kind2
+# patches:
+# - op: add
+# path: /deploy/helm/releases/0/valuesFiles/-
+# value: example/gardener-local/gardenlet/values-kind2.yaml
+# - op: replace
+# path: /deploy/helm/hooks/after/0/host/command
+# value:
+# - bash
+# - -ec
+# - KUBECONFIG=$GARDENER_LOCAL_KUBECONFIG hack/usage/wait-for.sh seed local2 GardenletReady SeedSystemComponentsHealthy ExtensionsReady BackupBucketsReady
+# - name: extensions
+# patches:
+# - op: add
+# path: /deploy/helm/releases/0/valuesFiles/-
+# value: example/gardener-local/gardenlet/values-provider-extensions.yaml
+# - op: add
+# path: /deploy/helm/releases/0/valuesFiles/-
+# value: example/provider-extensions/gardenlet/{{.SEED_VALUES}}
+# - op: replace
+# path: /deploy/helm/hooks/after/0/host/command
+# value:
+# - bash
+# - -ec
+# - KUBECONFIG=$GARDENER_LOCAL_KUBECONFIG hack/usage/wait-for.sh seed "$SEED_NAME" GardenletReady SeedSystemComponentsHealthy ExtensionsReady
+# - name: ha-single-zone
+# patches:
+# - op: add
+# path: /deploy/helm/releases/0/valuesFiles/-
+# value: example/gardener-local/gardenlet/values-kind-ha-single-zone.yaml
+# - op: replace
+# path: /deploy/helm/hooks/after/0/host/command
+# value:
+# - bash
+# - -ec
+# - hack/usage/wait-for.sh seed local-ha-single-zone GardenletReady SeedSystemComponentsHealthy ExtensionsReady BackupBucketsReady
+# - name: kind2-ha-single-zone
+# patches:
+# - op: add
+# path: /deploy/helm/releases/0/valuesFiles/-
+# value: example/gardener-local/gardenlet/values-kind2-ha-single-zone.yaml
+# - op: replace
+# path: /deploy/helm/hooks/after/0/host/command
+# value:
+# - bash
+# - -ec
+# - KUBECONFIG=$GARDENER_LOCAL_KUBECONFIG hack/usage/wait-for.sh seed local2-ha-single-zone GardenletReady SeedSystemComponentsHealthy ExtensionsReady BackupBucketsReady
+# - name: ha-multi-zone
+# patches:
+# - op: add
+# path: /deploy/helm/releases/0/valuesFiles/-
+# value: example/gardener-local/gardenlet/values-kind-ha-multi-zone.yaml
+# - op: replace
+# path: /deploy/helm/hooks/after/0/host/command
+# value:
+# - bash
+# - -ec
+# - TIMEOUT=1200 hack/usage/wait-for.sh seed local-ha-multi-zone GardenletReady SeedSystemComponentsHealthy ExtensionsReady BackupBucketsReady
+# - name: ipv6
+# activation:
+# - env: IPFAMILY=ipv6
+# patches:
+# - op: add
+# path: /deploy/helm/releases/0/valuesFiles/-
+# value: example/gardener-local/gardenlet/values-ipv6.yaml
+# - name: debug
+# activation:
+# - command: debug
+# patches:
+# - op: add
+# path: /deploy/helm/releases/0/setValues
+# value:
+# replicaCount: 1
+# config.leaderElection.leaderElect: false
+# config.server.healthProbes.enable: false
From 0f0ee1198d6cc31a241abcfb7ff7a50f9345d0aa Mon Sep 17 00:00:00 2001
From: Andrey Anastasov <98102124+andrerun@users.noreply.github.com>
Date: Wed, 20 Mar 2024 13:58:35 +0200
Subject: [PATCH 2/8] Apply review comments
---
Dockerfile | 4 +-
Makefile | 10 +--
README.md | 2 +-
VERSION | 2 +-
docs/development/README.md | 21 +++++++
example/custom-metrics-deployment.yaml | 2 -
go.mod | 6 +-
go.sum | 25 ++++++++
pkg/ha/ha_service.go | 2 +-
pkg/util/gardener/util.go | 2 +-
pkg/util/gardener/util_test.go | 7 ++-
skaffold.yaml | 86 +-------------------------
12 files changed, 67 insertions(+), 102 deletions(-)
create mode 100644 docs/development/README.md
diff --git a/Dockerfile b/Dockerfile
index 5aea163e..7ecf541e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,12 +1,12 @@
############# builder
-FROM golang:1.19.9 AS builder
+FROM golang:1.22.1 AS builder
WORKDIR /go/src/github.com/gardener/gardener-custom-metrics
COPY . .
RUN make install
############# base image # TODO: Andrey: P1: Move to distroless
-FROM alpine:3.18.0 AS base
+FROM alpine:3.18.6 AS base
############# gardener-custom-metrics
FROM base AS gardener-custom-metrics
diff --git a/Makefile b/Makefile
index cb156418..f60b0707 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,6 @@
BUILD_DATE := $(shell date '+%Y-%m-%dT%H:%M:%S%z' | sed 's/\([0-9][0-9]\)$$/:\1/g')
NAME := gardener-custom-metrics
IMAGE_REGISTRY_URI := eu.gcr.io/gardener-project/gardener
-# IMAGE_REGISTRY_URI := eu.gcr.io/sap-se-gcp-scp-k8s/$(NAME)
REPO_ROOT := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
VERSION := $(shell cat "$(REPO_ROOT)/VERSION")
EFFECTIVE_VERSION := $(VERSION)-$(shell git rev-parse HEAD)
@@ -31,8 +30,9 @@ ifneq ($(strip $(shell git status --porcelain 2>/dev/null)),)
EFFECTIVE_VERSION := $(EFFECTIVE_VERSION)-dirty
endif
-LD_FLAGS_DEBUG := "$(shell EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) $(REPO_ROOT)/hack/gardener-util/get-build-ld-flags.sh k8s.io/component-base $(REPO_ROOT)/VERSION $(EXTENSION_PREFIX)-$(NAME))"
+# In debug, do not use the -w flag. It strips useful debug information.
LD_FLAGS := "-w $(shell EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) $(REPO_ROOT)/hack/gardener-util/get-build-ld-flags.sh k8s.io/component-base $(REPO_ROOT)/VERSION $(EXTENSION_PREFIX)-$(NAME))"
+LD_FLAGS_DEBUG := "$(shell EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) $(REPO_ROOT)/hack/gardener-util/get-build-ld-flags.sh k8s.io/component-base $(REPO_ROOT)/VERSION $(EXTENSION_PREFIX)-$(NAME))"
TOOLS_DIR := $(REPO_ROOT)/hack/gardener-util/tools
include $(REPO_ROOT)/hack/gardener-util/tools.mk
@@ -150,8 +150,10 @@ debug: export SOURCE_DATE_EPOCH = $(shell date -d $(BUILD_DATE) +%s)
.PHONY: debug
debug: $(SKAFFOLD)
- @echo "LD_FLAGS: $(LD_FLAGS_DEBUG)"
- @LD_FLAGS=$(LD_FLAGS) $(SKAFFOLD) debug
+ @LD_FLAGS=$(LD_FLAGS_DEBUG) $(SKAFFOLD) debug
+
+ # TODO: Andrey: P1: Inject TLS secret name dynamically into deployment
+ # GCMX_TLS_SECRET_NAME=$(kubectl -n garden get secrets | grep '^gardener-custom-metrics' | head -n 1 | awk '{print $1}') \
# TODO: Andrey: P1: code cleanup
# export SKAFFOLD_DEFAULT_REPO = localhost:5001
# export SKAFFOLD_PUSH = true
diff --git a/README.md b/README.md
index 8fdafd8e..95338b44 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# gardener-custom-metrics
-[](https://reuse.software/)
+[](https://api.reuse.software/info/github.com/gardener/gardener-custom-metrics)
## Overview
The `gardener-custom-metrics` component operates as a K8s API service, adding functionality to the seed kube-apiserver.
It periodically scrapes the metrics endpoints of all shoot kube-apiserver pods on the seed. It implements the K8s custom
diff --git a/VERSION b/VERSION
index 2787740c..0a02a013 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-v0.10.11-dev
\ No newline at end of file
+v0.1.0-dev
\ No newline at end of file
diff --git a/docs/development/README.md b/docs/development/README.md
new file mode 100644
index 00000000..5ef08ccd
--- /dev/null
+++ b/docs/development/README.md
@@ -0,0 +1,21 @@
+### To debug gardener-custom-metrics (GCMx):
+- Prerequisite: [Gardener local dev setup]
+- Open a terminal
+- Set current directory to project root
+- Point $KUBECONFIG to the K8s cluster from the [Gardener local dev setup]
+- Run `make debug`:
+ - This is a blocking call
+ - It builds and deploys a debug-instrumented pod to the cluster
+ - It forwards the pod's log output to the console window
+ - It forwards localhost:56268 to the debugger port for the pod
+- Attach debugger to localhost:56268. At this point, if you place a breakpoint somewhere, it should be hit.
+
+### To build and publish GCMx:
+These instructions are a work in progress and may contain errors
+- Open a terminal
+- Set current directory to project root
+- Run `make docker-build`
+- Run `make docker-login`
+- Run `make docker-push`
+
+[Gardener local dev setup]: https://gardener.cloud/docs/gardener/deployment/getting_started_locally
\ No newline at end of file
diff --git a/example/custom-metrics-deployment.yaml b/example/custom-metrics-deployment.yaml
index ee7edc56..84f05359 100644
--- a/example/custom-metrics-deployment.yaml
+++ b/example/custom-metrics-deployment.yaml
@@ -11,13 +11,11 @@ spec:
matchLabels:
app: gardener-custom-metrics
gardener.cloud/role: gardener-custom-metrics
- resources.gardener.cloud/managed-by: gardener
template:
metadata:
labels:
app: gardener-custom-metrics
gardener.cloud/role: gardener-custom-metrics
- resources.gardener.cloud/managed-by: gardener
networking.gardener.cloud/from-seed: allowed
networking.gardener.cloud/to-dns: allowed
networking.gardener.cloud/to-runtime-apiserver: allowed
diff --git a/go.mod b/go.mod
index 2b535378..57823249 100644
--- a/go.mod
+++ b/go.mod
@@ -1,13 +1,14 @@
module github.com/gardener/gardener-custom-metrics
-go 1.21
+go 1.22.0
require (
github.com/go-logr/logr v1.2.4
github.com/onsi/ginkgo/v2 v2.11.0
github.com/onsi/gomega v1.27.8
- github.com/spf13/cobra v1.6.1
+ github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
+ go.uber.org/atomic v1.7.0
go.uber.org/zap v1.21.0
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
golang.org/x/time v0.3.0
@@ -82,7 +83,6 @@ require (
go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect
go.opentelemetry.io/otel/trace v0.20.0 // indirect
go.opentelemetry.io/proto/otlp v0.7.0 // indirect
- go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/mod v0.10.0 // indirect
diff --git a/go.sum b/go.sum
index e1c8d8a2..bf963668 100644
--- a/go.sum
+++ b/go.sum
@@ -21,7 +21,9 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM
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.13.0 h1:AYrLkB8NPdDRslNp4Jxmzrhdr03fUAIDbiGFjLWowoU=
+cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE=
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=
@@ -36,6 +38,7 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
+github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
@@ -81,6 +84,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.16.0+incompatible h1:rgqiKNjTnFQA6kkhFe16D8epTksy9HQ1MyrbDXSdYhM=
github.com/emicklei/go-restful v2.16.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
@@ -98,6 +102,7 @@ github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQL
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
+github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
@@ -168,6 +173,7 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
+github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -205,7 +211,9 @@ github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
+github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
@@ -221,6 +229,7 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
+github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
@@ -268,8 +277,10 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
+github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
@@ -309,9 +320,12 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
+github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.9.4 h1:Sd43wM1IWz/s1aVXdOBkjJvuP8UdyqioeE4AmM0QsBs=
+github.com/spf13/afero v1.9.4/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -326,24 +340,32 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
+go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY=
go.etcd.io/etcd/api/v3 v3.5.7/go.mod h1:9qew1gCdDDLu+VwmeG+iFpL+QlpHTo7iubavdVDgCAA=
go.etcd.io/etcd/client/pkg/v3 v3.5.7 h1:y3kf5Gbp4e4q7egZdn5T7W9TSHUvkClN6u+Rq9mEOmg=
go.etcd.io/etcd/client/pkg/v3 v3.5.7/go.mod h1:o0Abi1MK86iad3YrWhgUsbGx1pmTS+hrORWc2CamuhY=
go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLTs=
+go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
go.etcd.io/etcd/client/v3 v3.5.7 h1:u/OhpiuCgYY8awOHlhIhmGIGpxfBU/GZBUP3m/3/Iz4=
go.etcd.io/etcd/client/v3 v3.5.7/go.mod h1:sOWmj9DZUMyAngS7QQwCyAXXAL6WhgTOPLNS/NabQgw=
go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk=
+go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE=
go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw=
+go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc=
go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E=
+go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -378,6 +400,7 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
@@ -695,6 +718,7 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -720,6 +744,7 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
k8s.io/api v0.23.17 h1:gC11V5AIsNXUUa/xd5RQo7djukvl5O1ZDQKwEYu0H7g=
k8s.io/api v0.23.17/go.mod h1:upM9VIzXUjEyLTmGGi0KnH8kdlPnvgv+fEJ3tggDHfE=
k8s.io/apiextensions-apiserver v0.23.5 h1:5SKzdXyvIJKu+zbfPc3kCbWpbxi+O+zdmAJBm26UJqI=
+k8s.io/apiextensions-apiserver v0.23.5/go.mod h1:ntcPWNXS8ZPKN+zTXuzYMeg731CP0heCTl6gYBxLcuQ=
k8s.io/apimachinery v0.23.17 h1:ipJ0SrpI6EzH8zVw0WhCBldgJhzIamiYIumSGTdFExY=
k8s.io/apimachinery v0.23.17/go.mod h1:87v5Wl9qpHbnapX1PSNgln4oO3dlyjAU3NSIwNhT4Lo=
k8s.io/apiserver v0.23.17 h1:0br6oJhknp1mT0epMS84ibj+XcpmthPd60B5bPdbko8=
diff --git a/pkg/ha/ha_service.go b/pkg/ha/ha_service.go
index bab4e163..808d4e97 100644
--- a/pkg/ha/ha_service.go
+++ b/pkg/ha/ha_service.go
@@ -71,7 +71,7 @@ func (ha *HAService) setEndpoints(ctx context.Context) error {
endpoints.ObjectMeta.Name = app.Name
}
- endpoints.ObjectMeta.Labels = map[string]string{"app": app.Name, "resources.gardener.cloud/managed-by": "gardener"}
+ endpoints.ObjectMeta.Labels = map[string]string{"app": app.Name}
endpoints.Subsets = []corev1.EndpointSubset{{
Addresses: []corev1.EndpointAddress{{IP: ha.servingIPAddress}},
Ports: []corev1.EndpointPort{{Port: int32(ha.servingPort), Protocol: "TCP"}},
diff --git a/pkg/util/gardener/util.go b/pkg/util/gardener/util.go
index e8795e96..ae873cc6 100644
--- a/pkg/util/gardener/util.go
+++ b/pkg/util/gardener/util.go
@@ -10,7 +10,7 @@ import (
// IsShootNamespace determines whether the format of specified name implies that it is a shoot namespace in a seed
// cluster
func IsShootNamespace(namespace string) bool {
- return strings.HasPrefix(namespace, "shoot--")
+ return strings.HasPrefix(namespace, "shoot-")
}
// WatchBuilder holds various functions which add watch controls to the passed Controller.
diff --git a/pkg/util/gardener/util_test.go b/pkg/util/gardener/util_test.go
index 75420351..ae88b31e 100644
--- a/pkg/util/gardener/util_test.go
+++ b/pkg/util/gardener/util_test.go
@@ -7,9 +7,12 @@ import (
var _ = Describe("uti/gardener", func() {
Describe("IsShootNamespace", func() {
- It("should work expected on certain predefined values", func() {
+ It("should work as expected on certain predefined values", func() {
+ // Not a valid format from the Gardener perspective, but one we expect the less rigorous check in
+ // IsShootNamespace() to accept
Expect(IsShootNamespace("shoot--my-shoot")).To(BeTrue())
- Expect(IsShootNamespace("shoot-my-shoot")).To(BeFalse())
+ // Legacy format - some clusters may still use it
+ Expect(IsShootNamespace("shoot-my-shoot")).To(BeTrue())
Expect(IsShootNamespace("")).To(BeFalse())
Expect(IsShootNamespace("shoot--my--shoot")).To(BeTrue())
})
diff --git a/skaffold.yaml b/skaffold.yaml
index b8928fd6..b3e00b11 100644
--- a/skaffold.yaml
+++ b/skaffold.yaml
@@ -2,7 +2,7 @@
apiVersion: skaffold/v4beta7
kind: Config
metadata:
- name: gcmx
+ name: gardener-custom-metrics
build:
artifacts:
- image: eu.gcr.io/gardener-project/gardener/gardener-custom-metrics
@@ -29,87 +29,3 @@ profiles:
# - example/provider-local/seed-kind2/skaffold
deploy:
kubectl: {}
-
-# TODO: Andrey: P1: cleanup
-# patches:
-# - op: add
-# path: /deploy/helm/releases/0/setValues
-# value:
-# replicaCount: 1
-# config.leaderElection.leaderElect: false
-# config.server.healthProbes.enable: false
-# - name: kind2
-# patches:
-# - op: add
-# path: /deploy/helm/releases/0/valuesFiles/-
-# value: example/gardener-local/gardenlet/values-kind2.yaml
-# - op: replace
-# path: /deploy/helm/hooks/after/0/host/command
-# value:
-# - bash
-# - -ec
-# - KUBECONFIG=$GARDENER_LOCAL_KUBECONFIG hack/usage/wait-for.sh seed local2 GardenletReady SeedSystemComponentsHealthy ExtensionsReady BackupBucketsReady
-# - name: extensions
-# patches:
-# - op: add
-# path: /deploy/helm/releases/0/valuesFiles/-
-# value: example/gardener-local/gardenlet/values-provider-extensions.yaml
-# - op: add
-# path: /deploy/helm/releases/0/valuesFiles/-
-# value: example/provider-extensions/gardenlet/{{.SEED_VALUES}}
-# - op: replace
-# path: /deploy/helm/hooks/after/0/host/command
-# value:
-# - bash
-# - -ec
-# - KUBECONFIG=$GARDENER_LOCAL_KUBECONFIG hack/usage/wait-for.sh seed "$SEED_NAME" GardenletReady SeedSystemComponentsHealthy ExtensionsReady
-# - name: ha-single-zone
-# patches:
-# - op: add
-# path: /deploy/helm/releases/0/valuesFiles/-
-# value: example/gardener-local/gardenlet/values-kind-ha-single-zone.yaml
-# - op: replace
-# path: /deploy/helm/hooks/after/0/host/command
-# value:
-# - bash
-# - -ec
-# - hack/usage/wait-for.sh seed local-ha-single-zone GardenletReady SeedSystemComponentsHealthy ExtensionsReady BackupBucketsReady
-# - name: kind2-ha-single-zone
-# patches:
-# - op: add
-# path: /deploy/helm/releases/0/valuesFiles/-
-# value: example/gardener-local/gardenlet/values-kind2-ha-single-zone.yaml
-# - op: replace
-# path: /deploy/helm/hooks/after/0/host/command
-# value:
-# - bash
-# - -ec
-# - KUBECONFIG=$GARDENER_LOCAL_KUBECONFIG hack/usage/wait-for.sh seed local2-ha-single-zone GardenletReady SeedSystemComponentsHealthy ExtensionsReady BackupBucketsReady
-# - name: ha-multi-zone
-# patches:
-# - op: add
-# path: /deploy/helm/releases/0/valuesFiles/-
-# value: example/gardener-local/gardenlet/values-kind-ha-multi-zone.yaml
-# - op: replace
-# path: /deploy/helm/hooks/after/0/host/command
-# value:
-# - bash
-# - -ec
-# - TIMEOUT=1200 hack/usage/wait-for.sh seed local-ha-multi-zone GardenletReady SeedSystemComponentsHealthy ExtensionsReady BackupBucketsReady
-# - name: ipv6
-# activation:
-# - env: IPFAMILY=ipv6
-# patches:
-# - op: add
-# path: /deploy/helm/releases/0/valuesFiles/-
-# value: example/gardener-local/gardenlet/values-ipv6.yaml
-# - name: debug
-# activation:
-# - command: debug
-# patches:
-# - op: add
-# path: /deploy/helm/releases/0/setValues
-# value:
-# replicaCount: 1
-# config.leaderElection.leaderElect: false
-# config.server.healthProbes.enable: false
From 6d713a65e8a6c7557dd3d1b6479a0fc8c023c0ff Mon Sep 17 00:00:00 2001
From: Andrey Anastasov <98102124+andrerun@users.noreply.github.com>
Date: Wed, 20 Mar 2024 13:59:40 +0200
Subject: [PATCH 3/8] Metrics client: cap input stream length
---
pkg/input/metrics_scraper/metrics_client.go | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/pkg/input/metrics_scraper/metrics_client.go b/pkg/input/metrics_scraper/metrics_client.go
index 6a522a7c..8224a897 100644
--- a/pkg/input/metrics_scraper/metrics_client.go
+++ b/pkg/input/metrics_scraper/metrics_client.go
@@ -93,7 +93,7 @@ func (mc *metricsClientImpl) GetKapiInstanceMetrics(
}(response.Body)
if response.StatusCode < 200 || response.StatusCode >= 300 {
- return 0, fmt.Errorf("metrics client: responce reported HTTP status %d", response.StatusCode)
+ return 0, fmt.Errorf("metrics client: response reported HTTP status %d", response.StatusCode)
}
// If the server returned compressed response, use decompressing reader
@@ -117,7 +117,9 @@ func (mc *metricsClientImpl) GetKapiInstanceMetrics(
// - an optional error
//
// Exactly one of the int64 value and the error is non-zero.
-func getTotalRequestCount(metricsStream io.ReadCloser) (int64, error) {
+func getTotalRequestCount(metricsStream io.Reader) (int64, error) {
+ // Limit the metrics response as a general precaution. It should be < 5MB, so if we're getting >20MB something's wrong
+ metricsStream = &io.LimitedReader{R: metricsStream, N: 20 * 1024 * 1024}
reader := bufio.NewReader(metricsStream)
totalRequestCount := int64(0)
From a322ae23d8bd8252dac4144c15a6295741f560dd Mon Sep 17 00:00:00 2001
From: Andrey Anastasov <98102124+andrerun@users.noreply.github.com>
Date: Thu, 21 Mar 2024 12:09:03 +0200
Subject: [PATCH 4/8] Development README cosmetics
Co-authored-by: Ismail Alidzhikov
---
docs/development/README.md | 48 +++++++++++++++++++++-----------------
1 file changed, 27 insertions(+), 21 deletions(-)
diff --git a/docs/development/README.md b/docs/development/README.md
index 5ef08ccd..398d79ad 100644
--- a/docs/development/README.md
+++ b/docs/development/README.md
@@ -1,21 +1,27 @@
-### To debug gardener-custom-metrics (GCMx):
-- Prerequisite: [Gardener local dev setup]
-- Open a terminal
-- Set current directory to project root
-- Point $KUBECONFIG to the K8s cluster from the [Gardener local dev setup]
-- Run `make debug`:
- - This is a blocking call
- - It builds and deploys a debug-instrumented pod to the cluster
- - It forwards the pod's log output to the console window
- - It forwards localhost:56268 to the debugger port for the pod
-- Attach debugger to localhost:56268. At this point, if you place a breakpoint somewhere, it should be hit.
-
-### To build and publish GCMx:
-These instructions are a work in progress and may contain errors
-- Open a terminal
-- Set current directory to project root
-- Run `make docker-build`
-- Run `make docker-login`
-- Run `make docker-push`
-
-[Gardener local dev setup]: https://gardener.cloud/docs/gardener/deployment/getting_started_locally
\ No newline at end of file
+> 🚧 Note: This is a WIP document.
+
+### Debugging gardener-custom-metrics
+
+1. Make sure that you have a running local Gardener setup. The steps to complete this can be found in the [Deploying Gardener Locally guide](https://github.com/gardener/gardener/blob/master/docs/deployment/getting_started_locally.md).
+
+1. In a new terminal, navigate to the gardener-custom-metrics project root.
+
+1. Make sure that your `KUBECONFIG` environment variable is targeting the local Gardener cluster.
+
+1. Run `make debug`.
+
+ This is a blocking call. It builds and deploys a debug-instrumented pod to the cluster. It forwards the pod's log output to the console window. It forwards `localhost:56268` to the debugger port for the pod.
+
+1. Attach debugger to `localhost:56268`.
+
+ At this point, if you place a breakpoint somewhere, it should be hit.
+
+### Building and publishing gardener-custom-metrics container image:
+
+1. In a new terminal, navigate to the gardener-custom-metrics project root.
+
+1. Run `make docker-build` to build container image.
+
+1. Run `make docker-login` to authenticate against Artifact Registry before pushing the image.
+
+1. Run `make docker-push` to push the container image.
From c5908edb6191e73e2eca7502cf49558839f7614c Mon Sep 17 00:00:00 2001
From: Andrey Anastasov <98102124+andrerun@users.noreply.github.com>
Date: Thu, 21 Mar 2024 12:10:40 +0200
Subject: [PATCH 5/8] README cosmetics
Co-authored-by: Ismail Alidzhikov
---
README.md | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 95338b44..06a39eec 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
# gardener-custom-metrics
+
[](https://api.reuse.software/info/github.com/gardener/gardener-custom-metrics)
+
## Overview
-The `gardener-custom-metrics` component operates as a K8s API service, adding functionality to the seed kube-apiserver.
-It periodically scrapes the metrics endpoints of all shoot kube-apiserver pods on the seed. It implements the K8s custom
-metrics API and provides K8s metrics specific to Gardener, based on custom calculations.
+
+The `gardener-custom-metrics` component operates as a K8s API service, adding functionality to the seed kube-apiserver. It periodically scrapes the metrics endpoints of all shoot kube-apiserver pods on the seed. It implements the K8s custom metrics API and provides K8s metrics specific to Gardener, based on custom calculations.
+
From 3e4add3868cab1665e957f9e96f8e902e8808937 Mon Sep 17 00:00:00 2001
From: Andrey Anastasov <98102124+andrerun@users.noreply.github.com>
Date: Thu, 21 Mar 2024 13:26:37 +0200
Subject: [PATCH 6/8] Makefile - remove TODO
---
Makefile | 7 -------
1 file changed, 7 deletions(-)
diff --git a/Makefile b/Makefile
index f60b0707..6501a8d8 100644
--- a/Makefile
+++ b/Makefile
@@ -154,10 +154,3 @@ debug: $(SKAFFOLD)
# TODO: Andrey: P1: Inject TLS secret name dynamically into deployment
# GCMX_TLS_SECRET_NAME=$(kubectl -n garden get secrets | grep '^gardener-custom-metrics' | head -n 1 | awk '{print $1}') \
- # TODO: Andrey: P1: code cleanup
- # export SKAFFOLD_DEFAULT_REPO = localhost:5001
- # export SKAFFOLD_PUSH = true
-
- # skaffold dev triggers new builds and deployments immediately on file changes by default,
- # this is too heavy in a large project like gardener, so trigger new builds and deployments manually instead.
- # gardener%dev gardenlet%dev operator-dev: export SKAFFOLD_TRIGGER = manual
From 8e9248a468562a742d3f142153efe0e65449e2b1 Mon Sep 17 00:00:00 2001
From: Andrey Anastasov <98102124+andrerun@users.noreply.github.com>
Date: Thu, 21 Mar 2024 13:53:22 +0200
Subject: [PATCH 7/8] Bump pipeline_definitions to golang:1.22.1
---
.ci/pipeline_definitions | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.ci/pipeline_definitions b/.ci/pipeline_definitions
index b3d220d6..e68679dd 100644
--- a/.ci/pipeline_definitions
+++ b/.ci/pipeline_definitions
@@ -36,7 +36,7 @@ gardener-custom-metrics:
release:
steps:
verify:
- image: 'golang:1.19.9'
+ image: 'golang:1.22.1'
traits:
version:
preprocess: 'finalize'
From b80af7c7058f50da2a576e42343cdfeed0831a02 Mon Sep 17 00:00:00 2001
From: Andrey Anastasov <98102124+andrerun@users.noreply.github.com>
Date: Thu, 21 Mar 2024 17:09:38 +0200
Subject: [PATCH 8/8] Drop inactive configuration from skaffold.yaml
---
skaffold.yaml | 3 ---
1 file changed, 3 deletions(-)
diff --git a/skaffold.yaml b/skaffold.yaml
index b3e00b11..90baa450 100644
--- a/skaffold.yaml
+++ b/skaffold.yaml
@@ -24,8 +24,5 @@ profiles:
manifests:
rawYaml:
- example/custom-metrics-deployment.yaml
-# kustomize:
-# paths:
-# - example/provider-local/seed-kind2/skaffold
deploy:
kubectl: {}