From 713d92702e74c3c8fd5caf85584a15ffb3ada067 Mon Sep 17 00:00:00 2001 From: Adam Janikowski <12255597+ajanikow@users.noreply.github.com> Date: Fri, 6 Sep 2024 11:52:37 +0200 Subject: [PATCH] [Feature] Scheduler Handler (#1716) --- CHANGELOG.md | 1 + README.md | 3 +- .../templates/deployment.yaml | 3 + .../cluster-role-binding.yaml | 26 +++ .../scheduler-operator/cluster-role.yaml | 22 ++ .../scheduler-operator/role-binding.yaml | 25 +++ .../templates/scheduler-operator/role.yaml | 32 +++ .../templates/deployment.yaml | 3 + .../cluster-role-binding.yaml | 26 +++ .../scheduler-operator/cluster-role.yaml | 22 ++ .../scheduler-operator/role-binding.yaml | 25 +++ .../templates/scheduler-operator/role.yaml | 32 +++ .../templates/deployment.yaml | 3 + .../cluster-role-binding.yaml | 26 +++ .../scheduler-operator/cluster-role.yaml | 22 ++ .../scheduler-operator/role-binding.yaml | 25 +++ .../templates/scheduler-operator/role.yaml | 32 +++ chart/kube-arangodb/templates/deployment.yaml | 3 + .../cluster-role-binding.yaml | 26 +++ .../scheduler-operator/cluster-role.yaml | 22 ++ .../scheduler-operator/role-binding.yaml | 25 +++ .../templates/scheduler-operator/role.yaml | 32 +++ chart/kube-arangodb/values.yaml | 1 + cmd/cmd.go | 18 +- docs/cli/arangodb_operator.md | 3 +- pkg/apis/scheduler/v1alpha1/profile.go | 8 + pkg/apis/scheduler/v1beta1/profile.go | 8 + pkg/apis/scheduler/v1beta1/profile_status.go | 3 +- pkg/deployment/resources/inspector/ap.go | 192 ++++++++++++++++++ .../resources/inspector/ap_anonymous.go | 45 ++++ pkg/deployment/resources/inspector/ap_gvk.go | 43 ++++ pkg/deployment/resources/inspector/ap_mod.go | 47 +++++ .../resources/inspector/ap_v1beta1.go | 138 +++++++++++++ .../resources/inspector/inspector.go | 19 ++ .../resources/inspector/inspector_test.go | 4 +- .../resources/inspector/pdbs_version_test.go | 2 +- .../resources/inspector/throttles.go | 1 + pkg/handlers/networking/route/suite_test.go | 4 +- pkg/handlers/scheduler/profile/handler.go | 104 ++++++++++ .../scheduler/profile/handler_test.go | 59 ++++++ pkg/handlers/scheduler/profile/local.go | 38 ++++ pkg/handlers/scheduler/profile/register.go | 60 ++++++ pkg/handlers/scheduler/profile/suite_test.go | 61 ++++++ pkg/operator/operator.go | 32 +++ pkg/operatorV2/update_wraps.go | 5 + pkg/server/server.go | 5 + pkg/util/constants/constants.go | 1 + .../inspector/arangoprofile/definition.go | 44 ++++ .../inspector/arangoprofile/v1beta1/loader.go | 53 +++++ .../inspector/arangoprofile/v1beta1/reader.go | 50 +++++ .../inspector/constants/ap_constants.go | 66 ++++++ pkg/util/k8sutil/inspector/constants/gvk.go | 8 +- .../k8sutil/inspector/constants/gvk_test.go | 7 +- .../inspector/definitions/components.go | 2 + pkg/util/k8sutil/inspector/inspector.go | 2 + pkg/util/k8sutil/inspector/mods/mods.go | 6 + .../k8sutil/inspector/throttle/throttle.go | 14 +- 57 files changed, 1572 insertions(+), 17 deletions(-) create mode 100644 chart/kube-arangodb-arm64/templates/scheduler-operator/cluster-role-binding.yaml create mode 100644 chart/kube-arangodb-arm64/templates/scheduler-operator/cluster-role.yaml create mode 100644 chart/kube-arangodb-arm64/templates/scheduler-operator/role-binding.yaml create mode 100644 chart/kube-arangodb-arm64/templates/scheduler-operator/role.yaml create mode 100644 chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/cluster-role-binding.yaml create mode 100644 chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/cluster-role.yaml create mode 100644 chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/role-binding.yaml create mode 100644 chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/role.yaml create mode 100644 chart/kube-arangodb-enterprise/templates/scheduler-operator/cluster-role-binding.yaml create mode 100644 chart/kube-arangodb-enterprise/templates/scheduler-operator/cluster-role.yaml create mode 100644 chart/kube-arangodb-enterprise/templates/scheduler-operator/role-binding.yaml create mode 100644 chart/kube-arangodb-enterprise/templates/scheduler-operator/role.yaml create mode 100644 chart/kube-arangodb/templates/scheduler-operator/cluster-role-binding.yaml create mode 100644 chart/kube-arangodb/templates/scheduler-operator/cluster-role.yaml create mode 100644 chart/kube-arangodb/templates/scheduler-operator/role-binding.yaml create mode 100644 chart/kube-arangodb/templates/scheduler-operator/role.yaml create mode 100644 pkg/deployment/resources/inspector/ap.go create mode 100644 pkg/deployment/resources/inspector/ap_anonymous.go create mode 100644 pkg/deployment/resources/inspector/ap_gvk.go create mode 100644 pkg/deployment/resources/inspector/ap_mod.go create mode 100644 pkg/deployment/resources/inspector/ap_v1beta1.go create mode 100644 pkg/handlers/scheduler/profile/handler.go create mode 100644 pkg/handlers/scheduler/profile/handler_test.go create mode 100644 pkg/handlers/scheduler/profile/local.go create mode 100644 pkg/handlers/scheduler/profile/register.go create mode 100644 pkg/handlers/scheduler/profile/suite_test.go create mode 100644 pkg/util/k8sutil/inspector/arangoprofile/definition.go create mode 100644 pkg/util/k8sutil/inspector/arangoprofile/v1beta1/loader.go create mode 100644 pkg/util/k8sutil/inspector/arangoprofile/v1beta1/reader.go create mode 100644 pkg/util/k8sutil/inspector/constants/ap_constants.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c076e232..3064aa46e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ - (Feature) (Gateway) SNI and Authz support - (Maintenance) Bump Examples to ArangoDB 3.12 - (Feature) (Gateway) ArangoDB JWT Auth Integration +- (Feature) Scheduler Handler ## [1.2.42](https://github.com/arangodb/kube-arangodb/tree/1.2.42) (2024-07-23) - (Maintenance) Go 1.22.4 & Kubernetes 1.29.6 libraries diff --git a/README.md b/README.md index 71e7392a3..55c1af195 100644 --- a/README.md +++ b/README.md @@ -182,7 +182,7 @@ Flags: --kubernetes.max-batch-size int Size of batch during objects read (default 256) --kubernetes.qps float32 Number of queries per second for k8s API (default 15) --log.format string Set log format. Allowed values: 'pretty', 'JSON'. If empty, default format is used (default "pretty") - --log.level stringArray Set log levels in format or =. Possible loggers: action, agency, api-server, assertion, backup-operator, chaos-monkey, crd, deployment, deployment-ci, deployment-reconcile, deployment-replication, deployment-resilience, deployment-resources, deployment-storage, deployment-storage-pc, deployment-storage-service, http, inspector, integration-config-v1, integration-envoy-auth-v3, integrations, k8s-client, kubernetes-informer, monitor, networking-route-operator, operator, operator-arangojob-handler, operator-v2, operator-v2-event, operator-v2-worker, panics, pod_compare, root, root-event-recorder, server, server-authentication (default [info]) + --log.level stringArray Set log levels in format or =. Possible loggers: action, agency, api-server, assertion, backup-operator, chaos-monkey, crd, deployment, deployment-ci, deployment-reconcile, deployment-replication, deployment-resilience, deployment-resources, deployment-storage, deployment-storage-pc, deployment-storage-service, http, inspector, integration-config-v1, integration-envoy-auth-v3, integrations, k8s-client, kubernetes-informer, monitor, networking-route-operator, operator, operator-arangojob-handler, operator-v2, operator-v2-event, operator-v2-worker, panics, pod_compare, root, root-event-recorder, scheduler-profile-operator, server, server-authentication (default [info]) --log.sampling If true, operator will try to minimize duplication of logging events (default true) --memory-limit uint Define memory limit for hard shutdown and the dump of goroutines. Used for testing --metrics.excluded-prefixes stringArray List of the excluded metrics prefixes @@ -196,6 +196,7 @@ Flags: --operator.networking Enable to run the Networking operator --operator.reconciliation.retry.count int Count of retries during Object Update operations in the Reconciliation loop (default 25) --operator.reconciliation.retry.delay duration Delay between Object Update operations in the Reconciliation loop (default 1s) + --operator.scheduler Enable to run the Scheduler operator --operator.storage Enable to run the ArangoLocalStorage operator --operator.version Enable only version endpoint in Operator --reconciliation.delay duration Delay between reconciliation loops (<= 0 -> Disabled) diff --git a/chart/kube-arangodb-arm64/templates/deployment.yaml b/chart/kube-arangodb-arm64/templates/deployment.yaml index 49958189d..3488df768 100644 --- a/chart/kube-arangodb-arm64/templates/deployment.yaml +++ b/chart/kube-arangodb-arm64/templates/deployment.yaml @@ -120,6 +120,9 @@ spec: {{ if .Values.operator.features.networking }} - --operator.networking {{- end }} +{{ if .Values.operator.features.scheduler }} + - --operator.scheduler +{{- end }} {{ if .Values.operator.features.k8sToK8sClusterSync }} - --operator.k2k-cluster-sync {{- end }} diff --git a/chart/kube-arangodb-arm64/templates/scheduler-operator/cluster-role-binding.yaml b/chart/kube-arangodb-arm64/templates/scheduler-operator/cluster-role-binding.yaml new file mode 100644 index 000000000..aa1dd27d9 --- /dev/null +++ b/chart/kube-arangodb-arm64/templates/scheduler-operator/cluster-role-binding.yaml @@ -0,0 +1,26 @@ +{{ if .Values.rbac.enabled -}} +{{ if not (eq .Values.operator.scope "namespaced") -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "kube-arangodb.rbac-cluster" . }}-scheduler + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "kube-arangodb.rbac-cluster" . }}-scheduler +subjects: + - kind: ServiceAccount + name: {{ template "kube-arangodb.operatorName" . }} + namespace: {{ .Release.Namespace }} + +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb-arm64/templates/scheduler-operator/cluster-role.yaml b/chart/kube-arangodb-arm64/templates/scheduler-operator/cluster-role.yaml new file mode 100644 index 000000000..12e4b2fd3 --- /dev/null +++ b/chart/kube-arangodb-arm64/templates/scheduler-operator/cluster-role.yaml @@ -0,0 +1,22 @@ +{{ if .Values.rbac.enabled -}} +{{ if not (eq .Values.operator.scope "namespaced") -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "kube-arangodb.rbac-cluster" . }}-scheduler + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +rules: + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] + +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb-arm64/templates/scheduler-operator/role-binding.yaml b/chart/kube-arangodb-arm64/templates/scheduler-operator/role-binding.yaml new file mode 100644 index 000000000..02e1eb816 --- /dev/null +++ b/chart/kube-arangodb-arm64/templates/scheduler-operator/role-binding.yaml @@ -0,0 +1,25 @@ +{{ if .Values.rbac.enabled -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "kube-arangodb.rbac" . }}-scheduler + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "kube-arangodb.rbac" . }}-scheduler +subjects: + - kind: ServiceAccount + name: {{ template "kube-arangodb.operatorName" . }} + namespace: {{ .Release.Namespace }} + +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb-arm64/templates/scheduler-operator/role.yaml b/chart/kube-arangodb-arm64/templates/scheduler-operator/role.yaml new file mode 100644 index 000000000..46a3d92f0 --- /dev/null +++ b/chart/kube-arangodb-arm64/templates/scheduler-operator/role.yaml @@ -0,0 +1,32 @@ +{{ if .Values.rbac.enabled -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "kube-arangodb.rbac" . }}-scheduler + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +rules: + - apiGroups: + - "scheduler.arangodb.com" + resources: + - "arangoprofiles" + - "arangoprofiles/status" + verbs: + - "*" + - apiGroups: + - "database.arangodb.com" + resources: + - "arangodeployments" + verbs: + - "get" + - "list" + - "watch" +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb-enterprise-arm64/templates/deployment.yaml b/chart/kube-arangodb-enterprise-arm64/templates/deployment.yaml index 49958189d..3488df768 100644 --- a/chart/kube-arangodb-enterprise-arm64/templates/deployment.yaml +++ b/chart/kube-arangodb-enterprise-arm64/templates/deployment.yaml @@ -120,6 +120,9 @@ spec: {{ if .Values.operator.features.networking }} - --operator.networking {{- end }} +{{ if .Values.operator.features.scheduler }} + - --operator.scheduler +{{- end }} {{ if .Values.operator.features.k8sToK8sClusterSync }} - --operator.k2k-cluster-sync {{- end }} diff --git a/chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/cluster-role-binding.yaml b/chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/cluster-role-binding.yaml new file mode 100644 index 000000000..aa1dd27d9 --- /dev/null +++ b/chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/cluster-role-binding.yaml @@ -0,0 +1,26 @@ +{{ if .Values.rbac.enabled -}} +{{ if not (eq .Values.operator.scope "namespaced") -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "kube-arangodb.rbac-cluster" . }}-scheduler + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "kube-arangodb.rbac-cluster" . }}-scheduler +subjects: + - kind: ServiceAccount + name: {{ template "kube-arangodb.operatorName" . }} + namespace: {{ .Release.Namespace }} + +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/cluster-role.yaml b/chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/cluster-role.yaml new file mode 100644 index 000000000..12e4b2fd3 --- /dev/null +++ b/chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/cluster-role.yaml @@ -0,0 +1,22 @@ +{{ if .Values.rbac.enabled -}} +{{ if not (eq .Values.operator.scope "namespaced") -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "kube-arangodb.rbac-cluster" . }}-scheduler + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +rules: + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] + +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/role-binding.yaml b/chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/role-binding.yaml new file mode 100644 index 000000000..02e1eb816 --- /dev/null +++ b/chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/role-binding.yaml @@ -0,0 +1,25 @@ +{{ if .Values.rbac.enabled -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "kube-arangodb.rbac" . }}-scheduler + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "kube-arangodb.rbac" . }}-scheduler +subjects: + - kind: ServiceAccount + name: {{ template "kube-arangodb.operatorName" . }} + namespace: {{ .Release.Namespace }} + +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/role.yaml b/chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/role.yaml new file mode 100644 index 000000000..46a3d92f0 --- /dev/null +++ b/chart/kube-arangodb-enterprise-arm64/templates/scheduler-operator/role.yaml @@ -0,0 +1,32 @@ +{{ if .Values.rbac.enabled -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "kube-arangodb.rbac" . }}-scheduler + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +rules: + - apiGroups: + - "scheduler.arangodb.com" + resources: + - "arangoprofiles" + - "arangoprofiles/status" + verbs: + - "*" + - apiGroups: + - "database.arangodb.com" + resources: + - "arangodeployments" + verbs: + - "get" + - "list" + - "watch" +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb-enterprise/templates/deployment.yaml b/chart/kube-arangodb-enterprise/templates/deployment.yaml index 49958189d..3488df768 100644 --- a/chart/kube-arangodb-enterprise/templates/deployment.yaml +++ b/chart/kube-arangodb-enterprise/templates/deployment.yaml @@ -120,6 +120,9 @@ spec: {{ if .Values.operator.features.networking }} - --operator.networking {{- end }} +{{ if .Values.operator.features.scheduler }} + - --operator.scheduler +{{- end }} {{ if .Values.operator.features.k8sToK8sClusterSync }} - --operator.k2k-cluster-sync {{- end }} diff --git a/chart/kube-arangodb-enterprise/templates/scheduler-operator/cluster-role-binding.yaml b/chart/kube-arangodb-enterprise/templates/scheduler-operator/cluster-role-binding.yaml new file mode 100644 index 000000000..aa1dd27d9 --- /dev/null +++ b/chart/kube-arangodb-enterprise/templates/scheduler-operator/cluster-role-binding.yaml @@ -0,0 +1,26 @@ +{{ if .Values.rbac.enabled -}} +{{ if not (eq .Values.operator.scope "namespaced") -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "kube-arangodb.rbac-cluster" . }}-scheduler + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "kube-arangodb.rbac-cluster" . }}-scheduler +subjects: + - kind: ServiceAccount + name: {{ template "kube-arangodb.operatorName" . }} + namespace: {{ .Release.Namespace }} + +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb-enterprise/templates/scheduler-operator/cluster-role.yaml b/chart/kube-arangodb-enterprise/templates/scheduler-operator/cluster-role.yaml new file mode 100644 index 000000000..12e4b2fd3 --- /dev/null +++ b/chart/kube-arangodb-enterprise/templates/scheduler-operator/cluster-role.yaml @@ -0,0 +1,22 @@ +{{ if .Values.rbac.enabled -}} +{{ if not (eq .Values.operator.scope "namespaced") -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "kube-arangodb.rbac-cluster" . }}-scheduler + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +rules: + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] + +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb-enterprise/templates/scheduler-operator/role-binding.yaml b/chart/kube-arangodb-enterprise/templates/scheduler-operator/role-binding.yaml new file mode 100644 index 000000000..02e1eb816 --- /dev/null +++ b/chart/kube-arangodb-enterprise/templates/scheduler-operator/role-binding.yaml @@ -0,0 +1,25 @@ +{{ if .Values.rbac.enabled -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "kube-arangodb.rbac" . }}-scheduler + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "kube-arangodb.rbac" . }}-scheduler +subjects: + - kind: ServiceAccount + name: {{ template "kube-arangodb.operatorName" . }} + namespace: {{ .Release.Namespace }} + +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb-enterprise/templates/scheduler-operator/role.yaml b/chart/kube-arangodb-enterprise/templates/scheduler-operator/role.yaml new file mode 100644 index 000000000..46a3d92f0 --- /dev/null +++ b/chart/kube-arangodb-enterprise/templates/scheduler-operator/role.yaml @@ -0,0 +1,32 @@ +{{ if .Values.rbac.enabled -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "kube-arangodb.rbac" . }}-scheduler + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +rules: + - apiGroups: + - "scheduler.arangodb.com" + resources: + - "arangoprofiles" + - "arangoprofiles/status" + verbs: + - "*" + - apiGroups: + - "database.arangodb.com" + resources: + - "arangodeployments" + verbs: + - "get" + - "list" + - "watch" +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb/templates/deployment.yaml b/chart/kube-arangodb/templates/deployment.yaml index 49958189d..3488df768 100644 --- a/chart/kube-arangodb/templates/deployment.yaml +++ b/chart/kube-arangodb/templates/deployment.yaml @@ -120,6 +120,9 @@ spec: {{ if .Values.operator.features.networking }} - --operator.networking {{- end }} +{{ if .Values.operator.features.scheduler }} + - --operator.scheduler +{{- end }} {{ if .Values.operator.features.k8sToK8sClusterSync }} - --operator.k2k-cluster-sync {{- end }} diff --git a/chart/kube-arangodb/templates/scheduler-operator/cluster-role-binding.yaml b/chart/kube-arangodb/templates/scheduler-operator/cluster-role-binding.yaml new file mode 100644 index 000000000..aa1dd27d9 --- /dev/null +++ b/chart/kube-arangodb/templates/scheduler-operator/cluster-role-binding.yaml @@ -0,0 +1,26 @@ +{{ if .Values.rbac.enabled -}} +{{ if not (eq .Values.operator.scope "namespaced") -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "kube-arangodb.rbac-cluster" . }}-scheduler + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "kube-arangodb.rbac-cluster" . }}-scheduler +subjects: + - kind: ServiceAccount + name: {{ template "kube-arangodb.operatorName" . }} + namespace: {{ .Release.Namespace }} + +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb/templates/scheduler-operator/cluster-role.yaml b/chart/kube-arangodb/templates/scheduler-operator/cluster-role.yaml new file mode 100644 index 000000000..12e4b2fd3 --- /dev/null +++ b/chart/kube-arangodb/templates/scheduler-operator/cluster-role.yaml @@ -0,0 +1,22 @@ +{{ if .Values.rbac.enabled -}} +{{ if not (eq .Values.operator.scope "namespaced") -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "kube-arangodb.rbac-cluster" . }}-scheduler + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +rules: + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] + +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb/templates/scheduler-operator/role-binding.yaml b/chart/kube-arangodb/templates/scheduler-operator/role-binding.yaml new file mode 100644 index 000000000..02e1eb816 --- /dev/null +++ b/chart/kube-arangodb/templates/scheduler-operator/role-binding.yaml @@ -0,0 +1,25 @@ +{{ if .Values.rbac.enabled -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "kube-arangodb.rbac" . }}-scheduler + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "kube-arangodb.rbac" . }}-scheduler +subjects: + - kind: ServiceAccount + name: {{ template "kube-arangodb.operatorName" . }} + namespace: {{ .Release.Namespace }} + +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb/templates/scheduler-operator/role.yaml b/chart/kube-arangodb/templates/scheduler-operator/role.yaml new file mode 100644 index 000000000..46a3d92f0 --- /dev/null +++ b/chart/kube-arangodb/templates/scheduler-operator/role.yaml @@ -0,0 +1,32 @@ +{{ if .Values.rbac.enabled -}} +{{ if .Values.operator.features.scheduler -}} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "kube-arangodb.rbac" . }}-scheduler + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ template "kube-arangodb.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + release: {{ .Release.Name }} +rules: + - apiGroups: + - "scheduler.arangodb.com" + resources: + - "arangoprofiles" + - "arangoprofiles/status" + verbs: + - "*" + - apiGroups: + - "database.arangodb.com" + resources: + - "arangodeployments" + verbs: + - "get" + - "list" + - "watch" +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/kube-arangodb/values.yaml b/chart/kube-arangodb/values.yaml index 98ac2e00f..980cd6866 100644 --- a/chart/kube-arangodb/values.yaml +++ b/chart/kube-arangodb/values.yaml @@ -35,6 +35,7 @@ operator: ml: false analytics: false networking: true + scheduler: true tolerations: [] rbac: enabled: true diff --git a/cmd/cmd.go b/cmd/cmd.go index bafe078fa..023e89a99 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -120,6 +120,7 @@ var ( enableML bool // Run ml operator enableAnalytics bool // Run analytics operator enableNetworking bool // Run networking operator + enableScheduler bool // Run scheduler operator versionOnly bool // Run only version endpoint, explicitly disabled with other enableK2KClusterSync bool // Run k2kClusterSync operator @@ -186,6 +187,7 @@ var ( mlProbe probe.ReadyProbe analyticsProbe probe.ReadyProbe networkingProbe probe.ReadyProbe + schedulerProbe probe.ReadyProbe k2KClusterSyncProbe probe.ReadyProbe ) @@ -213,6 +215,7 @@ func init() { f.BoolVar(&operatorOptions.enableML, "operator.ml", false, "Enable to run the ArangoML operator") f.BoolVar(&operatorOptions.enableAnalytics, "operator.analytics", false, "Enable to run the Analytics operator") f.BoolVar(&operatorOptions.enableNetworking, "operator.networking", false, "Enable to run the Networking operator") + f.BoolVar(&operatorOptions.enableScheduler, "operator.scheduler", false, "Enable to run the Scheduler operator") f.BoolVar(&operatorOptions.enableK2KClusterSync, "operator.k2k-cluster-sync", false, "Enable to run the ListSimple operator") f.MarkDeprecated("operator.k2k-cluster-sync", "Enabled within deployment operator") f.BoolVar(&operatorOptions.versionOnly, "operator.version", false, "Enable only version endpoint in Operator") @@ -349,12 +352,13 @@ func executeMain(cmd *cobra.Command, args []string) { // Check operating mode if !operatorOptions.enableDeployment && !operatorOptions.enableDeploymentReplication && !operatorOptions.enableStorage && !operatorOptions.enableBackup && !operatorOptions.enableApps && !operatorOptions.enableK2KClusterSync && - !operatorOptions.enableML && !operatorOptions.enableAnalytics && !operatorOptions.enableNetworking { + !operatorOptions.enableML && !operatorOptions.enableAnalytics && + !operatorOptions.enableNetworking && !operatorOptions.enableScheduler { if !operatorOptions.versionOnly { if version.GetVersionV1().IsEnterprise() { - logger.Fatal("Turn on --operator.deployment, --operator.deployment-replication, --operator.storage, --operator.backup, --operator.apps, --operator.k2k-cluster-sync, --operator.ml, --operator.analytics, --operator.networking or any combination of these") + logger.Fatal("Turn on --operator.deployment, --operator.deployment-replication, --operator.storage, --operator.backup, --operator.apps, --operator.k2k-cluster-sync, --operator.ml, --operator.analytics, --operator.networking, --operator.scheduler or any combination of these") } else { - logger.Fatal("Turn on --operator.deployment, --operator.deployment-replication, --operator.storage, --operator.backup, --operator.apps, --operator.k2k-cluster-sync, --operator.networking or any combination of these") + logger.Fatal("Turn on --operator.deployment, --operator.deployment-replication, --operator.storage, --operator.backup, --operator.apps, --operator.k2k-cluster-sync, --operator.networking, --operator.scheduler or any combination of these") } } } else if operatorOptions.versionOnly { @@ -498,7 +502,11 @@ func executeMain(cmd *cobra.Command, args []string) { }, Networking: server.OperatorDependency{ Enabled: cfg.EnableNetworking, - Probe: &analyticsProbe, + Probe: &networkingProbe, + }, + Scheduler: server.OperatorDependency{ + Enabled: cfg.EnableScheduler, + Probe: &schedulerProbe, }, ClusterSync: server.OperatorDependency{ Enabled: cfg.EnableK2KClusterSync, @@ -585,6 +593,7 @@ func newOperatorConfigAndDeps(id, namespace, name string) (operator.Config, oper EnableML: operatorOptions.enableML, EnableAnalytics: operatorOptions.enableAnalytics, EnableNetworking: operatorOptions.enableNetworking, + EnableScheduler: operatorOptions.enableScheduler, EnableK2KClusterSync: operatorOptions.enableK2KClusterSync, AllowChaos: chaosOptions.allowed, ScalingIntegrationEnabled: operatorOptions.scalingIntegrationEnabled, @@ -606,6 +615,7 @@ func newOperatorConfigAndDeps(id, namespace, name string) (operator.Config, oper MlProbe: &mlProbe, AnalyticsProbe: &analyticsProbe, NetworkingProbe: &networkingProbe, + SchedulerProbe: &schedulerProbe, K2KClusterSyncProbe: &k2KClusterSyncProbe, } diff --git a/docs/cli/arangodb_operator.md b/docs/cli/arangodb_operator.md index 938126a07..0caa979b0 100644 --- a/docs/cli/arangodb_operator.md +++ b/docs/cli/arangodb_operator.md @@ -80,7 +80,7 @@ Flags: --kubernetes.max-batch-size int Size of batch during objects read (default 256) --kubernetes.qps float32 Number of queries per second for k8s API (default 15) --log.format string Set log format. Allowed values: 'pretty', 'JSON'. If empty, default format is used (default "pretty") - --log.level stringArray Set log levels in format or =. Possible loggers: action, agency, api-server, assertion, backup-operator, chaos-monkey, crd, deployment, deployment-ci, deployment-reconcile, deployment-replication, deployment-resilience, deployment-resources, deployment-storage, deployment-storage-pc, deployment-storage-service, http, inspector, integration-config-v1, integration-envoy-auth-v3, integrations, k8s-client, kubernetes-informer, monitor, networking-route-operator, operator, operator-arangojob-handler, operator-v2, operator-v2-event, operator-v2-worker, panics, pod_compare, root, root-event-recorder, server, server-authentication (default [info]) + --log.level stringArray Set log levels in format or =. Possible loggers: action, agency, api-server, assertion, backup-operator, chaos-monkey, crd, deployment, deployment-ci, deployment-reconcile, deployment-replication, deployment-resilience, deployment-resources, deployment-storage, deployment-storage-pc, deployment-storage-service, http, inspector, integration-config-v1, integration-envoy-auth-v3, integrations, k8s-client, kubernetes-informer, monitor, networking-route-operator, operator, operator-arangojob-handler, operator-v2, operator-v2-event, operator-v2-worker, panics, pod_compare, root, root-event-recorder, scheduler-profile-operator, server, server-authentication (default [info]) --log.sampling If true, operator will try to minimize duplication of logging events (default true) --memory-limit uint Define memory limit for hard shutdown and the dump of goroutines. Used for testing --metrics.excluded-prefixes stringArray List of the excluded metrics prefixes @@ -94,6 +94,7 @@ Flags: --operator.networking Enable to run the Networking operator --operator.reconciliation.retry.count int Count of retries during Object Update operations in the Reconciliation loop (default 25) --operator.reconciliation.retry.delay duration Delay between Object Update operations in the Reconciliation loop (default 1s) + --operator.scheduler Enable to run the Scheduler operator --operator.storage Enable to run the ArangoLocalStorage operator --operator.version Enable only version endpoint in Operator --reconciliation.delay duration Delay between reconciliation loops (<= 0 -> Disabled) diff --git a/pkg/apis/scheduler/v1alpha1/profile.go b/pkg/apis/scheduler/v1alpha1/profile.go index 599f866e3..587fef7db 100644 --- a/pkg/apis/scheduler/v1alpha1/profile.go +++ b/pkg/apis/scheduler/v1alpha1/profile.go @@ -43,3 +43,11 @@ type ArangoProfile struct { Spec ProfileSpec `json:"spec"` Status ProfileStatus `json:"status"` } + +func (a *ArangoProfile) GetStatus() ProfileStatus { + return a.Status +} + +func (a *ArangoProfile) SetStatus(status ProfileStatus) { + a.Status = status +} diff --git a/pkg/apis/scheduler/v1beta1/profile.go b/pkg/apis/scheduler/v1beta1/profile.go index 89888779c..843c4639c 100644 --- a/pkg/apis/scheduler/v1beta1/profile.go +++ b/pkg/apis/scheduler/v1beta1/profile.go @@ -43,3 +43,11 @@ type ArangoProfile struct { Spec ProfileSpec `json:"spec"` Status ProfileStatus `json:"status"` } + +func (a *ArangoProfile) GetStatus() ProfileStatus { + return a.Status +} + +func (a *ArangoProfile) SetStatus(status ProfileStatus) { + a.Status = status +} diff --git a/pkg/apis/scheduler/v1beta1/profile_status.go b/pkg/apis/scheduler/v1beta1/profile_status.go index 7652443ac..7f9d98dfb 100644 --- a/pkg/apis/scheduler/v1beta1/profile_status.go +++ b/pkg/apis/scheduler/v1beta1/profile_status.go @@ -20,5 +20,4 @@ package v1beta1 -type ProfileStatus struct { -} +type ProfileStatus struct{} diff --git a/pkg/deployment/resources/inspector/ap.go b/pkg/deployment/resources/inspector/ap.go new file mode 100644 index 000000000..611c85ec8 --- /dev/null +++ b/pkg/deployment/resources/inspector/ap.go @@ -0,0 +1,192 @@ +// +// DISCLAIMER +// +// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package inspector + +import ( + "context" + "time" + + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" + "github.com/arangodb/kube-arangodb/pkg/util/errors" + "github.com/arangodb/kube-arangodb/pkg/util/globals" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/definitions" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/throttle" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/version" +) + +func init() { + requireRegisterInspectorLoader(arangoProfilesInspectorLoaderObj) +} + +var arangoProfilesInspectorLoaderObj = arangoProfilesInspectorLoader{} + +type arangoProfilesInspectorLoader struct { +} + +func (p arangoProfilesInspectorLoader) Component() definitions.Component { + return definitions.ArangoProfile +} + +func (p arangoProfilesInspectorLoader) Load(ctx context.Context, i *inspectorState) { + var q arangoProfilesInspector + p.loadV1Beta1(ctx, i, &q) + i.arangoProfiles = &q + q.state = i + q.last = time.Now() +} + +func (p arangoProfilesInspectorLoader) loadV1Beta1(ctx context.Context, i *inspectorState, q *arangoProfilesInspector) { + var z arangoProfilesInspectorV1Beta1 + + z.arangoProfileInspector = q + + z.arangoProfiles, z.err = p.getV1ArangoProfiles(ctx, i) + + q.v1beta1 = &z +} + +func (p arangoProfilesInspectorLoader) getV1ArangoProfiles(ctx context.Context, i *inspectorState) (map[string]*schedulerApi.ArangoProfile, error) { + objs, err := p.getV1ArangoProfilesList(ctx, i) + if err != nil { + return nil, err + } + + r := make(map[string]*schedulerApi.ArangoProfile, len(objs)) + + for id := range objs { + r[objs[id].GetName()] = objs[id] + } + + return r, nil +} + +func (p arangoProfilesInspectorLoader) getV1ArangoProfilesList(ctx context.Context, i *inspectorState) ([]*schedulerApi.ArangoProfile, error) { + ctxChild, cancel := globals.GetGlobalTimeouts().Kubernetes().WithTimeout(ctx) + defer cancel() + obj, err := i.client.Arango().SchedulerV1beta1().ArangoProfiles(i.namespace).List(ctxChild, meta.ListOptions{ + Limit: globals.GetGlobals().Kubernetes().RequestBatchSize().Get(), + }) + + if err != nil { + return nil, err + } + + items := obj.Items + cont := obj.Continue + var s = int64(len(items)) + + if z := obj.RemainingItemCount; z != nil { + s += *z + } + + ptrs := make([]*schedulerApi.ArangoProfile, 0, s) + + for { + for id := range items { + ptrs = append(ptrs, &items[id]) + } + + if cont == "" { + break + } + + items, cont, err = p.getV1ArangoProfilesListRequest(ctx, i, cont) + + if err != nil { + return nil, err + } + } + + return ptrs, nil +} + +func (p arangoProfilesInspectorLoader) getV1ArangoProfilesListRequest(ctx context.Context, i *inspectorState, cont string) ([]schedulerApi.ArangoProfile, string, error) { + ctxChild, cancel := globals.GetGlobalTimeouts().Kubernetes().WithTimeout(ctx) + defer cancel() + obj, err := i.client.Arango().SchedulerV1beta1().ArangoProfiles(i.namespace).List(ctxChild, meta.ListOptions{ + Limit: globals.GetGlobals().Kubernetes().RequestBatchSize().Get(), + Continue: cont, + }) + + if err != nil { + return nil, "", err + } + + return obj.Items, obj.Continue, err +} + +func (p arangoProfilesInspectorLoader) Verify(i *inspectorState) error { + return nil +} + +func (p arangoProfilesInspectorLoader) Copy(from, to *inspectorState, override bool) { + if to.arangoProfiles != nil { + if !override { + return + } + } + + to.arangoProfiles = from.arangoProfiles + to.arangoProfiles.state = to +} + +func (p arangoProfilesInspectorLoader) Name() string { + return "arangoProfiles" +} + +type arangoProfilesInspector struct { + state *inspectorState + + last time.Time + + v1beta1 *arangoProfilesInspectorV1Beta1 +} + +func (p *arangoProfilesInspector) LastRefresh() time.Time { + return p.last +} + +func (p *arangoProfilesInspector) Refresh(ctx context.Context) error { + p.Throttle(p.state.throttles).Invalidate() + return p.state.refresh(ctx, arangoProfilesInspectorLoaderObj) +} + +func (p *arangoProfilesInspector) Version() version.Version { + return version.V1 +} + +func (p *arangoProfilesInspector) Throttle(c throttle.Components) throttle.Throttle { + return c.ArangoProfile() +} + +func (p *arangoProfilesInspector) validate() error { + if p == nil { + return errors.Errorf("ArangoProfileInspector is nil") + } + + if p.state == nil { + return errors.Errorf("Parent is nil") + } + + return p.v1beta1.validate() +} diff --git a/pkg/deployment/resources/inspector/ap_anonymous.go b/pkg/deployment/resources/inspector/ap_anonymous.go new file mode 100644 index 000000000..78bc26245 --- /dev/null +++ b/pkg/deployment/resources/inspector/ap_anonymous.go @@ -0,0 +1,45 @@ +// +// DISCLAIMER +// +// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package inspector + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/anonymous" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/constants" +) + +func (p *arangoProfilesInspector) Anonymous(gvk schema.GroupVersionKind) (anonymous.Interface, bool) { + g := constants.ArangoProfileGKv1() + + if g.Kind == gvk.Kind && g.Group == gvk.Group { + switch gvk.Version { + case constants.ArangoProfileVersionV1Beta1, DefaultVersion: + if p.v1beta1 == nil || p.v1beta1.err != nil { + return nil, false + } + return anonymous.NewAnonymous[*schedulerApi.ArangoProfile](g, p.state.arangoProfiles.v1beta1, p.state.ArangoProfileModInterface().V1Beta1()), true + } + } + + return nil, false +} diff --git a/pkg/deployment/resources/inspector/ap_gvk.go b/pkg/deployment/resources/inspector/ap_gvk.go new file mode 100644 index 000000000..f73892fde --- /dev/null +++ b/pkg/deployment/resources/inspector/ap_gvk.go @@ -0,0 +1,43 @@ +// +// DISCLAIMER +// +// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package inspector + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/constants" +) + +func (p *arangoProfilesInspectorV1Beta1) GroupVersionKind() schema.GroupVersionKind { + return constants.ArangoProfileGKv1() +} + +func (p *arangoProfilesInspectorV1Beta1) GroupVersionResource() schema.GroupVersionResource { + return constants.ArangoProfileGRv1() +} + +func (p *arangoProfilesInspector) GroupKind() schema.GroupKind { + return constants.ArangoProfileGK() +} + +func (p *arangoProfilesInspector) GroupResource() schema.GroupResource { + return constants.ArangoProfileGR() +} diff --git a/pkg/deployment/resources/inspector/ap_mod.go b/pkg/deployment/resources/inspector/ap_mod.go new file mode 100644 index 000000000..276bb8935 --- /dev/null +++ b/pkg/deployment/resources/inspector/ap_mod.go @@ -0,0 +1,47 @@ +// +// DISCLAIMER +// +// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package inspector + +import ( + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" + arangoProfilev1 "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangoprofile/v1beta1" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/definitions" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/generic" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/mods" +) + +func (i *inspectorState) ArangoProfileModInterface() mods.ArangoProfileMods { + return arangoProfileMod{ + i: i, + } +} + +type arangoProfileMod struct { + i *inspectorState +} + +func (p arangoProfileMod) V1Beta1() arangoProfilev1.ModInterface { + return wrapMod[*schedulerApi.ArangoProfile](definitions.ArangoProfile, p.i.GetThrottles, p.clientv1beta1) +} + +func (p arangoProfileMod) clientv1beta1() generic.ModStatusClient[*schedulerApi.ArangoProfile] { + return p.i.Client().Arango().SchedulerV1beta1().ArangoProfiles(p.i.Namespace()) +} diff --git a/pkg/deployment/resources/inspector/ap_v1beta1.go b/pkg/deployment/resources/inspector/ap_v1beta1.go new file mode 100644 index 000000000..add18b85c --- /dev/null +++ b/pkg/deployment/resources/inspector/ap_v1beta1.go @@ -0,0 +1,138 @@ +// +// DISCLAIMER +// +// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package inspector + +import ( + "context" + + apiErrors "k8s.io/apimachinery/pkg/api/errors" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" + "github.com/arangodb/kube-arangodb/pkg/util/errors" + ins "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangoprofile/v1beta1" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/constants" +) + +func (p *arangoProfilesInspector) V1Beta1() (ins.Inspector, error) { + if p.v1beta1.err != nil { + return nil, p.v1beta1.err + } + + return p.v1beta1, nil +} + +type arangoProfilesInspectorV1Beta1 struct { + arangoProfileInspector *arangoProfilesInspector + + arangoProfiles map[string]*schedulerApi.ArangoProfile + err error +} + +func (p *arangoProfilesInspectorV1Beta1) Filter(filters ...ins.Filter) []*schedulerApi.ArangoProfile { + z := p.ListSimple() + + r := make([]*schedulerApi.ArangoProfile, 0, len(z)) + + for _, o := range z { + if !ins.FilterObject(o, filters...) { + continue + } + + r = append(r, o) + } + + return r +} + +func (p *arangoProfilesInspectorV1Beta1) validate() error { + if p == nil { + return errors.Errorf("ArangoProfilesV1AlphaInspector is nil") + } + + if p.arangoProfileInspector == nil { + return errors.Errorf("Parent is nil") + } + + if p.arangoProfiles == nil && p.err == nil { + return errors.Errorf("ArangoProfiles or err should be not nil") + } + + if p.arangoProfiles != nil && p.err != nil { + return errors.Errorf("ArangoProfiles or err cannot be not nil together") + } + + return nil +} + +func (p *arangoProfilesInspectorV1Beta1) ListSimple() []*schedulerApi.ArangoProfile { + var r []*schedulerApi.ArangoProfile + for _, arangoProfile := range p.arangoProfiles { + r = append(r, arangoProfile) + } + + return r +} + +func (p *arangoProfilesInspectorV1Beta1) GetSimple(name string) (*schedulerApi.ArangoProfile, bool) { + arangoProfile, ok := p.arangoProfiles[name] + if !ok { + return nil, false + } + + return arangoProfile, true +} + +func (p *arangoProfilesInspectorV1Beta1) Iterate(action ins.Action, filters ...ins.Filter) error { + for _, arangoProfile := range p.arangoProfiles { + if err := p.iterateArangoProfile(arangoProfile, action, filters...); err != nil { + return err + } + } + + return nil +} + +func (p *arangoProfilesInspectorV1Beta1) iterateArangoProfile(arangoProfile *schedulerApi.ArangoProfile, action ins.Action, filters ...ins.Filter) error { + for _, f := range filters { + if f == nil { + continue + } + + if !f(arangoProfile) { + return nil + } + } + + return action(arangoProfile) +} + +func (p *arangoProfilesInspectorV1Beta1) Read() ins.ReadInterface { + return p +} + +func (p *arangoProfilesInspectorV1Beta1) Get(ctx context.Context, name string, opts meta.GetOptions) (*schedulerApi.ArangoProfile, error) { + if s, ok := p.GetSimple(name); !ok { + return nil, apiErrors.NewNotFound(constants.ArangoProfileGR(), name) + } else { + return s, nil + } +} diff --git a/pkg/deployment/resources/inspector/inspector.go b/pkg/deployment/resources/inspector/inspector.go index 8ed7bd964..1a8d7a434 100644 --- a/pkg/deployment/resources/inspector/inspector.go +++ b/pkg/deployment/resources/inspector/inspector.go @@ -42,6 +42,7 @@ import ( "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/anonymous" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangoclustersynchronization" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangomember" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangoprofile" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangoroute" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangotask" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/configmap" @@ -137,6 +138,7 @@ type inspectorState struct { serviceMonitors *serviceMonitorsInspector arangoMembers *arangoMembersInspector arangoTasks *arangoTasksInspector + arangoProfiles *arangoProfilesInspector arangoRoutes *arangoRoutesInspector arangoClusterSynchronizations *arangoClusterSynchronizationsInspector endpoints *endpointsInspector @@ -172,6 +174,10 @@ func (i *inspectorState) RegisterInformers(k8s informers.SharedInformerFactory, arango.Database().V1().ArangoTasks().Informer().AddEventHandler(i.eventHandler(definitions.ArangoTask)) } + if _, err := i.ArangoProfiles().V1Beta1(); err == nil { + arango.Scheduler().V1beta1().ArangoProfiles().Informer().AddEventHandler(i.eventHandler(definitions.ArangoProfile)) + } + if _, err := i.ArangoRoute().V1Alpha1(); err == nil { arango.Networking().V1alpha1().ArangoRoutes().Informer().AddEventHandler(i.eventHandler(definitions.ArangoRoute)) } @@ -336,6 +342,14 @@ func (i *inspectorState) ArangoRoute() arangoroute.Definition { return i.arangoRoutes } +func (i *inspectorState) ArangoProfile() arangoprofile.Definition { + return i.arangoProfiles +} + +func (i *inspectorState) ArangoProfiles() arangoprofile.Definition { + return i.arangoProfiles +} + func (i *inspectorState) Refresh(ctx context.Context) error { return i.refresh(ctx, inspectorLoadersList...) } @@ -491,6 +505,10 @@ func (i *inspectorState) validate() error { return err } + if err := i.arangoProfiles.validate(); err != nil { + return err + } + if err := i.arangoTasks.validate(); err != nil { return err } @@ -524,6 +542,7 @@ func (i *inspectorState) copyCore() *inspectorState { arangoMembers: i.arangoMembers, arangoTasks: i.arangoTasks, arangoRoutes: i.arangoRoutes, + arangoProfiles: i.arangoProfiles, arangoClusterSynchronizations: i.arangoClusterSynchronizations, throttles: i.throttles.Copy(), versionInfo: i.versionInfo, diff --git a/pkg/deployment/resources/inspector/inspector_test.go b/pkg/deployment/resources/inspector/inspector_test.go index 262fd519a..40b057b76 100644 --- a/pkg/deployment/resources/inspector/inspector_test.go +++ b/pkg/deployment/resources/inspector/inspector_test.go @@ -142,7 +142,7 @@ func getAllTypes() []string { func Test_Inspector_RefreshMatrix(t *testing.T) { c := kclient.NewFakeClient() - tc := throttle.NewThrottleComponents(time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour) + tc := throttle.NewThrottleComponents(time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour) i := NewInspector(tc, c, "test", "test") @@ -302,7 +302,7 @@ func Test_Inspector_Load(t *testing.T) { func Test_Inspector_Invalidate(t *testing.T) { c := kclient.NewFakeClient() - tc := throttle.NewThrottleComponents(time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour) + tc := throttle.NewThrottleComponents(time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour) i := NewInspector(tc, c, "test", "test") diff --git a/pkg/deployment/resources/inspector/pdbs_version_test.go b/pkg/deployment/resources/inspector/pdbs_version_test.go index d0e96460f..01e03d309 100644 --- a/pkg/deployment/resources/inspector/pdbs_version_test.go +++ b/pkg/deployment/resources/inspector/pdbs_version_test.go @@ -52,7 +52,7 @@ func Test_PDB_Versions(t *testing.T) { GitVersion: v, }) - tc := throttle.NewThrottleComponents(time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour) + tc := throttle.NewThrottleComponents(time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour, time.Hour) i := NewInspector(tc, c, "test", "test") require.NoError(t, i.Refresh(context.Background())) diff --git a/pkg/deployment/resources/inspector/throttles.go b/pkg/deployment/resources/inspector/throttles.go index 26baaa36a..67a245a48 100644 --- a/pkg/deployment/resources/inspector/throttles.go +++ b/pkg/deployment/resources/inspector/throttles.go @@ -32,6 +32,7 @@ func NewDefaultThrottle() throttle.Components { 30*time.Second, // ArangoMember 30*time.Second, // ArangoTask 30*time.Second, // ArangoRoute + 30*time.Second, // ArangoProfile 30*time.Second, // Node 30*time.Second, // PV 15*time.Second, // PVC diff --git a/pkg/handlers/networking/route/suite_test.go b/pkg/handlers/networking/route/suite_test.go index dc222725c..f247ecf8e 100644 --- a/pkg/handlers/networking/route/suite_test.go +++ b/pkg/handlers/networking/route/suite_test.go @@ -23,7 +23,7 @@ package route import ( "k8s.io/client-go/kubernetes/fake" - "github.com/arangodb/kube-arangodb/pkg/apis/analytics" + "github.com/arangodb/kube-arangodb/pkg/apis/networking" networkingApi "github.com/arangodb/kube-arangodb/pkg/apis/networking/v1alpha1" fakeClientSet "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/fake" operator "github.com/arangodb/kube-arangodb/pkg/operatorV2" @@ -51,7 +51,7 @@ func newItem(o operation.Operation, namespace, name string) operation.Item { return operation.Item{ Group: networkingApi.SchemeGroupVersion.Group, Version: networkingApi.SchemeGroupVersion.Version, - Kind: analytics.GraphAnalyticsEngineResourceKind, + Kind: networking.ArangoRouteResourceKind, Operation: o, diff --git a/pkg/handlers/scheduler/profile/handler.go b/pkg/handlers/scheduler/profile/handler.go new file mode 100644 index 000000000..3961ba872 --- /dev/null +++ b/pkg/handlers/scheduler/profile/handler.go @@ -0,0 +1,104 @@ +// +// DISCLAIMER +// +// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package profile + +import ( + "context" + + apiErrors "k8s.io/apimachinery/pkg/api/errors" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" + arangoClientSet "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned" + "github.com/arangodb/kube-arangodb/pkg/logging" + operator "github.com/arangodb/kube-arangodb/pkg/operatorV2" + "github.com/arangodb/kube-arangodb/pkg/operatorV2/event" + "github.com/arangodb/kube-arangodb/pkg/operatorV2/operation" + "github.com/arangodb/kube-arangodb/pkg/util" +) + +var logger = logging.Global().RegisterAndGetLogger("scheduler-profile-operator", logging.Info) + +type handler struct { + client arangoClientSet.Interface + kubeClient kubernetes.Interface + + eventRecorder event.RecorderInstance + + operator operator.Operator +} + +func (h *handler) Name() string { + return Kind() +} + +func (h *handler) Handle(ctx context.Context, item operation.Item) error { + // Get Backup object. It also covers NotFound case + + object, err := util.WithKubernetesContextTimeoutP2A2(ctx, h.client.SchedulerV1beta1().ArangoProfiles(item.Namespace).Get, item.Name, meta.GetOptions{}) + if err != nil { + if apiErrors.IsNotFound(err) { + return nil + } + + return err + } + + status := object.Status.DeepCopy() + + changed, reconcileErr := operator.HandleP3WithStop(ctx, item, object, status, h.handle) + if reconcileErr != nil && !operator.IsReconcile(reconcileErr) { + logger.Err(reconcileErr).Warn("Fail for %s %s/%s", + item.Kind, + item.Namespace, + item.Name) + + return reconcileErr + } + + if !changed { + return reconcileErr + } + + logger.Debug("Updating %s %s/%s", + item.Kind, + item.Namespace, + item.Name) + + if _, err := operator.WithNetworkingArangoProfileUpdateStatusInterfaceRetry(context.Background(), h.client.SchedulerV1beta1().ArangoProfiles(object.GetNamespace()), object, *status, meta.UpdateOptions{}); err != nil { + return err + } + + return reconcileErr +} + +func (h *handler) handle(ctx context.Context, item operation.Item, extension *schedulerApi.ArangoProfile, status *schedulerApi.ProfileStatus) (bool, error) { + return false, nil +} + +func (h *handler) CanBeHandled(item operation.Item) bool { + return item.Group == Group() && + item.Version == Version() && + item.Kind == Kind() +} + +func (h *handler) init() {} diff --git a/pkg/handlers/scheduler/profile/handler_test.go b/pkg/handlers/scheduler/profile/handler_test.go new file mode 100644 index 000000000..7e824bd87 --- /dev/null +++ b/pkg/handlers/scheduler/profile/handler_test.go @@ -0,0 +1,59 @@ +// +// DISCLAIMER +// +// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package profile + +import ( + "testing" + + "github.com/stretchr/testify/require" + apiErrors "k8s.io/apimachinery/pkg/api/errors" + + "github.com/arangodb/kube-arangodb/pkg/operatorV2/operation" + "github.com/arangodb/kube-arangodb/pkg/util/tests" +) + +func Test_ObjectNotFound(t *testing.T) { + // Arrange + handler := newFakeHandler() + + i := newItem(operation.Add, "test", "test") + + actions := map[operation.Operation]bool{ + operation.Add: false, + operation.Update: false, + operation.Delete: false, + } + + // Act + for op, shouldFail := range actions { + t.Run(string(op), func(t *testing.T) { + err := tests.Handle(handler, i) + + // Assert + if shouldFail { + require.Error(t, err) + require.True(t, apiErrors.IsNotFound(err)) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/pkg/handlers/scheduler/profile/local.go b/pkg/handlers/scheduler/profile/local.go new file mode 100644 index 000000000..3fa7f09bc --- /dev/null +++ b/pkg/handlers/scheduler/profile/local.go @@ -0,0 +1,38 @@ +// +// DISCLAIMER +// +// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package profile + +import ( + "github.com/arangodb/kube-arangodb/pkg/apis/scheduler" + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" +) + +func Kind() string { + return scheduler.ArangoProfileResourceKind +} + +func Group() string { + return schedulerApi.SchemeGroupVersion.Group +} + +func Version() string { + return schedulerApi.SchemeGroupVersion.Version +} diff --git a/pkg/handlers/scheduler/profile/register.go b/pkg/handlers/scheduler/profile/register.go new file mode 100644 index 000000000..81bcfe193 --- /dev/null +++ b/pkg/handlers/scheduler/profile/register.go @@ -0,0 +1,60 @@ +// +// DISCLAIMER +// +// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package profile + +import ( + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + + arangoClientSet "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned" + arangoInformer "github.com/arangodb/kube-arangodb/pkg/generated/informers/externalversions" + operator "github.com/arangodb/kube-arangodb/pkg/operatorV2" + "github.com/arangodb/kube-arangodb/pkg/operatorV2/event" +) + +// RegisterInformer into operator +func RegisterInformer(operator operator.Operator, recorder event.Recorder, client arangoClientSet.Interface, + kubeClient kubernetes.Interface, informer arangoInformer.SharedInformerFactory, kubeInformer informers.SharedInformerFactory) error { + + if err := operator.RegisterInformer(informer.Scheduler().V1beta1().ArangoProfiles().Informer(), + Group(), + Version(), + Kind()); err != nil { + return err + } + + h := &handler{ + client: client, + kubeClient: kubeClient, + + eventRecorder: recorder.NewInstance(Group(), Version(), Kind()), + + operator: operator, + } + + h.init() + + if err := operator.RegisterHandler(h); err != nil { + return err + } + + return nil +} diff --git a/pkg/handlers/scheduler/profile/suite_test.go b/pkg/handlers/scheduler/profile/suite_test.go new file mode 100644 index 000000000..6e5eeb32b --- /dev/null +++ b/pkg/handlers/scheduler/profile/suite_test.go @@ -0,0 +1,61 @@ +// +// DISCLAIMER +// +// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package profile + +import ( + "k8s.io/client-go/kubernetes/fake" + + "github.com/arangodb/kube-arangodb/pkg/apis/scheduler" + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" + fakeClientSet "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/fake" + operator "github.com/arangodb/kube-arangodb/pkg/operatorV2" + "github.com/arangodb/kube-arangodb/pkg/operatorV2/event" + "github.com/arangodb/kube-arangodb/pkg/operatorV2/operation" +) + +func newFakeHandler() *handler { + f := fakeClientSet.NewSimpleClientset() + k := fake.NewSimpleClientset() + + h := &handler{ + client: f, + kubeClient: k, + eventRecorder: event.NewEventRecorder("mock", k).NewInstance(Group(), Version(), Kind()), + operator: operator.NewOperator("mock", "mock", "mock"), + } + + h.init() + + return h +} + +func newItem(o operation.Operation, namespace, name string) operation.Item { + return operation.Item{ + Group: schedulerApi.SchemeGroupVersion.Group, + Version: schedulerApi.SchemeGroupVersion.Version, + Kind: scheduler.ArangoProfileResourceKind, + + Operation: o, + + Namespace: namespace, + Name: name, + } +} diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go index 586f3bcd1..3d0768819 100644 --- a/pkg/operator/operator.go +++ b/pkg/operator/operator.go @@ -40,6 +40,7 @@ import ( "github.com/arangodb/kube-arangodb/pkg/apis/networking" repldef "github.com/arangodb/kube-arangodb/pkg/apis/replication" replapi "github.com/arangodb/kube-arangodb/pkg/apis/replication/v1" + "github.com/arangodb/kube-arangodb/pkg/apis/scheduler" lsapi "github.com/arangodb/kube-arangodb/pkg/apis/storage/v1alpha" "github.com/arangodb/kube-arangodb/pkg/deployment" arangoClientSet "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned" @@ -48,6 +49,7 @@ import ( "github.com/arangodb/kube-arangodb/pkg/handlers/job" "github.com/arangodb/kube-arangodb/pkg/handlers/networking/route" "github.com/arangodb/kube-arangodb/pkg/handlers/policy" + "github.com/arangodb/kube-arangodb/pkg/handlers/scheduler/profile" "github.com/arangodb/kube-arangodb/pkg/logging" "github.com/arangodb/kube-arangodb/pkg/operator/scope" operatorV2 "github.com/arangodb/kube-arangodb/pkg/operatorV2" @@ -74,6 +76,7 @@ const ( mlOperator operatorV2type = "ml" analyticsOperator operatorV2type = "analytics" networkingOperator operatorV2type = "networking" + schedulerOperator operatorV2type = "scheduler" appsOperator operatorV2type = "apps" ) @@ -106,6 +109,7 @@ type Config struct { EnableML bool EnableAnalytics bool EnableNetworking bool + EnableScheduler bool EnableBackup bool EnableApps bool EnableK2KClusterSync bool @@ -129,6 +133,7 @@ type Dependencies struct { MlProbe *probe.ReadyProbe AnalyticsProbe *probe.ReadyProbe NetworkingProbe *probe.ReadyProbe + SchedulerProbe *probe.ReadyProbe AppsProbe *probe.ReadyProbe K2KClusterSyncProbe *probe.ReadyProbe } @@ -204,6 +209,13 @@ func (o *Operator) Run() { go o.runWithoutLeaderElection("arango-networking-operator", constants.NetworkingLabelRole, o.onStartNetworking, o.Dependencies.NetworkingProbe) } } + if o.Config.EnableScheduler { + if !o.Config.SingleMode { + go o.runLeaderElection("arango-scheduler-operator", constants.SchedulerLabelRole, o.onStartScheduler, o.Dependencies.SchedulerProbe) + } else { + go o.runWithoutLeaderElection("arango-scheduler-operator", constants.SchedulerLabelRole, o.onStartScheduler, o.Dependencies.SchedulerProbe) + } + } if o.Config.EnableK2KClusterSync { // Nothing to do o.log.Warn("K2K Cluster sync is permanently disabled") @@ -279,6 +291,11 @@ func (o *Operator) onStartNetworking(stop <-chan struct{}) { o.onStartOperatorV2(networkingOperator, stop) } +// onStartNetworking starts the operator and run till given channel is closed. +func (o *Operator) onStartScheduler(stop <-chan struct{}) { + o.onStartOperatorV2(schedulerOperator, stop) +} + // onStartOperatorV2 run the operatorV2 type func (o *Operator) onStartOperatorV2(operatorType operatorV2type, stop <-chan struct{}) { operatorName := fmt.Sprintf("arangodb-%s-operator", operatorType) @@ -310,6 +327,9 @@ func (o *Operator) onStartOperatorV2(operatorType operatorV2type, stop <-chan st case networkingOperator: o.onStartOperatorV2Networking(operator, eventRecorder, o.Client.Arango(), o.Client.Kubernetes(), arangoInformer, kubeInformer) o.Dependencies.NetworkingProbe.SetReady() + case schedulerOperator: + o.onStartOperatorV2Scheduler(operator, eventRecorder, o.Client.Arango(), o.Client.Kubernetes(), arangoInformer, kubeInformer) + o.Dependencies.SchedulerProbe.SetReady() } if err := operator.RegisterStarter(arangoInformer); err != nil { @@ -353,6 +373,18 @@ func (o *Operator) onStartOperatorV2Networking(operator operatorV2.Operator, rec } } +func (o *Operator) onStartOperatorV2Scheduler(operator operatorV2.Operator, recorder event.Recorder, client arangoClientSet.Interface, kubeClient kubernetes.Interface, informer arangoInformer.SharedInformerFactory, kubeInformer informers.SharedInformerFactory) { + checkFn := func() error { + _, err := o.Client.Arango().SchedulerV1beta1().ArangoProfiles(o.Namespace).List(context.Background(), meta.ListOptions{}) + return err + } + o.waitForCRD(scheduler.ArangoProfileCRDName, checkFn) + + if err := profile.RegisterInformer(operator, recorder, client, kubeClient, informer, kubeInformer); err != nil { + panic(err) + } +} + func (o *Operator) onStartOperatorV2Backup(operator operatorV2.Operator, recorder event.Recorder, client arangoClientSet.Interface, kubeClient kubernetes.Interface, informer arangoInformer.SharedInformerFactory) { checkFn := func() error { _, err := o.Client.Arango().BackupV1().ArangoBackups(o.Namespace).List(context.Background(), meta.ListOptions{}) diff --git a/pkg/operatorV2/update_wraps.go b/pkg/operatorV2/update_wraps.go index acae0b86f..9ec789c27 100644 --- a/pkg/operatorV2/update_wraps.go +++ b/pkg/operatorV2/update_wraps.go @@ -30,6 +30,7 @@ import ( mlApiv1alpha1 "github.com/arangodb/kube-arangodb/pkg/apis/ml/v1alpha1" mlApi "github.com/arangodb/kube-arangodb/pkg/apis/ml/v1beta1" networkingApi "github.com/arangodb/kube-arangodb/pkg/apis/networking/v1alpha1" + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" ) func WithArangoBackupUpdateStatusInterfaceRetry(ctx context.Context, client UpdateStatusInterface[backupApi.ArangoBackupStatus, *backupApi.ArangoBackup], obj *backupApi.ArangoBackup, status backupApi.ArangoBackupStatus, opts meta.UpdateOptions) (*backupApi.ArangoBackup, error) { @@ -56,6 +57,10 @@ func WithNetworkingArangoRouteUpdateStatusInterfaceRetry(ctx context.Context, cl return WithUpdateStatusInterfaceRetry[networkingApi.ArangoRouteStatus, *networkingApi.ArangoRoute](ctx, client, obj, status, opts) } +func WithNetworkingArangoProfileUpdateStatusInterfaceRetry(ctx context.Context, client UpdateStatusInterface[schedulerApi.ProfileStatus, *schedulerApi.ArangoProfile], obj *schedulerApi.ArangoProfile, status schedulerApi.ProfileStatus, opts meta.UpdateOptions) (*schedulerApi.ArangoProfile, error) { + return WithUpdateStatusInterfaceRetry[schedulerApi.ProfileStatus, *schedulerApi.ArangoProfile](ctx, client, obj, status, opts) +} + func WithArangoStorageUpdateStatusInterfaceRetry(ctx context.Context, client UpdateStatusInterface[mlApi.ArangoMLStorageStatus, *mlApi.ArangoMLStorage], obj *mlApi.ArangoMLStorage, status mlApi.ArangoMLStorageStatus, opts meta.UpdateOptions) (*mlApi.ArangoMLStorage, error) { return WithUpdateStatusInterfaceRetry[mlApi.ArangoMLStorageStatus, *mlApi.ArangoMLStorage](ctx, client, obj, status, opts) } diff --git a/pkg/server/server.go b/pkg/server/server.go index 940cff618..61f67bd0b 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -71,6 +71,7 @@ type Dependencies struct { ML OperatorDependency Analytics OperatorDependency Networking OperatorDependency + Scheduler OperatorDependency ClusterSync OperatorDependency Operators Operators Secrets typedCore.SecretInterface @@ -199,6 +200,10 @@ func NewServer(cli typedCore.CoreV1Interface, cfg Config, deps Dependencies) (*S r.GET("/ready/networking", gin.WrapF(deps.Networking.Probe.ReadyHandler)) readyProbes = append(readyProbes, deps.Networking.Probe) } + if deps.Scheduler.Enabled { + r.GET("/ready/scheduler", gin.WrapF(deps.Scheduler.Probe.ReadyHandler)) + readyProbes = append(readyProbes, deps.Scheduler.Probe) + } r.GET("/ready", gin.WrapF(ready(readyProbes...))) r.GET("/metrics", gin.WrapF(metrics.Handler())) r.POST("/login", s.auth.handleLogin) diff --git a/pkg/util/constants/constants.go b/pkg/util/constants/constants.go index 9b603a1f8..831bec24d 100644 --- a/pkg/util/constants/constants.go +++ b/pkg/util/constants/constants.go @@ -74,6 +74,7 @@ const ( MLLabelRole = "ml/role" AnalyticsLabelRole = "analytics/role" NetworkingLabelRole = "networking/role" + SchedulerLabelRole = "scheduler/role" AppsLabelRole = "apps/role" ClusterSyncLabelRole = "clustersync/role" LabelRole = "role" diff --git a/pkg/util/k8sutil/inspector/arangoprofile/definition.go b/pkg/util/k8sutil/inspector/arangoprofile/definition.go new file mode 100644 index 000000000..cf6e79851 --- /dev/null +++ b/pkg/util/k8sutil/inspector/arangoprofile/definition.go @@ -0,0 +1,44 @@ +// +// DISCLAIMER +// +// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package arangoprofile + +import ( + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/anonymous" + v1beta1 "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangoprofile/v1beta1" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/gvk" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/refresh" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/version" +) + +type Inspector interface { + ArangoProfile() Definition +} + +type Definition interface { + refresh.Inspector + + gvk.GK + anonymous.Impl + + Version() version.Version + + V1Beta1() (v1beta1.Inspector, error) +} diff --git a/pkg/util/k8sutil/inspector/arangoprofile/v1beta1/loader.go b/pkg/util/k8sutil/inspector/arangoprofile/v1beta1/loader.go new file mode 100644 index 000000000..64844795f --- /dev/null +++ b/pkg/util/k8sutil/inspector/arangoprofile/v1beta1/loader.go @@ -0,0 +1,53 @@ +// +// DISCLAIMER +// +// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package v1beta1 + +import ( + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/gvk" +) + +type Inspector interface { + gvk.GVK + + ListSimple() []*schedulerApi.ArangoProfile + GetSimple(name string) (*schedulerApi.ArangoProfile, bool) + Filter(filters ...Filter) []*schedulerApi.ArangoProfile + Iterate(action Action, filters ...Filter) error + Read() ReadInterface +} + +type Filter func(at *schedulerApi.ArangoProfile) bool +type Action func(at *schedulerApi.ArangoProfile) error + +func FilterObject(at *schedulerApi.ArangoProfile, filters ...Filter) bool { + for _, f := range filters { + if f == nil { + continue + } + + if !f(at) { + return false + } + } + + return true +} diff --git a/pkg/util/k8sutil/inspector/arangoprofile/v1beta1/reader.go b/pkg/util/k8sutil/inspector/arangoprofile/v1beta1/reader.go new file mode 100644 index 000000000..1cc3a44cf --- /dev/null +++ b/pkg/util/k8sutil/inspector/arangoprofile/v1beta1/reader.go @@ -0,0 +1,50 @@ +// +// DISCLAIMER +// +// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package v1beta1 + +import ( + "context" + + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" +) + +// ModInterface has methods to work with ArangoTask resources only for creation +type ModInterface interface { + Create(ctx context.Context, arangotask *schedulerApi.ArangoProfile, opts meta.CreateOptions) (*schedulerApi.ArangoProfile, error) + Update(ctx context.Context, arangotask *schedulerApi.ArangoProfile, opts meta.UpdateOptions) (*schedulerApi.ArangoProfile, error) + UpdateStatus(ctx context.Context, arangotask *schedulerApi.ArangoProfile, opts meta.UpdateOptions) (*schedulerApi.ArangoProfile, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts meta.PatchOptions, subresources ...string) (result *schedulerApi.ArangoProfile, err error) + Delete(ctx context.Context, name string, opts meta.DeleteOptions) error +} + +// Interface has methods to work with ArangoTask resources. +type Interface interface { + ModInterface + ReadInterface +} + +// ReadInterface has methods to work with ArangoTask resources with ReadOnly mode. +type ReadInterface interface { + Get(ctx context.Context, name string, opts meta.GetOptions) (*schedulerApi.ArangoProfile, error) +} diff --git a/pkg/util/k8sutil/inspector/constants/ap_constants.go b/pkg/util/k8sutil/inspector/constants/ap_constants.go new file mode 100644 index 000000000..fdcb4960b --- /dev/null +++ b/pkg/util/k8sutil/inspector/constants/ap_constants.go @@ -0,0 +1,66 @@ +// +// DISCLAIMER +// +// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany +// +// 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. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package constants + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/arangodb/kube-arangodb/pkg/apis/scheduler" + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" +) + +// ArangoProfile +const ( + ArangoProfileGroup = scheduler.ArangoSchedulerGroupName + ArangoProfileResource = scheduler.ArangoProfileResourcePlural + ArangoProfileKind = scheduler.ArangoProfileResourceKind + ArangoProfileVersionV1Beta1 = schedulerApi.ArangoSchedulerVersion +) + +func ArangoProfileGK() schema.GroupKind { + return schema.GroupKind{ + Group: ArangoProfileGroup, + Kind: ArangoProfileKind, + } +} + +func ArangoProfileGKv1() schema.GroupVersionKind { + return schema.GroupVersionKind{ + Group: ArangoProfileGroup, + Kind: ArangoProfileKind, + Version: ArangoProfileVersionV1Beta1, + } +} + +func ArangoProfileGR() schema.GroupResource { + return schema.GroupResource{ + Group: ArangoProfileGroup, + Resource: ArangoProfileResource, + } +} + +func ArangoProfileGRv1() schema.GroupVersionResource { + return schema.GroupVersionResource{ + Group: ArangoProfileGroup, + Resource: ArangoProfileResource, + Version: ArangoProfileVersionV1Beta1, + } +} diff --git a/pkg/util/k8sutil/inspector/constants/gvk.go b/pkg/util/k8sutil/inspector/constants/gvk.go index 3bce1cc17..e1128171d 100644 --- a/pkg/util/k8sutil/inspector/constants/gvk.go +++ b/pkg/util/k8sutil/inspector/constants/gvk.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany +// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,6 +27,8 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" + networkingApi "github.com/arangodb/kube-arangodb/pkg/apis/networking/v1alpha1" + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" ) func ExtractGVKFromObject(in interface{}) (schema.GroupVersionKind, bool) { @@ -38,6 +40,10 @@ func ExtractGVKFromObject(in interface{}) (schema.GroupVersionKind, bool) { return ArangoMemberGKv1(), true case *api.ArangoTask, api.ArangoTask: return ArangoTaskGKv1(), true + case *schedulerApi.ArangoProfile, schedulerApi.ArangoProfile: + return ArangoProfileGKv1(), true + case *networkingApi.ArangoRoute, networkingApi.ArangoRoute: + return ArangoRouteGKv1(), true case *core.Endpoints, core.Endpoints: return EndpointsGKv1(), true case *core.Node, core.Node: diff --git a/pkg/util/k8sutil/inspector/constants/gvk_test.go b/pkg/util/k8sutil/inspector/constants/gvk_test.go index 0abb7a1f6..de91cb980 100644 --- a/pkg/util/k8sutil/inspector/constants/gvk_test.go +++ b/pkg/util/k8sutil/inspector/constants/gvk_test.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany +// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -31,12 +31,17 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" + networkingApi "github.com/arangodb/kube-arangodb/pkg/apis/networking/v1alpha1" + schedulerApi "github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1beta1" ) func Test_GVK(t *testing.T) { testGVK(t, ArangoClusterSynchronizationGKv1(), &api.ArangoClusterSynchronization{}, api.ArangoClusterSynchronization{}) testGVK(t, ArangoMemberGKv1(), &api.ArangoMember{}, api.ArangoMember{}) testGVK(t, ArangoTaskGKv1(), &api.ArangoTask{}, api.ArangoTask{}) + testGVK(t, ArangoRouteGKv1(), &networkingApi.ArangoRoute{}, networkingApi.ArangoRoute{}) + testGVK(t, ArangoProfileGKv1(), &schedulerApi.ArangoProfile{}, schedulerApi.ArangoProfile{}) + testGVK(t, ArangoTaskGKv1(), &api.ArangoTask{}, api.ArangoTask{}) testGVK(t, EndpointsGKv1(), &core.Endpoints{}, core.Endpoints{}) testGVK(t, NodeGKv1(), &core.Node{}, core.Node{}) testGVK(t, PodDisruptionBudgetGKv1(), &policy.PodDisruptionBudget{}, policy.PodDisruptionBudget{}) diff --git a/pkg/util/k8sutil/inspector/definitions/components.go b/pkg/util/k8sutil/inspector/definitions/components.go index e78759c2a..886cddaf3 100644 --- a/pkg/util/k8sutil/inspector/definitions/components.go +++ b/pkg/util/k8sutil/inspector/definitions/components.go @@ -29,6 +29,7 @@ const ( ArangoMember Component = "ArangoMember" ArangoTask Component = "ArangoTask" ArangoRoute Component = "ArangoRoute" + ArangoProfile Component = "ArangoProfile" Node Component = "Node" PersistentVolume Component = "PersistentVolume" PersistentVolumeClaim Component = "PersistentVolumeClaim" @@ -48,6 +49,7 @@ func AllComponents() []Component { ArangoMember, ArangoTask, ArangoRoute, + ArangoProfile, Node, PersistentVolume, PersistentVolumeClaim, diff --git a/pkg/util/k8sutil/inspector/inspector.go b/pkg/util/k8sutil/inspector/inspector.go index 6064b7e0a..41a1631aa 100644 --- a/pkg/util/k8sutil/inspector/inspector.go +++ b/pkg/util/k8sutil/inspector/inspector.go @@ -32,6 +32,7 @@ import ( "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangoclustersynchronization" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangodeployment" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangomember" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangoprofile" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangoroute" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangotask" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/configmap" @@ -94,6 +95,7 @@ type Inspector interface { arangoclustersynchronization.Inspector arangotask.Inspector arangoroute.Inspector + arangoprofile.Inspector mods.Mods diff --git a/pkg/util/k8sutil/inspector/mods/mods.go b/pkg/util/k8sutil/inspector/mods/mods.go index 3f1e2761c..62eeb6295 100644 --- a/pkg/util/k8sutil/inspector/mods/mods.go +++ b/pkg/util/k8sutil/inspector/mods/mods.go @@ -23,6 +23,7 @@ package mods import ( arangoclustersynchronizationv1 "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangoclustersynchronization/v1" arangomemberv1 "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangomember/v1" + arangoProfilev1beta1 "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangoprofile/v1beta1" arangoroutev1alpha1 "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangoroute/v1alpha1" arangotaskv1 "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/arangotask/v1" configMapv1 "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/configmap/v1" @@ -88,6 +89,10 @@ type ArangoRouteMods interface { V1Alpha1() arangoroutev1alpha1.ModInterface } +type ArangoProfileMods interface { + V1Beta1() arangoProfilev1beta1.ModInterface +} + type Mods interface { PodsModInterface() PodsMods ServiceAccountsModInterface() ServiceAccountsMods @@ -103,4 +108,5 @@ type Mods interface { ArangoTaskModInterface() ArangoTaskMods ArangoClusterSynchronizationModInterface() ArangoClusterSynchronizationMods ArangoRouteModInterface() ArangoRouteMods + ArangoProfileModInterface() ArangoProfileMods } diff --git a/pkg/util/k8sutil/inspector/throttle/throttle.go b/pkg/util/k8sutil/inspector/throttle/throttle.go index 0fe1afde6..d1a178737 100644 --- a/pkg/util/k8sutil/inspector/throttle/throttle.go +++ b/pkg/util/k8sutil/inspector/throttle/throttle.go @@ -32,15 +32,16 @@ type Inspector interface { } func NewAlwaysThrottleComponents() Components { - return NewThrottleComponents(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + return NewThrottleComponents(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) } -func NewThrottleComponents(acs, am, at, ar, node, pvc, pod, pv, pdb, secret, cm, service, serviceAccount, sm, endpoints time.Duration) Components { +func NewThrottleComponents(acs, am, at, ar, ap, node, pvc, pod, pv, pdb, secret, cm, service, serviceAccount, sm, endpoints time.Duration) Components { return &throttleComponents{ arangoClusterSynchronization: NewThrottle(acs), arangoMember: NewThrottle(am), arangoTask: NewThrottle(at), arangoRoute: NewThrottle(ar), + arangoProfile: NewThrottle(ap), node: NewThrottle(node), persistentVolume: NewThrottle(pv), persistentVolumeClaim: NewThrottle(pvc), @@ -60,6 +61,7 @@ type Components interface { ArangoMember() Throttle ArangoTask() Throttle ArangoRoute() Throttle + ArangoProfile() Throttle Node() Throttle PersistentVolume() Throttle PersistentVolumeClaim() Throttle @@ -84,6 +86,7 @@ type throttleComponents struct { arangoMember Throttle arangoTask Throttle arangoRoute Throttle + arangoProfile Throttle node Throttle persistentVolume Throttle persistentVolumeClaim Throttle @@ -138,6 +141,8 @@ func (t *throttleComponents) Get(c definitions.Component) Throttle { return t.arangoTask case definitions.ArangoRoute: return t.arangoRoute + case definitions.ArangoProfile: + return t.arangoProfile case definitions.Node: return t.node case definitions.PersistentVolume: @@ -171,6 +176,7 @@ func (t *throttleComponents) Copy() Components { arangoMember: t.arangoMember.Copy(), arangoTask: t.arangoTask.Copy(), arangoRoute: t.arangoRoute.Copy(), + arangoProfile: t.arangoProfile.Copy(), node: t.node.Copy(), persistentVolume: t.persistentVolume.Copy(), persistentVolumeClaim: t.persistentVolumeClaim.Copy(), @@ -201,6 +207,10 @@ func (t *throttleComponents) ArangoRoute() Throttle { return t.arangoRoute } +func (t *throttleComponents) ArangoProfile() Throttle { + return t.arangoProfile +} + func (t *throttleComponents) Node() Throttle { return t.node }