mirror of
https://github.com/outbackdingo/talos-cloud-controller-manager.git
synced 2026-01-27 18:20:23 +00:00
feat: node transformer
Node transformer allows you to add extra labels/annotations and modify platform metadata. Signed-off-by: Serge Logvinov <serge.logvinov@sinextra.dev>
This commit is contained in:
6
.github/workflows/build-test.yaml
vendored
6
.github/workflows/build-test.yaml
vendored
@@ -35,10 +35,10 @@ jobs:
|
|||||||
go-version-file: 'go.mod'
|
go-version-file: 'go.mod'
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
uses: golangci/golangci-lint-action@v4
|
uses: golangci/golangci-lint-action@v5
|
||||||
with:
|
with:
|
||||||
version: v1.56.2
|
version: v1.57.1
|
||||||
args: --config=.golangci.yml
|
args: --timeout=5m --config=.golangci.yml
|
||||||
- name: Build
|
- name: Build
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
run: make images
|
run: make images
|
||||||
|
|||||||
2
.github/workflows/release-charts.yaml
vendored
2
.github/workflows/release-charts.yaml
vendored
@@ -24,8 +24,6 @@ jobs:
|
|||||||
|
|
||||||
- name: Install Helm
|
- name: Install Helm
|
||||||
uses: azure/setup-helm@v4
|
uses: azure/setup-helm@v4
|
||||||
with:
|
|
||||||
version: v3.12.2
|
|
||||||
- name: Install Cosign
|
- name: Install Cosign
|
||||||
uses: sigstore/cosign-installer@v3.5.0
|
uses: sigstore/cosign-installer@v3.5.0
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
# options for analysis running
|
# options for analysis running
|
||||||
run:
|
run:
|
||||||
go: '1.21'
|
|
||||||
# default concurrency is a available CPU number
|
# default concurrency is a available CPU number
|
||||||
# concurrency: 4
|
# concurrency: 4
|
||||||
|
|
||||||
@@ -20,7 +19,8 @@ run:
|
|||||||
# won't be reported. Default value is empty list, but there is
|
# won't be reported. Default value is empty list, but there is
|
||||||
# no need to include all autogenerated files, we confidently recognize
|
# no need to include all autogenerated files, we confidently recognize
|
||||||
# autogenerated files. If it's not please let us know.
|
# autogenerated files. If it's not please let us know.
|
||||||
skip-files:
|
exclude-files:
|
||||||
|
- charts/
|
||||||
- docs/
|
- docs/
|
||||||
|
|
||||||
# list of build tags, all linters use it. Default is empty list.
|
# list of build tags, all linters use it. Default is empty list.
|
||||||
@@ -34,7 +34,13 @@ run:
|
|||||||
# output configuration options
|
# output configuration options
|
||||||
output:
|
output:
|
||||||
# colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number"
|
# colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number"
|
||||||
format: line-number
|
formats:
|
||||||
|
- format: line-number
|
||||||
|
path: stdout
|
||||||
|
print-issued-lines: true
|
||||||
|
print-linter-name: true
|
||||||
|
uniq-by-line: true
|
||||||
|
sort-results: true
|
||||||
|
|
||||||
# all available settings of specific linters
|
# all available settings of specific linters
|
||||||
linters-settings:
|
linters-settings:
|
||||||
@@ -46,15 +52,13 @@ linters-settings:
|
|||||||
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
||||||
# default is false: such cases aren't reported by default.
|
# default is false: such cases aren't reported by default.
|
||||||
check-blank: true
|
check-blank: true
|
||||||
govet:
|
govet: {}
|
||||||
# report about shadowed variables
|
|
||||||
check-shadowing: true
|
|
||||||
gofmt:
|
gofmt:
|
||||||
# simplify code: gofmt with `-s` option, true by default
|
# simplify code: gofmt with `-s` option, true by default
|
||||||
simplify: true
|
simplify: true
|
||||||
gocyclo:
|
gocyclo:
|
||||||
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
# minimal code complexity to report, 30 by default (but we recommend 10-20)
|
||||||
min-complexity: 15
|
min-complexity: 20
|
||||||
maligned:
|
maligned:
|
||||||
# print struct with more effective memory layout or not, false by default
|
# print struct with more effective memory layout or not, false by default
|
||||||
suggest-new: true
|
suggest-new: true
|
||||||
@@ -66,6 +70,8 @@ linters-settings:
|
|||||||
min-len: 3
|
min-len: 3
|
||||||
# minimal occurrences count to trigger, 3 by default
|
# minimal occurrences count to trigger, 3 by default
|
||||||
min-occurrences: 3
|
min-occurrences: 3
|
||||||
|
depguard:
|
||||||
|
list-type: blacklist
|
||||||
misspell:
|
misspell:
|
||||||
# Correct spellings using locale preferences for US or UK.
|
# Correct spellings using locale preferences for US or UK.
|
||||||
# Default is to use a neutral variety of English.
|
# Default is to use a neutral variety of English.
|
||||||
@@ -167,11 +173,21 @@ linters:
|
|||||||
- wrapcheck
|
- wrapcheck
|
||||||
- perfsprint
|
- perfsprint
|
||||||
|
|
||||||
|
# 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
|
# abandoned linters for which golangci shows the warning that the repo is archived by the owner
|
||||||
- golint
|
- golint
|
||||||
- interfacer
|
- interfacer
|
||||||
- maligned
|
- maligned
|
||||||
- scopelint
|
- scopelint
|
||||||
|
- varcheck
|
||||||
|
- structcheck
|
||||||
|
- deadcode
|
||||||
|
- ifshort
|
||||||
|
- perfsprint
|
||||||
|
|
||||||
disable-all: false
|
disable-all: false
|
||||||
fast: false
|
fast: false
|
||||||
|
|||||||
@@ -11,5 +11,5 @@ keywords:
|
|||||||
maintainers:
|
maintainers:
|
||||||
- name: sergelogvinov
|
- name: sergelogvinov
|
||||||
url: https://github.com/sergelogvinov
|
url: https://github.com/sergelogvinov
|
||||||
version: 0.2.3
|
version: 0.3.0
|
||||||
appVersion: "v1.6.0"
|
appVersion: "v1.6.0"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# talos-cloud-controller-manager
|
# talos-cloud-controller-manager
|
||||||
|
|
||||||
  
|
  
|
||||||
|
|
||||||
Talos Cloud Controller Manager Helm Chart
|
Talos Cloud Controller Manager Helm Chart
|
||||||
|
|
||||||
@@ -79,5 +79,6 @@ helm upgrade -i --namespace=kube-system -f talos-ccm.yaml \
|
|||||||
| serviceAccount.create | bool | `true` | Specifies whether a service account should be created. |
|
| serviceAccount.create | bool | `true` | Specifies whether a service account should be created. |
|
||||||
| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. |
|
| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. |
|
||||||
| tolerations | list | `[{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane","operator":"Exists"},{"effect":"NoSchedule","key":"node.cloudprovider.kubernetes.io/uninitialized","operator":"Exists"}]` | Tolerations for data pods assignment. ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ |
|
| tolerations | list | `[{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane","operator":"Exists"},{"effect":"NoSchedule","key":"node.cloudprovider.kubernetes.io/uninitialized","operator":"Exists"}]` | Tolerations for data pods assignment. ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ |
|
||||||
|
| transformations | list | `[]` | List of node transformations. Available matchExpressions key values: https://github.com/siderolabs/talos/blob/main/pkg/machinery/resources/runtime/platform_metadata.go#L28 |
|
||||||
| updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":1},"type":"RollingUpdate"}` | Deployment update stategy type. ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment |
|
| updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":1},"type":"RollingUpdate"}` | Deployment update stategy type. ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment |
|
||||||
| useDaemonSet | bool | `false` | Deploy CCM in Daemonset mode. CCM will use hostNetwork and current node to access kubernetes/talos API You can run it without CNI plugin. |
|
| useDaemonSet | bool | `false` | Deploy CCM in Daemonset mode. CCM will use hostNetwork and current node to access kubernetes/talos API You can run it without CNI plugin. |
|
||||||
|
|||||||
@@ -11,3 +11,7 @@ data:
|
|||||||
{{- if .Values.features.approveNodeCSR }}
|
{{- if .Values.features.approveNodeCSR }}
|
||||||
approveNodeCSR: true
|
approveNodeCSR: true
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- with .Values.transformations }}
|
||||||
|
transformations:
|
||||||
|
{{- toYaml . | nindent 6 }}
|
||||||
|
{{- end }}
|
||||||
|
|||||||
@@ -40,6 +40,23 @@ features:
|
|||||||
# `approveNodeCSR` - check and approve node CSR.
|
# `approveNodeCSR` - check and approve node CSR.
|
||||||
approveNodeCSR: true
|
approveNodeCSR: true
|
||||||
|
|
||||||
|
# -- List of node transformations.
|
||||||
|
# Available matchExpressions key values: https://github.com/siderolabs/talos/blob/main/pkg/machinery/resources/runtime/platform_metadata.go#L28
|
||||||
|
transformations: []
|
||||||
|
# - name: control-plane region
|
||||||
|
# nodeSelector:
|
||||||
|
# - matchExpressions:
|
||||||
|
# - key: hostname
|
||||||
|
# operator: Regexp
|
||||||
|
# values:
|
||||||
|
# - ^control-.+$
|
||||||
|
# annotations:
|
||||||
|
# talos.dev/instance-id: "{{ .InstanceID }}"
|
||||||
|
# labels:
|
||||||
|
# talos.dev/instance-spot: "{{ .Spot }}"
|
||||||
|
# platformMetadata:
|
||||||
|
# Region: "us-west-2"
|
||||||
|
|
||||||
# -- Log verbosity level. See https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md
|
# -- Log verbosity level. See https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md
|
||||||
# for description of individual verbosity levels.
|
# for description of individual verbosity levels.
|
||||||
logVerbosityLevel: 2
|
logVerbosityLevel: 2
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ kind: ServiceAccount
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager
|
name: talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -18,7 +18,7 @@ kind: ServiceAccount
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager-talos-secrets
|
name: talos-cloud-controller-manager-talos-secrets
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -34,7 +34,7 @@ kind: ConfigMap
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager
|
name: talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -51,7 +51,7 @@ kind: ClusterRole
|
|||||||
metadata:
|
metadata:
|
||||||
name: system:talos-cloud-controller-manager
|
name: system:talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -159,7 +159,7 @@ kind: Service
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager
|
name: talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -183,7 +183,7 @@ kind: DaemonSet
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager
|
name: talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ kind: ServiceAccount
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager
|
name: talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -18,7 +18,7 @@ kind: ServiceAccount
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager-talos-secrets
|
name: talos-cloud-controller-manager-talos-secrets
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -34,7 +34,7 @@ kind: ConfigMap
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager
|
name: talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -51,7 +51,7 @@ kind: ClusterRole
|
|||||||
metadata:
|
metadata:
|
||||||
name: system:talos-cloud-controller-manager
|
name: system:talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -159,7 +159,7 @@ kind: Service
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager
|
name: talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -183,7 +183,7 @@ kind: Deployment
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager
|
name: talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ kind: ServiceAccount
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager
|
name: talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -18,7 +18,7 @@ kind: ServiceAccount
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager-talos-secrets
|
name: talos-cloud-controller-manager-talos-secrets
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -34,7 +34,7 @@ kind: ConfigMap
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager
|
name: talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -51,7 +51,7 @@ kind: ClusterRole
|
|||||||
metadata:
|
metadata:
|
||||||
name: system:talos-cloud-controller-manager
|
name: system:talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -159,7 +159,7 @@ kind: Service
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager
|
name: talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
@@ -183,7 +183,7 @@ kind: Deployment
|
|||||||
metadata:
|
metadata:
|
||||||
name: talos-cloud-controller-manager
|
name: talos-cloud-controller-manager
|
||||||
labels:
|
labels:
|
||||||
helm.sh/chart: talos-cloud-controller-manager-0.2.3
|
helm.sh/chart: talos-cloud-controller-manager-0.3.0
|
||||||
app.kubernetes.io/name: talos-cloud-controller-manager
|
app.kubernetes.io/name: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/instance: talos-cloud-controller-manager
|
app.kubernetes.io/instance: talos-cloud-controller-manager
|
||||||
app.kubernetes.io/version: "v1.6.0"
|
app.kubernetes.io/version: "v1.6.0"
|
||||||
|
|||||||
85
docs/rules.yaml
Normal file
85
docs/rules.yaml
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# transformation rules for the node
|
||||||
|
transformations:
|
||||||
|
- name: oracle
|
||||||
|
# Match rules similar as kubernetes matchExpressions
|
||||||
|
nodeSelector:
|
||||||
|
- name: oracle vm in frankfurt
|
||||||
|
matchExpressions:
|
||||||
|
- key: platform
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- oracle
|
||||||
|
- key: region
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- eu-frankfurt-1
|
||||||
|
# or
|
||||||
|
- name: special vm name
|
||||||
|
matchExpressions:
|
||||||
|
- key: hostname
|
||||||
|
operator: Regexp
|
||||||
|
values:
|
||||||
|
- ^web-oci-ad2-.+$
|
||||||
|
|
||||||
|
# We will annotate and label the nodes
|
||||||
|
annotations:
|
||||||
|
oci.oraclecloud.com/instance-id: "{{ .InstanceID }}"
|
||||||
|
oci.oraclecloud.com/compartment-id: ocid1.compartment.oc1..aaaaaaaabbbbbbccccccdddddd
|
||||||
|
labels:
|
||||||
|
talos.dev/zone": "frankfurt"
|
||||||
|
node-role.kubernetes.io/web: ""
|
||||||
|
|
||||||
|
# Transforme the platformMetadata
|
||||||
|
platformMetadata:
|
||||||
|
zone: EU-FRANKFURT-1-AD-2
|
||||||
|
|
||||||
|
- name: openstack
|
||||||
|
nodeSelector:
|
||||||
|
- name: fix openstack zone
|
||||||
|
matchExpressions:
|
||||||
|
- key: platform
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- openstack
|
||||||
|
- key: zone
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- nova
|
||||||
|
- key: hostname
|
||||||
|
operator: Regexp
|
||||||
|
values:
|
||||||
|
- ^web-fra-.+$
|
||||||
|
annotations: {}
|
||||||
|
labels:
|
||||||
|
talos.dev/zone: "frankfurt"
|
||||||
|
node-role.kubernetes.io/web: ""
|
||||||
|
|
||||||
|
# Set providerId/region/zone based on the hostname and platform
|
||||||
|
platformMetadata:
|
||||||
|
zone: frankfurt
|
||||||
|
region: eu-frankfurt-1
|
||||||
|
providerId: openstack://fra/{{ .InstanceID }}
|
||||||
|
|
||||||
|
# Special features for the node
|
||||||
|
features:
|
||||||
|
publicIPPredict: true
|
||||||
|
|
||||||
|
---
|
||||||
|
# Metadata for the node
|
||||||
|
|
||||||
|
# Oracle
|
||||||
|
platform: oracle
|
||||||
|
hostname: web-oci-ad2-1
|
||||||
|
region: eu-frankfurt-1
|
||||||
|
zone: EU-FRANKFURT-1-AD-2
|
||||||
|
instanceType: VM.Standard.A1.Flex
|
||||||
|
instanceId: ocid1.instance.oc1.eu-frankfurt-1.aaaaaaaabbbbbbccccccdddddd
|
||||||
|
providerId: oci://ocid1.instance.oc1.eu-frankfurt-1.aaaaaaaabbbbbbccccccdddddd
|
||||||
|
|
||||||
|
# Openstack
|
||||||
|
platform: openstack
|
||||||
|
hostname: web-fra-de11
|
||||||
|
zone: nova
|
||||||
|
instanceType: b2-7
|
||||||
|
instanceId: 9a1fd9ee-9f05-473e-88d8-1b1b1b1b1b1b
|
||||||
|
providerId: openstack:///9a1fd9ee-9f05-473e-88d8-1b1b1b1b1b1b
|
||||||
52
go.mod
52
go.mod
@@ -3,24 +3,24 @@ module github.com/siderolabs/talos-cloud-controller-manager
|
|||||||
go 1.22.2
|
go 1.22.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cosi-project/runtime v0.4.1
|
github.com/cosi-project/runtime v0.4.2
|
||||||
github.com/siderolabs/net v0.4.0
|
github.com/siderolabs/net v0.4.0
|
||||||
github.com/siderolabs/talos/pkg/machinery v1.6.7
|
github.com/siderolabs/talos/pkg/machinery v1.7.1
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
gotest.tools/v3 v3.5.1
|
gotest.tools/v3 v3.5.1
|
||||||
k8s.io/api v0.29.3
|
k8s.io/api v0.30.0
|
||||||
k8s.io/apimachinery v0.29.3
|
k8s.io/apimachinery v0.30.0
|
||||||
k8s.io/client-go v0.29.3
|
k8s.io/client-go v0.30.0
|
||||||
k8s.io/cloud-provider v0.29.3
|
k8s.io/cloud-provider v0.30.0
|
||||||
k8s.io/component-base v0.29.3
|
k8s.io/component-base v0.30.0
|
||||||
k8s.io/klog/v2 v2.120.1
|
k8s.io/klog/v2 v2.120.1
|
||||||
k8s.io/utils v0.0.0-20240310230437-4693a0247e57
|
k8s.io/utils v0.0.0-20240423183400-0849a56e8f22
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||||
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||||
@@ -41,7 +41,7 @@ require (
|
|||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||||
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
|
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
github.com/gertd/go-pluralize v0.2.1 // indirect
|
github.com/gertd/go-pluralize v0.2.1 // indirect
|
||||||
@@ -53,7 +53,7 @@ require (
|
|||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/google/cel-go v0.17.7 // indirect
|
github.com/google/cel-go v0.17.8 // indirect
|
||||||
github.com/google/gnostic-models v0.6.8 // indirect
|
github.com/google/gnostic-models v0.6.8 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
@@ -66,21 +66,22 @@ require (
|
|||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/josharian/native v1.1.0 // indirect
|
github.com/josharian/native v1.1.0 // indirect
|
||||||
github.com/jsimonetti/rtnetlink v1.4.0 // indirect
|
github.com/jsimonetti/rtnetlink v1.4.1 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
github.com/mdlayher/ethtool v0.1.0 // indirect
|
github.com/mdlayher/ethtool v0.1.0 // indirect
|
||||||
github.com/mdlayher/genetlink v1.3.2 // indirect
|
github.com/mdlayher/genetlink v1.3.2 // indirect
|
||||||
github.com/mdlayher/netlink v1.7.2 // indirect
|
github.com/mdlayher/netlink v1.7.2 // indirect
|
||||||
github.com/mdlayher/socket v0.4.1 // indirect
|
github.com/mdlayher/socket v0.5.1 // indirect
|
||||||
github.com/moby/term v0.5.0 // indirect
|
github.com/moby/term v0.5.0 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
github.com/opencontainers/runtime-spec v1.2.0 // indirect
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/planetscale/vtprotobuf v0.6.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_golang v1.16.0 // indirect
|
github.com/prometheus/client_golang v1.16.0 // indirect
|
||||||
github.com/prometheus/client_model v0.4.0 // indirect
|
github.com/prometheus/client_model v0.4.0 // indirect
|
||||||
@@ -110,29 +111,28 @@ require (
|
|||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/crypto v0.22.0 // indirect
|
golang.org/x/crypto v0.22.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
|
||||||
golang.org/x/net v0.24.0 // indirect
|
golang.org/x/net v0.24.0 // indirect
|
||||||
golang.org/x/oauth2 v0.16.0 // indirect
|
golang.org/x/oauth2 v0.19.0 // indirect
|
||||||
golang.org/x/sync v0.7.0 // indirect
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
golang.org/x/sys v0.19.0 // indirect
|
golang.org/x/sys v0.19.0 // indirect
|
||||||
golang.org/x/term v0.19.0 // indirect
|
golang.org/x/term v0.19.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
google.golang.org/appengine v1.6.8 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8 // indirect
|
|
||||||
google.golang.org/grpc v1.62.1 // indirect
|
google.golang.org/grpc v1.62.1 // indirect
|
||||||
google.golang.org/protobuf v1.33.0 // indirect
|
google.golang.org/protobuf v1.33.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
k8s.io/apiserver v0.29.3 // indirect
|
k8s.io/apiserver v0.30.0 // indirect
|
||||||
k8s.io/component-helpers v0.29.3 // indirect
|
k8s.io/component-helpers v0.30.0 // indirect
|
||||||
k8s.io/controller-manager v0.29.3 // indirect
|
k8s.io/controller-manager v0.30.0 // indirect
|
||||||
k8s.io/kms v0.29.3 // indirect
|
k8s.io/kms v0.30.0 // indirect
|
||||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
|
k8s.io/kube-openapi v0.0.0-20240411171206-dc4e619f62f3 // indirect
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 // indirect
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 // indirect
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
122
go.sum
122
go.sum
@@ -2,8 +2,8 @@ cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiV
|
|||||||
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
||||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
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/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||||
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
|
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
|
||||||
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||||
@@ -47,8 +47,8 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr
|
|||||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/cosi-project/runtime v0.4.1 h1:9lJWw5cl3Lz1qP32bl2vxAsJs6LM8KdUGLCc9t/EGqw=
|
github.com/cosi-project/runtime v0.4.2 h1:kJkhorzDWierDDbXn1BDHS6iQ7ai9AdvQOnK5uG/g8g=
|
||||||
github.com/cosi-project/runtime v0.4.1/go.mod h1:eXVAHf9QzzSVblLUtHHPFOZ7JBuz+GypHbao1vw+SdQ=
|
github.com/cosi-project/runtime v0.4.2/go.mod h1:eXVAHf9QzzSVblLUtHHPFOZ7JBuz+GypHbao1vw+SdQ=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||||
@@ -62,8 +62,8 @@ github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxER
|
|||||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||||
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
|
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
|
||||||
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
|
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
|
||||||
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
|
github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=
|
||||||
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
@@ -77,8 +77,8 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
|||||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A=
|
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
|
||||||
github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4=
|
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
|
||||||
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
|
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
|
||||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||||
@@ -95,25 +95,22 @@ github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w
|
|||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
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/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||||
github.com/google/cel-go v0.17.7 h1:6ebJFzu1xO2n7TLtN+UBqShGBhlD85bhvglh5DpcfqQ=
|
github.com/google/cel-go v0.17.8 h1:j9m730pMZt1Fc4oKhCLUHfjj6527LuhYcYw0Rl8gqto=
|
||||||
github.com/google/cel-go v0.17.7/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
|
github.com/google/cel-go v0.17.8/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
|
||||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
|
github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f h1:f00RU+zOX+B3rLAmMMkzHUF2h1z4DeYR9tTCvEq2REY=
|
||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
@@ -141,8 +138,8 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
|
|||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||||
github.com/jsimonetti/rtnetlink v1.4.0 h1:Z1BF0fRgcETPEa0Kt0MRk3yV5+kF1FWTni6KUFKrq2I=
|
github.com/jsimonetti/rtnetlink v1.4.1 h1:JfD4jthWBqZMEffc5RjgmlzpYttAVw1sdnmiNaPO3hE=
|
||||||
github.com/jsimonetti/rtnetlink v1.4.0/go.mod h1:5W1jDvWdnthFJ7fxYX1GMK07BUpI4oskfOqvPteYS6E=
|
github.com/jsimonetti/rtnetlink v1.4.1/go.mod h1:xJjT7t59UIZ62GLZbv6PLLo8VFrostJMPBAheR6OM8w=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
@@ -164,8 +161,8 @@ github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy5
|
|||||||
github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o=
|
github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o=
|
||||||
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
|
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
|
||||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||||
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
|
||||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
||||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
@@ -179,12 +176,14 @@ github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8
|
|||||||
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||||
github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk=
|
github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk=
|
||||||
github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg=
|
github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg=
|
||||||
github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
|
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
|
||||||
github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/planetscale/vtprotobuf v0.6.0 h1:nBeETjudeJ5ZgBHUz1fVHvbqUKnYOXNhsIEabROxmNA=
|
||||||
|
github.com/planetscale/vtprotobuf v0.6.0/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
|
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
|
||||||
@@ -216,8 +215,8 @@ github.com/siderolabs/net v0.4.0 h1:1bOgVay/ijPkJz4qct98nHsiB/ysLQU0KLoBC4qLm7I=
|
|||||||
github.com/siderolabs/net v0.4.0/go.mod h1:/ibG+Hm9HU27agp5r9Q3eZicEfjquzNzQNux5uEk0kM=
|
github.com/siderolabs/net v0.4.0/go.mod h1:/ibG+Hm9HU27agp5r9Q3eZicEfjquzNzQNux5uEk0kM=
|
||||||
github.com/siderolabs/protoenc v0.2.1 h1:BqxEmeWQeMpNP3R6WrPqDatX8sM/r4t97OP8mFmg6GA=
|
github.com/siderolabs/protoenc v0.2.1 h1:BqxEmeWQeMpNP3R6WrPqDatX8sM/r4t97OP8mFmg6GA=
|
||||||
github.com/siderolabs/protoenc v0.2.1/go.mod h1:StTHxjet1g11GpNAWiATgc8K0HMKiFSEVVFOa/H0otc=
|
github.com/siderolabs/protoenc v0.2.1/go.mod h1:StTHxjet1g11GpNAWiATgc8K0HMKiFSEVVFOa/H0otc=
|
||||||
github.com/siderolabs/talos/pkg/machinery v1.6.7 h1:L/IV0+w+0n6Jsxa1LEFOxPaNNluGrZqn3YRvAXk/xzA=
|
github.com/siderolabs/talos/pkg/machinery v1.7.1 h1:sVFQ0lNE6+kOomSZA8iuktzG1A4zSW9KTsB2TLaTPsU=
|
||||||
github.com/siderolabs/talos/pkg/machinery v1.6.7/go.mod h1:X1rb+ZA0tRjclzuH4Kurune4DK6kr58B/vorQ88KwpE=
|
github.com/siderolabs/talos/pkg/machinery v1.7.1/go.mod h1:YBl9KDCD45Uc7N0rXBY1JqovUn1n46ekUPSNbEVZzQU=
|
||||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
|
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
|
||||||
@@ -297,8 +296,8 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz
|
|||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI=
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
|
||||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
@@ -314,8 +313,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||||
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
|
||||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -350,7 +349,6 @@ golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
|||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
@@ -364,24 +362,20 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
|
|||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
|
||||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
|
||||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
|
||||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
|
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
|
||||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
|
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 h1:8eadJkXbwDEMNwcB5O0s5Y5eCfyuCLdvaiOIaGTrWmQ=
|
google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda h1:b6F6WIV4xHHD0FA4oIyzU6mHWg2WI2X1RBehwa5QN38=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y=
|
google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda/go.mod h1:AHcE/gZH76Bk/ROZhQphlRoWo5xKDEtz3eVEO1LfA8c=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8 h1:IR+hp6ypxjH24bkMfEJ0yHR21+gwPWdV+/IBrPQyn3k=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||||
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
|
||||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@@ -399,35 +393,35 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||||
k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw=
|
k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA=
|
||||||
k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80=
|
k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE=
|
||||||
k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU=
|
k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA=
|
||||||
k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU=
|
k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
|
||||||
k8s.io/apiserver v0.29.3 h1:xR7ELlJ/BZSr2n4CnD3lfA4gzFivh0wwfNfz9L0WZcE=
|
k8s.io/apiserver v0.30.0 h1:QCec+U72tMQ+9tR6A0sMBB5Vh6ImCEkoKkTDRABWq6M=
|
||||||
k8s.io/apiserver v0.29.3/go.mod h1:hrvXlwfRulbMbBgmWRQlFru2b/JySDpmzvQwwk4GUOs=
|
k8s.io/apiserver v0.30.0/go.mod h1:smOIBq8t0MbKZi7O7SyIpjPsiKJ8qa+llcFCluKyqiY=
|
||||||
k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg=
|
k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ=
|
||||||
k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0=
|
k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY=
|
||||||
k8s.io/cloud-provider v0.29.3 h1:y39hNq0lrPD1qmqQ2ykwMJGeWF9LsepVkR2a4wskwLc=
|
k8s.io/cloud-provider v0.30.0 h1:hz1MXkFjsyO167sRZVchXEi2YYMQ6kolBi79nuICjzw=
|
||||||
k8s.io/cloud-provider v0.29.3/go.mod h1:daDV1WkAO6pTrdsn7v8TpN/q9n75ExUC4RJDl7vlPKk=
|
k8s.io/cloud-provider v0.30.0/go.mod h1:iyVcGvDfmZ7m5cliI9TTHj0VTjYDNpc/K71Gp6hukjU=
|
||||||
k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo=
|
k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o=
|
||||||
k8s.io/component-base v0.29.3/go.mod h1:Yuj33XXjuOk2BAaHsIGHhCKZQAgYKhqIxIjIr2UXYio=
|
k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ=
|
||||||
k8s.io/component-helpers v0.29.3 h1:1dqZswuZgT2ZMixYeORyCUOAApXxgsvjVSgfoUT+P4o=
|
k8s.io/component-helpers v0.30.0 h1:xbJtNCfSM4SB/Tz5JqCKDZv4eT5LVi/AWQ1VOxhmStU=
|
||||||
k8s.io/component-helpers v0.29.3/go.mod h1:yiDqbRQrnQY+sPju/bL7EkwDJb6LVOots53uZNMZBos=
|
k8s.io/component-helpers v0.30.0/go.mod h1:68HlSwXIumMKmCx8cZe1PoafQEYh581/sEpxMrkhmX4=
|
||||||
k8s.io/controller-manager v0.29.3 h1:pvm3mirypgW7kM6dHRk6O5ANZj4bZTWirfk5gO6RlCo=
|
k8s.io/controller-manager v0.30.0 h1:jqqT8cK0Awdy0IfT0yuqYIRmwskbdzH5AEZqkuhEVMs=
|
||||||
k8s.io/controller-manager v0.29.3/go.mod h1:RNxpf0d1WAo59sOLd32isWJP0oZ7Zxr+q4VEEaSq4gk=
|
k8s.io/controller-manager v0.30.0/go.mod h1:suM1r/pxUuk2ij5Bbm7W9kBLrFujXuzIboNuWK5AfRA=
|
||||||
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
|
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
|
||||||
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
k8s.io/kms v0.29.3 h1:ReljsAUhYlm2spdT4yXmY+9a8x8dc/OT4mXvwQPPteQ=
|
k8s.io/kms v0.30.0 h1:ZlnD/ei5lpvUlPw6eLfVvH7d8i9qZ6HwUQgydNVks8g=
|
||||||
k8s.io/kms v0.29.3/go.mod h1:TBGbJKpRUMk59neTMDMddjIDL+D4HuFUbpuiuzmOPg0=
|
k8s.io/kms v0.30.0/go.mod h1:GrMurD0qk3G4yNgGcsCEmepqf9KyyIrTXYR2lyUOJC4=
|
||||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
|
k8s.io/kube-openapi v0.0.0-20240411171206-dc4e619f62f3 h1:SbdLaI6mM6ffDSJCadEaD4IkuPzepLDGlkd2xV0t1uA=
|
||||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
|
k8s.io/kube-openapi v0.0.0-20240411171206-dc4e619f62f3/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
|
||||||
k8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0gQBEuevE/AaBsHY=
|
k8s.io/utils v0.0.0-20240423183400-0849a56e8f22 h1:ao5hUqGhsqdm+bYbjH/pRkCs0unBGe9UyDahzs9zQzQ=
|
||||||
k8s.io/utils v0.0.0-20240310230437-4693a0247e57/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
k8s.io/utils v0.0.0-20240423183400-0849a56e8f22/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 h1:TgtAeesdhpm2SGwkQasmbeqDo8th5wOBA5h/AjTKA4I=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 h1:/U5vjBbQn3RChhv7P11uhYvCSm5G2GaIi5AIGBS6r4c=
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0/go.mod h1:VHVDI/KrK4fjnV61bE2g3sA7tiETLn8sooImelsCx3Y=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0/go.mod h1:z7+wmGM2dfIiLRfrC6jb5kV2Mq/sK1ZP303cxzkV5Y4=
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||||
|
|||||||
@@ -4,3 +4,14 @@ global:
|
|||||||
# endpoints:
|
# endpoints:
|
||||||
# - 1.2.3.4
|
# - 1.2.3.4
|
||||||
# - 4.3.2.1
|
# - 4.3.2.1
|
||||||
|
transformations:
|
||||||
|
- nodeSelector:
|
||||||
|
- matchExpressions:
|
||||||
|
- key: hostname
|
||||||
|
operator: Regexp
|
||||||
|
values:
|
||||||
|
- ^web-.+$
|
||||||
|
annotations:
|
||||||
|
talos.dev/instance-id: "id-{{ .InstanceID }}"
|
||||||
|
labels:
|
||||||
|
node-role.kubernetes.io/web: ""
|
||||||
|
|||||||
123
pkg/nodeselector/selector.go
Normal file
123
pkg/nodeselector/selector.go
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
// Package nodeselector provides a mechanism to match node based on node selector rules.
|
||||||
|
package nodeselector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"slices"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Match returns true if the node metadata matches the node selector rules.
|
||||||
|
func Match(rules []NodeSelectorTerm, fields map[string]string) (bool, error) {
|
||||||
|
if len(rules) == 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rule := range rules {
|
||||||
|
match, err := MatchExpressions(rule.MatchExpressions, fields)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if match {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchExpressions returns true if the node metadata matches the node selector expressions.
|
||||||
|
//
|
||||||
|
//nolint:cyclop,gocyclo
|
||||||
|
func MatchExpressions(rules []NodeSelectorRequirement, fields map[string]string) (bool, error) {
|
||||||
|
if len(rules) == 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
matchs := make([]bool, len(rules))
|
||||||
|
|
||||||
|
for idx, rule := range rules {
|
||||||
|
switch rule.Operator {
|
||||||
|
case NodeSelectorOpIn:
|
||||||
|
if len(rule.Values) == 0 {
|
||||||
|
return false, fmt.Errorf("values must be non-empty for operator '%s'", rule.Operator)
|
||||||
|
}
|
||||||
|
|
||||||
|
if value, ok := fields[strings.ToLower(rule.Key)]; ok {
|
||||||
|
matchs[idx] = slices.Contains(rule.Values, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
case NodeSelectorOpNotIn:
|
||||||
|
if len(rule.Values) == 0 {
|
||||||
|
return false, fmt.Errorf("values must be non-empty for operator '%s'", rule.Operator)
|
||||||
|
}
|
||||||
|
|
||||||
|
if value, ok := fields[strings.ToLower(rule.Key)]; ok {
|
||||||
|
matchs[idx] = !slices.Contains(rule.Values, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
case NodeSelectorOpExists:
|
||||||
|
if len(rule.Values) > 0 {
|
||||||
|
return false, fmt.Errorf("values must be empty for operator %s", rule.Operator)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := fields[strings.ToLower(rule.Key)]; ok {
|
||||||
|
matchs[idx] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
case NodeSelectorOpDoesNotExist:
|
||||||
|
if len(rule.Values) > 0 {
|
||||||
|
return false, fmt.Errorf("values must be empty for operator %s", rule.Operator)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := fields[strings.ToLower(rule.Key)]; !ok {
|
||||||
|
matchs[idx] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
case NodeSelectorOpGt, NodeSelectorOpLt:
|
||||||
|
if len(rule.Values) != 1 {
|
||||||
|
return false, fmt.Errorf("values must have a single element for operator %s", rule.Operator)
|
||||||
|
}
|
||||||
|
|
||||||
|
if value, ok := fields[strings.ToLower(rule.Key)]; ok {
|
||||||
|
lsValue, err := strconv.ParseInt(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("failed to parse value %s as int", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
rValue, err := strconv.ParseInt(rule.Values[0], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("failed to parse value %s as int", rule.Values[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
matchs[idx] = (rule.Operator == NodeSelectorOpGt && lsValue > rValue) || (rule.Operator == NodeSelectorOpLt && lsValue < rValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
case NodeSelectorOpRegexp:
|
||||||
|
if len(rule.Values) != 1 {
|
||||||
|
return false, fmt.Errorf("values must have a single element for operator %s", rule.Operator)
|
||||||
|
}
|
||||||
|
|
||||||
|
if value, ok := fields[strings.ToLower(rule.Key)]; ok {
|
||||||
|
r := regexp.MustCompile(rule.Values[0])
|
||||||
|
|
||||||
|
matchs[idx] = r.MatchString(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false, fmt.Errorf("%s not a valid selector operator", rule.Operator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// And operation between all matchs
|
||||||
|
for _, match := range matchs {
|
||||||
|
if !match {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
186
pkg/nodeselector/selector_test.go
Normal file
186
pkg/nodeselector/selector_test.go
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
package nodeselector_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/siderolabs/talos-cloud-controller-manager/pkg/nodeselector"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMatch(t *testing.T) {
|
||||||
|
fields := map[string]string{
|
||||||
|
"platform": "test-platform",
|
||||||
|
"hostname": "test-hostname",
|
||||||
|
"region": "region-a",
|
||||||
|
"int": "10",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range []struct {
|
||||||
|
name string
|
||||||
|
rules []nodeselector.NodeSelectorTerm
|
||||||
|
fields map[string]string
|
||||||
|
expected bool
|
||||||
|
expectedError error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "NotMatch with empty rules",
|
||||||
|
rules: []nodeselector.NodeSelectorTerm{},
|
||||||
|
fields: fields,
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NotMatch with empty expression rules",
|
||||||
|
rules: []nodeselector.NodeSelectorTerm{
|
||||||
|
{
|
||||||
|
MatchExpressions: []nodeselector.NodeSelectorRequirement{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: fields,
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NotMatch with nonexistent platform",
|
||||||
|
rules: []nodeselector.NodeSelectorTerm{
|
||||||
|
{
|
||||||
|
MatchExpressions: []nodeselector.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "platform",
|
||||||
|
Operator: nodeselector.NodeSelectorOpIn,
|
||||||
|
Values: []string{"bad-platform"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: fields,
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
match, err := nodeselector.Match(tt.rules, tt.fields)
|
||||||
|
|
||||||
|
if tt.expectedError != nil {
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Equal(t, tt.expectedError.Error(), err.Error())
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.expected, match)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMatchExpressions(t *testing.T) {
|
||||||
|
fields := map[string]string{
|
||||||
|
"platform": "test-platform",
|
||||||
|
"hostname": "test-hostname",
|
||||||
|
"region": "region-a",
|
||||||
|
"int": "10",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range []struct {
|
||||||
|
name string
|
||||||
|
rules []nodeselector.NodeSelectorRequirement
|
||||||
|
fields map[string]string
|
||||||
|
expected bool
|
||||||
|
expectedError error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "MatchExpressions with In operator error",
|
||||||
|
rules: []nodeselector.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "platform",
|
||||||
|
Operator: nodeselector.NodeSelectorOpIn,
|
||||||
|
Values: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: fields,
|
||||||
|
expected: false,
|
||||||
|
expectedError: fmt.Errorf("values must be non-empty for operator 'In'"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "MatchExpressions with In and Exists operator",
|
||||||
|
rules: []nodeselector.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "platform",
|
||||||
|
Operator: nodeselector.NodeSelectorOpIn,
|
||||||
|
Values: []string{"test-platform"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "region",
|
||||||
|
Operator: nodeselector.NodeSelectorOpExists,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "fake-key",
|
||||||
|
Operator: nodeselector.NodeSelectorOpDoesNotExist,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: fields,
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "MatchExpressions with GtLt operator",
|
||||||
|
rules: []nodeselector.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "platform",
|
||||||
|
Operator: nodeselector.NodeSelectorOpIn,
|
||||||
|
Values: []string{"test-platform"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "int",
|
||||||
|
Operator: nodeselector.NodeSelectorOpGt,
|
||||||
|
Values: []string{"5"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: fields,
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "MatchExpressions with regexp operator",
|
||||||
|
rules: []nodeselector.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "platform",
|
||||||
|
Operator: nodeselector.NodeSelectorOpIn,
|
||||||
|
Values: []string{"test-platform"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "hostname",
|
||||||
|
Operator: nodeselector.NodeSelectorOpRegexp,
|
||||||
|
Values: []string{"^test.+$"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: fields,
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "MatchExpressions with regexp operator did not match",
|
||||||
|
rules: []nodeselector.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "platform",
|
||||||
|
Operator: nodeselector.NodeSelectorOpIn,
|
||||||
|
Values: []string{"test-platform"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "hostname",
|
||||||
|
Operator: nodeselector.NodeSelectorOpRegexp,
|
||||||
|
Values: []string{"^somename.+$"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: fields,
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
match, err := nodeselector.MatchExpressions(tt.rules, tt.fields)
|
||||||
|
|
||||||
|
if tt.expectedError != nil {
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Equal(t, tt.expectedError.Error(), err.Error())
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.expected, match)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
66
pkg/nodeselector/types.go
Normal file
66
pkg/nodeselector/types.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nodeselector
|
||||||
|
|
||||||
|
// Source(04/2024): https://github.com/kubernetes/kubernetes/blob/master/pkg/apis/core/types.go with modifications (NodeSelectorOpRegexp)
|
||||||
|
|
||||||
|
// NodeSelectorTerm represents expressions and fields required to select nodes.
|
||||||
|
// A null or empty node selector term matches no objects. The requirements of
|
||||||
|
// them are ANDed.
|
||||||
|
// The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.
|
||||||
|
//
|
||||||
|
//nolint:revive
|
||||||
|
type NodeSelectorTerm struct {
|
||||||
|
// A list of node selector requirements by node's labels.
|
||||||
|
MatchExpressions []NodeSelectorRequirement `yaml:"matchExpressions,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeSelectorRequirement is a selector that contains values, a key, and an operator
|
||||||
|
// that relates the key and values.
|
||||||
|
//
|
||||||
|
//nolint:revive
|
||||||
|
type NodeSelectorRequirement struct {
|
||||||
|
// The label key that the selector applies to.
|
||||||
|
Key string `yaml:"key,omitempty"`
|
||||||
|
// Represents a key's relationship to a set of values.
|
||||||
|
// Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
|
||||||
|
Operator NodeSelectorOperator `yaml:"operator,omitempty"`
|
||||||
|
// An array of string values. If the operator is In or NotIn,
|
||||||
|
// the values array must be non-empty. If the operator is Exists or DoesNotExist,
|
||||||
|
// the values array must be empty. If the operator is Gt or Lt, the values
|
||||||
|
// array must have a single element, which will be interpreted as an integer.
|
||||||
|
// This array is replaced during a strategic merge patch.
|
||||||
|
// +optional
|
||||||
|
Values []string `yaml:"values,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeSelectorOperator is the set of operators that can be used in
|
||||||
|
// a node selector requirement.
|
||||||
|
//
|
||||||
|
//nolint:revive
|
||||||
|
type NodeSelectorOperator string
|
||||||
|
|
||||||
|
// These are valid values of NodeSelectorOperator.
|
||||||
|
const (
|
||||||
|
NodeSelectorOpIn NodeSelectorOperator = "In"
|
||||||
|
NodeSelectorOpNotIn NodeSelectorOperator = "NotIn"
|
||||||
|
NodeSelectorOpExists NodeSelectorOperator = "Exists"
|
||||||
|
NodeSelectorOpDoesNotExist NodeSelectorOperator = "DoesNotExist"
|
||||||
|
NodeSelectorOpGt NodeSelectorOperator = "Gt"
|
||||||
|
NodeSelectorOpLt NodeSelectorOperator = "Lt"
|
||||||
|
NodeSelectorOpRegexp NodeSelectorOperator = "Regexp"
|
||||||
|
)
|
||||||
@@ -7,12 +7,16 @@ import (
|
|||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
yaml "gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"github.com/siderolabs/talos-cloud-controller-manager/pkg/transformer"
|
||||||
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type cloudConfig struct {
|
type cloudConfig struct {
|
||||||
// Global configuration.
|
// Global configuration.
|
||||||
Global cloudConfigGlobal `yaml:"global,omitempty"`
|
Global cloudConfigGlobal `yaml:"global,omitempty"`
|
||||||
|
// Node transformation configuration.
|
||||||
|
Transformations []transformer.NodeTerm `yaml:"transformations,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type cloudConfigGlobal struct {
|
type cloudConfigGlobal struct {
|
||||||
|
|||||||
@@ -29,8 +29,21 @@ func TestReadCloudConfig(t *testing.T) {
|
|||||||
|
|
||||||
cfg, err := readCloudConfig(strings.NewReader(`
|
cfg, err := readCloudConfig(strings.NewReader(`
|
||||||
global:
|
global:
|
||||||
approveNodeCSR: true
|
approveNodeCSR: true
|
||||||
preferIPv6: true
|
preferIPv6: true
|
||||||
|
transformations:
|
||||||
|
- name: cluster
|
||||||
|
nodeSelector:
|
||||||
|
- name: cluter-1
|
||||||
|
matchExpressions:
|
||||||
|
- key: platform
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- cluter
|
||||||
|
annotations:
|
||||||
|
cluster-platform: "{{ .Platform }}"
|
||||||
|
labels:
|
||||||
|
node-role.kubernetes.io/web: ""
|
||||||
`))
|
`))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Should succeed when a valid config is provided: %s", err)
|
t.Fatalf("Should succeed when a valid config is provided: %s", err)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package talos
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -12,6 +13,8 @@ import (
|
|||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||||
clientkubernetes "k8s.io/client-go/kubernetes"
|
clientkubernetes "k8s.io/client-go/kubernetes"
|
||||||
cloudproviderapi "k8s.io/cloud-provider/api"
|
cloudproviderapi "k8s.io/cloud-provider/api"
|
||||||
cloudnodeutil "k8s.io/cloud-provider/node/helpers"
|
cloudnodeutil "k8s.io/cloud-provider/node/helpers"
|
||||||
@@ -72,24 +75,79 @@ func getNodeAddresses(config *cloudConfig, platform string, nodeIPs []string, if
|
|||||||
return addresses
|
return addresses
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncNodeLabels(c *client, node *v1.Node, meta *runtime.PlatformMetadataSpec) error {
|
func syncNodeAnnotations(ctx context.Context, c *client, node *v1.Node, nodeAnnotations map[string]string) error {
|
||||||
nodeLabels := node.ObjectMeta.Labels
|
nodeAnnotationsOrig := node.ObjectMeta.Labels
|
||||||
|
annotationsToUpdate := map[string]string{}
|
||||||
|
|
||||||
|
for k, v := range nodeAnnotations {
|
||||||
|
if r, ok := nodeAnnotationsOrig[k]; !ok || r != v {
|
||||||
|
annotationsToUpdate[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(annotationsToUpdate) > 0 {
|
||||||
|
oldData, err := json.Marshal(node)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to marshal the existing node %#v: %w", node, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
newNode := node.DeepCopy()
|
||||||
|
if newNode.Annotations == nil {
|
||||||
|
newNode.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range annotationsToUpdate {
|
||||||
|
newNode.Annotations[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
newData, err := json.Marshal(newNode)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to marshal the new node %#v: %w", newNode, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, &v1.Node{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create a two-way merge patch: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := c.kclient.CoreV1().Nodes().Patch(ctx, node.Name, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}); err != nil {
|
||||||
|
return fmt.Errorf("failed to patch the node: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setTalosNodeLabels(c *client, meta *runtime.PlatformMetadataSpec) map[string]string {
|
||||||
|
if meta == nil {
|
||||||
|
return make(map[string]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
labels := make(map[string]string, 3)
|
||||||
|
|
||||||
|
if meta.Platform != "" {
|
||||||
|
labels[ClusterNodePlatformLabel] = meta.Platform
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.Spot {
|
||||||
|
labels[ClusterNodeLifeCycleLabel] = "spot"
|
||||||
|
}
|
||||||
|
|
||||||
|
if clusterName := c.talos.GetClusterName(); clusterName != "" {
|
||||||
|
labels[ClusterNameNodeLabel] = clusterName
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
func syncNodeLabels(c *client, node *v1.Node, nodeLabels map[string]string) error {
|
||||||
|
nodeLabelsOrig := node.ObjectMeta.Labels
|
||||||
labelsToUpdate := map[string]string{}
|
labelsToUpdate := map[string]string{}
|
||||||
|
|
||||||
if nodeLabels == nil {
|
for k, v := range nodeLabels {
|
||||||
nodeLabels = map[string]string{}
|
if r, ok := nodeLabelsOrig[k]; !ok || r != v {
|
||||||
}
|
labelsToUpdate[k] = v
|
||||||
|
}
|
||||||
if meta.Platform != "" && nodeLabels[ClusterNodePlatformLabel] != meta.Platform {
|
|
||||||
labelsToUpdate[ClusterNodePlatformLabel] = meta.Platform
|
|
||||||
}
|
|
||||||
|
|
||||||
if meta.Spot && nodeLabels[ClusterNodeLifeCycleLabel] != "spot" {
|
|
||||||
labelsToUpdate[ClusterNodeLifeCycleLabel] = "spot"
|
|
||||||
}
|
|
||||||
|
|
||||||
if clusterName := c.talos.GetClusterName(); clusterName != "" && nodeLabels[ClusterNameNodeLabel] != clusterName {
|
|
||||||
labelsToUpdate[ClusterNameNodeLabel] = clusterName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(labelsToUpdate) > 0 {
|
if len(labelsToUpdate) > 0 {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"maps"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -11,6 +12,8 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/siderolabs/talos-cloud-controller-manager/pkg/nodeselector"
|
||||||
|
"github.com/siderolabs/talos-cloud-controller-manager/pkg/transformer"
|
||||||
"github.com/siderolabs/talos/pkg/machinery/resources/network"
|
"github.com/siderolabs/talos/pkg/machinery/resources/network"
|
||||||
"github.com/siderolabs/talos/pkg/machinery/resources/runtime"
|
"github.com/siderolabs/talos/pkg/machinery/resources/runtime"
|
||||||
|
|
||||||
@@ -151,10 +154,30 @@ func TestGetNodeAddresses(t *testing.T) {
|
|||||||
func TestSyncNodeLabels(t *testing.T) {
|
func TestSyncNodeLabels(t *testing.T) {
|
||||||
t.Setenv("TALOSCONFIG", "../../hack/talosconfig")
|
t.Setenv("TALOSCONFIG", "../../hack/talosconfig")
|
||||||
|
|
||||||
cfg := cloudConfig{Global: cloudConfigGlobal{
|
cfg := cloudConfig{
|
||||||
ClusterName: "test-cluster",
|
Global: cloudConfigGlobal{
|
||||||
Endpoints: []string{"127.0.0.1"},
|
ClusterName: "test-cluster",
|
||||||
}}
|
Endpoints: []string{"127.0.0.1"},
|
||||||
|
},
|
||||||
|
Transformations: []transformer.NodeTerm{
|
||||||
|
{
|
||||||
|
NodeSelector: []nodeselector.NodeSelectorTerm{
|
||||||
|
{
|
||||||
|
MatchExpressions: []nodeselector.NodeSelectorRequirement{
|
||||||
|
{
|
||||||
|
Key: "Hostname",
|
||||||
|
Operator: "Regexp",
|
||||||
|
Values: []string{"^web-.+$"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Labels: map[string]string{
|
||||||
|
"node-role.kubernetes.io/web": "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
nodes := &v1.NodeList{
|
nodes := &v1.NodeList{
|
||||||
Items: []v1.Node{
|
Items: []v1.Node{
|
||||||
@@ -167,6 +190,15 @@ func TestSyncNodeLabels(t *testing.T) {
|
|||||||
Name: "node1",
|
Name: "node1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "Node",
|
||||||
|
APIVersion: "v1",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "web-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,9 +290,45 @@ func TestSyncNodeLabels(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "node with custom labels",
|
||||||
|
node: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "web-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
meta: &runtime.PlatformMetadataSpec{
|
||||||
|
Platform: "nocloud",
|
||||||
|
Hostname: "web-1",
|
||||||
|
},
|
||||||
|
expectedError: nil,
|
||||||
|
expectedNode: &v1.Node{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "Node",
|
||||||
|
APIVersion: "v1",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "web-1",
|
||||||
|
Labels: map[string]string{
|
||||||
|
ClusterNameNodeLabel: "test-cluster",
|
||||||
|
ClusterNodePlatformLabel: "nocloud",
|
||||||
|
"node-role.kubernetes.io/web": "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
err := syncNodeLabels(client, tt.node, tt.meta)
|
nodeSpec, err := transformer.TransformNode(client.config.Transformations, tt.meta)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
labels := setTalosNodeLabels(client, tt.meta)
|
||||||
|
|
||||||
|
if nodeSpec != nil && nodeSpec.Labels != nil {
|
||||||
|
maps.Copy(labels, nodeSpec.Labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = syncNodeLabels(client, tt.node, labels)
|
||||||
|
|
||||||
assert.Equal(t, tt.expectedError, err)
|
assert.Equal(t, tt.expectedError, err)
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package talos
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"maps"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/siderolabs/talos-cloud-controller-manager/pkg/transformer"
|
||||||
"github.com/siderolabs/talos-cloud-controller-manager/pkg/utils/net"
|
"github.com/siderolabs/talos-cloud-controller-manager/pkg/utils/net"
|
||||||
"github.com/siderolabs/talos-cloud-controller-manager/pkg/utils/platform"
|
"github.com/siderolabs/talos-cloud-controller-manager/pkg/utils/platform"
|
||||||
"github.com/siderolabs/talos/pkg/machinery/resources/runtime"
|
"github.com/siderolabs/talos/pkg/machinery/resources/runtime"
|
||||||
@@ -44,6 +46,8 @@ func (i *instances) InstanceShutdown(_ context.Context, node *v1.Node) (bool, er
|
|||||||
// InstanceMetadata returns the instance's metadata. The values returned in InstanceMetadata are
|
// InstanceMetadata returns the instance's metadata. The values returned in InstanceMetadata are
|
||||||
// translated into specific fields in the Node object on registration.
|
// translated into specific fields in the Node object on registration.
|
||||||
// Use the node.name or node.spec.providerID field to find the node in the cloud provider.
|
// Use the node.name or node.spec.providerID field to find the node in the cloud provider.
|
||||||
|
//
|
||||||
|
//nolint:gocyclo,cyclop
|
||||||
func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloudprovider.InstanceMetadata, error) {
|
func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloudprovider.InstanceMetadata, error) {
|
||||||
klog.V(4).Info("instances.InstanceMetadata() called, node: ", node.Name)
|
klog.V(4).Info("instances.InstanceMetadata() called, node: ", node.Name)
|
||||||
|
|
||||||
@@ -90,6 +94,11 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodeSpec, err := transformer.TransformNode(i.c.config.Transformations, meta)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error transforming node: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
ifaces, err := i.c.getNodeIfaces(ctx, nodeIP)
|
ifaces, err := i.c.getNodeIfaces(ctx, nodeIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error getting interfaces list from the node %s: %w", node.Name, err)
|
return nil, fmt.Errorf("error getting interfaces list from the node %s: %w", node.Name, err)
|
||||||
@@ -112,7 +121,23 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syncNodeLabels(i.c, node, meta); err != nil {
|
if nodeSpec != nil && nodeSpec.Annotations != nil {
|
||||||
|
klog.V(4).Infof("instances.InstanceMetadata() node %s has annotations: %+v", node.Name, nodeSpec.Annotations)
|
||||||
|
|
||||||
|
if err := syncNodeAnnotations(ctx, i.c, node, nodeSpec.Annotations); err != nil {
|
||||||
|
klog.Errorf("failed update annotations for node %s, %v", node.Name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeLabels := setTalosNodeLabels(i.c, meta)
|
||||||
|
|
||||||
|
if nodeSpec != nil && nodeSpec.Labels != nil {
|
||||||
|
klog.V(4).Infof("instances.InstanceMetadata() node %s has labels: %+v", node.Name, nodeSpec.Labels)
|
||||||
|
|
||||||
|
maps.Copy(nodeLabels, nodeSpec.Labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := syncNodeLabels(i.c, node, nodeLabels); err != nil {
|
||||||
klog.Errorf("failed update labels for node %s, %v", node.Name, err)
|
klog.Errorf("failed update labels for node %s, %v", node.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
169
pkg/transformer/transformer.go
Normal file
169
pkg/transformer/transformer.go
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
// Package transformer provides a mechanism to transform node specification based on node transformation rules.
|
||||||
|
package transformer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"reflect"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/siderolabs/talos-cloud-controller-manager/pkg/nodeselector"
|
||||||
|
"github.com/siderolabs/talos/pkg/machinery/resources/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NodeTerm represents expressions and fields to transform node metadata.
|
||||||
|
type NodeTerm struct {
|
||||||
|
Name string `yaml:"name,omitempty"`
|
||||||
|
NodeSelector []nodeselector.NodeSelectorTerm `yaml:"nodeSelector,omitempty"`
|
||||||
|
Annotations map[string]string `yaml:"annotations,omitempty"`
|
||||||
|
Labels map[string]string `yaml:"labels,omitempty"`
|
||||||
|
PlatformMetadata map[string]string `yaml:"platformMetadata,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeSpec represents the transformed node specifcations.
|
||||||
|
type NodeSpec struct {
|
||||||
|
Annotations map[string]string
|
||||||
|
Labels map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
var prohibitedPlatformMetadataKeys = []string{"hostname", "platform"}
|
||||||
|
|
||||||
|
// TransformNode transforms the node metadata based on the node transformation rules.
|
||||||
|
func TransformNode(terms []NodeTerm, platformMetadata *runtime.PlatformMetadataSpec) (*NodeSpec, error) {
|
||||||
|
if len(terms) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata := metadataFromStruct(platformMetadata)
|
||||||
|
|
||||||
|
for _, term := range terms {
|
||||||
|
match, err := nodeselector.Match(term.NodeSelector, metadata)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to transformer annotation '%q': %w", k, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
node.Annotations[k] = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if term.Labels != nil {
|
||||||
|
for k, v := range term.Labels {
|
||||||
|
t, err := executeTemplate(v, platformMetadata)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to transformer label '%s': %w", k, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
node.Labels[k] = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if term.PlatformMetadata != nil {
|
||||||
|
p := reflect.ValueOf(platformMetadata)
|
||||||
|
ps := p.Elem()
|
||||||
|
|
||||||
|
for k, v := range term.PlatformMetadata {
|
||||||
|
if slices.Contains(prohibitedPlatformMetadataKeys, strings.ToLower(k)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := executeTemplate(v, platformMetadata)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to transformer platform metadata '%s': %w", k, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f := ps.FieldByNameFunc(func(fieldName string) bool {
|
||||||
|
return strings.EqualFold(fieldName, k)
|
||||||
|
})
|
||||||
|
|
||||||
|
if f.IsValid() {
|
||||||
|
switch f.Kind() { //nolint:exhaustive
|
||||||
|
case reflect.Bool:
|
||||||
|
f.SetBool(t == "true")
|
||||||
|
case reflect.String:
|
||||||
|
f.SetString(strings.TrimSpace(t))
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported platform metadata field %s", k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeTemplate(tmpl string, data interface{}) (string, error) {
|
||||||
|
t, err := template.New("transformer").Parse(tmpl)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to parse template %q: %w", tmpl, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := t.Execute(&buf, data); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func metadataFromStruct(in *runtime.PlatformMetadataSpec) map[string]string {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata := make(map[string]string)
|
||||||
|
|
||||||
|
v := reflect.ValueOf(in)
|
||||||
|
if v.Kind() == reflect.Ptr {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Kind() == reflect.Struct {
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
// skip unexported fields
|
||||||
|
if !v.Field(i).CanInterface() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tag := v.Type().Field(i).Tag.Get("yaml")
|
||||||
|
if tag == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldName := strings.ToLower(strings.Split(tag, ",")[0])
|
||||||
|
|
||||||
|
reflectedValue := reflect.Indirect(v.Field(i))
|
||||||
|
if reflectedValue.IsValid() {
|
||||||
|
switch reflectedValue.Kind() { //nolint:exhaustive
|
||||||
|
case reflect.Bool:
|
||||||
|
metadata[fieldName] = fmt.Sprintf("%t", reflectedValue.Bool())
|
||||||
|
case reflect.String:
|
||||||
|
v := reflectedValue.String()
|
||||||
|
if v != "" {
|
||||||
|
metadata[fieldName] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return metadata
|
||||||
|
}
|
||||||
210
pkg/transformer/transformer_test.go
Normal file
210
pkg/transformer/transformer_test.go
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
package transformer_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/siderolabs/talos-cloud-controller-manager/pkg/transformer"
|
||||||
|
"github.com/siderolabs/talos/pkg/machinery/resources/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMatch(t *testing.T) {
|
||||||
|
for _, tt := range []struct {
|
||||||
|
name string
|
||||||
|
terms []transformer.NodeTerm
|
||||||
|
metadata runtime.PlatformMetadataSpec
|
||||||
|
expected *transformer.NodeSpec
|
||||||
|
expectedMeta *runtime.PlatformMetadataSpec
|
||||||
|
expectedError error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Empty rules",
|
||||||
|
terms: []transformer.NodeTerm{},
|
||||||
|
metadata: runtime.PlatformMetadataSpec{
|
||||||
|
Platform: "test-platform",
|
||||||
|
Hostname: "test-hostname",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Transform labels",
|
||||||
|
terms: []transformer.NodeTerm{
|
||||||
|
{
|
||||||
|
Name: "my-transformer",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"my-label-name": "my-value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadata: runtime.PlatformMetadataSpec{
|
||||||
|
Platform: "test-platform",
|
||||||
|
Hostname: "test-hostname",
|
||||||
|
},
|
||||||
|
expected: &transformer.NodeSpec{
|
||||||
|
Annotations: map[string]string{},
|
||||||
|
Labels: map[string]string{
|
||||||
|
"my-label-name": "my-value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Transform annotations and labels",
|
||||||
|
terms: []transformer.NodeTerm{
|
||||||
|
{
|
||||||
|
Name: "my-transformer",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"my-label-name": "my-value",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"my-annotation-name": "my-annotation-value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadata: runtime.PlatformMetadataSpec{
|
||||||
|
Platform: "test-platform",
|
||||||
|
Hostname: "test-hostname",
|
||||||
|
},
|
||||||
|
expected: &transformer.NodeSpec{
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"my-annotation-name": "my-annotation-value",
|
||||||
|
},
|
||||||
|
Labels: map[string]string{
|
||||||
|
"my-label-name": "my-value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Transform bad template",
|
||||||
|
terms: []transformer.NodeTerm{
|
||||||
|
{
|
||||||
|
Name: "my-transformer",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"label-template": "my-value-{{ .Spot",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadata: runtime.PlatformMetadataSpec{
|
||||||
|
Platform: "test-platform",
|
||||||
|
Hostname: "test-hostname",
|
||||||
|
},
|
||||||
|
expectedError: fmt.Errorf("failed to transformer label 'label-template': failed to parse template \"my-value-{{ .Spot\": template: transformer:1: unclosed action"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Transform annotations with template",
|
||||||
|
terms: []transformer.NodeTerm{
|
||||||
|
{
|
||||||
|
Name: "my-transformer",
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"annotation-template": "my-value-{{ .Platform }}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadata: runtime.PlatformMetadataSpec{
|
||||||
|
Platform: "test-platform",
|
||||||
|
Hostname: "test-hostname",
|
||||||
|
},
|
||||||
|
expected: &transformer.NodeSpec{
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"annotation-template": "my-value-test-platform",
|
||||||
|
},
|
||||||
|
Labels: map[string]string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Transform labels with template and missing metadata fields",
|
||||||
|
terms: []transformer.NodeTerm{
|
||||||
|
{
|
||||||
|
Name: "my-transformer",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"label-template": "my-value-{{ .Spot }}-{{ .Zone }}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadata: runtime.PlatformMetadataSpec{
|
||||||
|
Platform: "test-platform",
|
||||||
|
Hostname: "test-hostname",
|
||||||
|
},
|
||||||
|
expected: &transformer.NodeSpec{
|
||||||
|
Annotations: map[string]string{},
|
||||||
|
Labels: map[string]string{
|
||||||
|
"label-template": "my-value-false-",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Transform metadata fields",
|
||||||
|
terms: []transformer.NodeTerm{
|
||||||
|
{
|
||||||
|
Name: "my-transformer",
|
||||||
|
PlatformMetadata: map[string]string{
|
||||||
|
"Spot": "true",
|
||||||
|
"Zone": "us-west1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadata: runtime.PlatformMetadataSpec{
|
||||||
|
Platform: "test-platform",
|
||||||
|
Hostname: "test-hostname",
|
||||||
|
},
|
||||||
|
expected: &transformer.NodeSpec{
|
||||||
|
Annotations: map[string]string{},
|
||||||
|
Labels: map[string]string{},
|
||||||
|
},
|
||||||
|
expectedMeta: &runtime.PlatformMetadataSpec{
|
||||||
|
Platform: "test-platform",
|
||||||
|
Hostname: "test-hostname",
|
||||||
|
Spot: true,
|
||||||
|
Zone: "us-west1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Transform metadata with wrong fields",
|
||||||
|
terms: []transformer.NodeTerm{
|
||||||
|
{
|
||||||
|
Name: "my-transformer",
|
||||||
|
PlatformMetadata: map[string]string{
|
||||||
|
"Hostname": "fake-hostname",
|
||||||
|
"spot": "true",
|
||||||
|
"zoNe": "us-west1",
|
||||||
|
"wrong": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadata: runtime.PlatformMetadataSpec{
|
||||||
|
Platform: "test-platform",
|
||||||
|
Hostname: "test-hostname",
|
||||||
|
},
|
||||||
|
expected: &transformer.NodeSpec{
|
||||||
|
Annotations: map[string]string{},
|
||||||
|
Labels: map[string]string{},
|
||||||
|
},
|
||||||
|
expectedMeta: &runtime.PlatformMetadataSpec{
|
||||||
|
Platform: "test-platform",
|
||||||
|
Hostname: "test-hostname",
|
||||||
|
Spot: true,
|
||||||
|
Zone: "us-west1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
node, err := transformer.TransformNode(tt.terms, &tt.metadata)
|
||||||
|
|
||||||
|
if tt.expectedError != nil {
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.Equal(t, tt.expectedError.Error(), err.Error())
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
if tt.expected != nil {
|
||||||
|
assert.NotNil(t, node)
|
||||||
|
assert.EqualValues(t, tt.expected, node)
|
||||||
|
|
||||||
|
if tt.expectedMeta != nil {
|
||||||
|
assert.EqualValues(t, tt.expectedMeta, &tt.metadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user