From 17de36eb646cc4f46bd5f148e37c84aa8b3401c0 Mon Sep 17 00:00:00 2001 From: chaosi-zju Date: Sat, 20 Apr 2024 21:12:28 +0800 Subject: [PATCH] Introduce a new API named WorkloadRebalancer to support rescheduling Signed-off-by: chaosi-zju --- api/openapi-spec/swagger.json | 1037 +++++++++++++++++ ...rk.karmada.io_clusterresourcebindings.yaml | 18 + .../work.karmada.io_resourcebindings.yaml | 18 + .../app/controllermanager.go | 14 + hack/tools/swagger/generateswagger.go | 6 + hack/update-codegen.sh | 17 +- pkg/apis/apps/v1alpha1/doc.go | 21 + .../apps/v1alpha1/workloadrebalancer_types.go | 125 ++ .../apps/v1alpha1/zz_generated.deepcopy.go | 162 +++ .../apps/v1alpha1/zz_generated.register.go | 67 ++ pkg/apis/work/v1alpha2/binding_types.go | 15 + .../work/v1alpha2/zz_generated.deepcopy.go | 8 + .../workloadrebalancer_controller.go | 188 +++ .../clientset/versioned/clientset.go | 13 + pkg/generated/clientset/versioned/doc.go | 4 - .../versioned/fake/clientset_generated.go | 7 + .../clientset/versioned/fake/register.go | 2 + .../clientset/versioned/scheme/register.go | 2 + .../typed/apps/v1alpha1/apps_client.go | 107 ++ .../versioned/typed/apps/v1alpha1/doc.go | 20 + .../versioned/typed/apps/v1alpha1/fake/doc.go | 20 + .../apps/v1alpha1/fake/fake_apps_client.go | 40 + .../v1alpha1/fake/fake_workloadrebalancer.go | 132 +++ .../apps/v1alpha1/generated_expansion.go | 21 + .../typed/apps/v1alpha1/workloadrebalancer.go | 184 +++ .../externalversions/apps/interface.go | 46 + .../apps/v1alpha1/interface.go | 45 + .../apps/v1alpha1/workloadrebalancer.go | 89 ++ .../informers/externalversions/factory.go | 6 + .../informers/externalversions/generic.go | 13 +- .../apps/v1alpha1/expansion_generated.go | 23 + .../apps/v1alpha1/workloadrebalancer.go | 68 ++ pkg/generated/openapi/zz_generated.openapi.go | 285 ++++- pkg/util/apigroup.go | 2 + pkg/util/gclient/gclient.go | 4 +- 35 files changed, 2815 insertions(+), 14 deletions(-) create mode 100644 pkg/apis/apps/v1alpha1/doc.go create mode 100644 pkg/apis/apps/v1alpha1/workloadrebalancer_types.go create mode 100644 pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go create mode 100644 pkg/apis/apps/v1alpha1/zz_generated.register.go create mode 100644 pkg/controllers/workloadrebalancer/workloadrebalancer_controller.go delete mode 100644 pkg/generated/clientset/versioned/doc.go create mode 100644 pkg/generated/clientset/versioned/typed/apps/v1alpha1/apps_client.go create mode 100644 pkg/generated/clientset/versioned/typed/apps/v1alpha1/doc.go create mode 100644 pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake/doc.go create mode 100644 pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake/fake_apps_client.go create mode 100644 pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake/fake_workloadrebalancer.go create mode 100644 pkg/generated/clientset/versioned/typed/apps/v1alpha1/generated_expansion.go create mode 100644 pkg/generated/clientset/versioned/typed/apps/v1alpha1/workloadrebalancer.go create mode 100644 pkg/generated/informers/externalversions/apps/interface.go create mode 100644 pkg/generated/informers/externalversions/apps/v1alpha1/interface.go create mode 100644 pkg/generated/informers/externalversions/apps/v1alpha1/workloadrebalancer.go create mode 100644 pkg/generated/listers/apps/v1alpha1/expansion_generated.go create mode 100644 pkg/generated/listers/apps/v1alpha1/workloadrebalancer.go mode change 100755 => 100644 pkg/generated/openapi/zz_generated.openapi.go diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index f6ba791bbfb4..c49b3f724017 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -40,6 +40,852 @@ } } }, + "/apis/apps.karmada.io/": { + "get": { + "description": "get information of a group", + "consumes": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo" + ], + "operationId": "getAppsKarmadaIoAPIGroup", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup" + } + } + } + } + }, + "/apis/apps.karmada.io/v1alpha1/": { + "get": { + "description": "get available resources", + "consumes": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "getAppsKarmadaIoV1alpha1APIResources", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList" + } + } + } + } + }, + "/apis/apps.karmada.io/v1alpha1/watch/workloadrebalancers": { + "get": { + "description": "watch individual changes to a list of WorkloadRebalancer. deprecated: use the 'watch' parameter with a list operation instead.", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "watchAppsKarmadaIoV1alpha1WorkloadRebalancerList", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "apps.karmada.io", + "version": "v1alpha1", + "kind": "WorkloadRebalancer" + } + }, + "parameters": [ + { + "$ref": "#/parameters/allowWatchBookmarks-HC2hJt-J" + }, + { + "$ref": "#/parameters/continue-QfD61s0i" + }, + { + "$ref": "#/parameters/fieldSelector-xIcQKXFG" + }, + { + "$ref": "#/parameters/labelSelector-5Zw57w4C" + }, + { + "$ref": "#/parameters/limit-1NfNmdNH" + }, + { + "$ref": "#/parameters/pretty-nN7o5FEq" + }, + { + "$ref": "#/parameters/resourceVersion-5WAnf1kx" + }, + { + "$ref": "#/parameters/resourceVersionMatch-t8XhRHeC" + }, + { + "$ref": "#/parameters/sendInitialEvents-rLXlEK_k" + }, + { + "$ref": "#/parameters/timeoutSeconds-yvYezaOC" + }, + { + "$ref": "#/parameters/watch-XNNPZGbK" + } + ] + }, + "/apis/apps.karmada.io/v1alpha1/watch/workloadrebalancers/{name}": { + "get": { + "description": "watch changes to an object of kind WorkloadRebalancer. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "watchAppsKarmadaIoV1alpha1WorkloadRebalancer", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + } + }, + "x-kubernetes-action": "watch", + "x-kubernetes-group-version-kind": { + "group": "apps.karmada.io", + "version": "v1alpha1", + "kind": "WorkloadRebalancer" + } + }, + "parameters": [ + { + "$ref": "#/parameters/allowWatchBookmarks-HC2hJt-J" + }, + { + "$ref": "#/parameters/continue-QfD61s0i" + }, + { + "$ref": "#/parameters/fieldSelector-xIcQKXFG" + }, + { + "$ref": "#/parameters/labelSelector-5Zw57w4C" + }, + { + "$ref": "#/parameters/limit-1NfNmdNH" + }, + { + "uniqueItems": true, + "type": "string", + "description": "name of the WorkloadRebalancer", + "name": "name", + "in": "path", + "required": true + }, + { + "$ref": "#/parameters/pretty-nN7o5FEq" + }, + { + "$ref": "#/parameters/resourceVersion-5WAnf1kx" + }, + { + "$ref": "#/parameters/resourceVersionMatch-t8XhRHeC" + }, + { + "$ref": "#/parameters/sendInitialEvents-rLXlEK_k" + }, + { + "$ref": "#/parameters/timeoutSeconds-yvYezaOC" + }, + { + "$ref": "#/parameters/watch-XNNPZGbK" + } + ] + }, + "/apis/apps.karmada.io/v1alpha1/workloadrebalancers": { + "get": { + "description": "list or watch objects of kind WorkloadRebalancer", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "listAppsKarmadaIoV1alpha1WorkloadRebalancer", + "parameters": [ + { + "$ref": "#/parameters/allowWatchBookmarks-HC2hJt-J" + }, + { + "$ref": "#/parameters/continue-QfD61s0i" + }, + { + "$ref": "#/parameters/fieldSelector-xIcQKXFG" + }, + { + "$ref": "#/parameters/labelSelector-5Zw57w4C" + }, + { + "$ref": "#/parameters/limit-1NfNmdNH" + }, + { + "$ref": "#/parameters/resourceVersion-5WAnf1kx" + }, + { + "$ref": "#/parameters/resourceVersionMatch-t8XhRHeC" + }, + { + "$ref": "#/parameters/sendInitialEvents-rLXlEK_k" + }, + { + "$ref": "#/parameters/timeoutSeconds-yvYezaOC" + }, + { + "$ref": "#/parameters/watch-XNNPZGbK" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancerList" + } + } + }, + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "apps.karmada.io", + "version": "v1alpha1", + "kind": "WorkloadRebalancer" + } + }, + "post": { + "description": "create a WorkloadRebalancer", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "createAppsKarmadaIoV1alpha1WorkloadRebalancer", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + }, + { + "uniqueItems": true, + "type": "string", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "name": "dryRun", + "in": "query" + }, + { + "$ref": "#/parameters/fieldManager-Qy4HdaTW" + }, + { + "uniqueItems": true, + "type": "string", + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default in v1.23+ - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "name": "fieldValidation", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + } + }, + "x-kubernetes-action": "post", + "x-kubernetes-group-version-kind": { + "group": "apps.karmada.io", + "version": "v1alpha1", + "kind": "WorkloadRebalancer" + } + }, + "delete": { + "description": "delete collection of WorkloadRebalancer", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "deleteAppsKarmadaIoV1alpha1CollectionWorkloadRebalancer", + "parameters": [ + { + "$ref": "#/parameters/body-2Y1dVQaQ" + }, + { + "$ref": "#/parameters/continue-QfD61s0i" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "name": "dryRun", + "in": "query" + }, + { + "$ref": "#/parameters/fieldSelector-xIcQKXFG" + }, + { + "$ref": "#/parameters/gracePeriodSeconds--K5HaBOS" + }, + { + "$ref": "#/parameters/labelSelector-5Zw57w4C" + }, + { + "$ref": "#/parameters/limit-1NfNmdNH" + }, + { + "$ref": "#/parameters/orphanDependents-uRB25kX5" + }, + { + "$ref": "#/parameters/propagationPolicy-6jk3prlO" + }, + { + "$ref": "#/parameters/resourceVersion-5WAnf1kx" + }, + { + "$ref": "#/parameters/resourceVersionMatch-t8XhRHeC" + }, + { + "$ref": "#/parameters/sendInitialEvents-rLXlEK_k" + }, + { + "$ref": "#/parameters/timeoutSeconds-yvYezaOC" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + } + }, + "x-kubernetes-action": "deletecollection", + "x-kubernetes-group-version-kind": { + "group": "apps.karmada.io", + "version": "v1alpha1", + "kind": "WorkloadRebalancer" + } + }, + "parameters": [ + { + "$ref": "#/parameters/pretty-nN7o5FEq" + } + ] + }, + "/apis/apps.karmada.io/v1alpha1/workloadrebalancers/{name}": { + "get": { + "description": "read the specified WorkloadRebalancer", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "readAppsKarmadaIoV1alpha1WorkloadRebalancer", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + } + }, + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "apps.karmada.io", + "version": "v1alpha1", + "kind": "WorkloadRebalancer" + } + }, + "put": { + "description": "replace the specified WorkloadRebalancer", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "replaceAppsKarmadaIoV1alpha1WorkloadRebalancer", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + }, + { + "uniqueItems": true, + "type": "string", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "name": "dryRun", + "in": "query" + }, + { + "$ref": "#/parameters/fieldManager-Qy4HdaTW" + }, + { + "uniqueItems": true, + "type": "string", + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default in v1.23+ - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "name": "fieldValidation", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + } + }, + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "apps.karmada.io", + "version": "v1alpha1", + "kind": "WorkloadRebalancer" + } + }, + "delete": { + "description": "delete a WorkloadRebalancer", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "deleteAppsKarmadaIoV1alpha1WorkloadRebalancer", + "parameters": [ + { + "$ref": "#/parameters/body-2Y1dVQaQ" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "name": "dryRun", + "in": "query" + }, + { + "$ref": "#/parameters/gracePeriodSeconds--K5HaBOS" + }, + { + "$ref": "#/parameters/orphanDependents-uRB25kX5" + }, + { + "$ref": "#/parameters/propagationPolicy-6jk3prlO" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + } + }, + "x-kubernetes-action": "delete", + "x-kubernetes-group-version-kind": { + "group": "apps.karmada.io", + "version": "v1alpha1", + "kind": "WorkloadRebalancer" + } + }, + "patch": { + "description": "partially update the specified WorkloadRebalancer", + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json", + "application/apply-patch+yaml" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "patchAppsKarmadaIoV1alpha1WorkloadRebalancer", + "parameters": [ + { + "$ref": "#/parameters/body-78PwaGsr" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "name": "dryRun", + "in": "query" + }, + { + "$ref": "#/parameters/fieldManager-7c6nTn1T" + }, + { + "uniqueItems": true, + "type": "string", + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default in v1.23+ - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "name": "fieldValidation", + "in": "query" + }, + { + "$ref": "#/parameters/force-tOGGb0Yi" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + } + }, + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "apps.karmada.io", + "version": "v1alpha1", + "kind": "WorkloadRebalancer" + } + }, + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "name of the WorkloadRebalancer", + "name": "name", + "in": "path", + "required": true + }, + { + "$ref": "#/parameters/pretty-nN7o5FEq" + } + ] + }, + "/apis/apps.karmada.io/v1alpha1/workloadrebalancers/{name}/status": { + "get": { + "description": "read status of the specified WorkloadRebalancer", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "readAppsKarmadaIoV1alpha1WorkloadRebalancerStatus", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + } + }, + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "apps.karmada.io", + "version": "v1alpha1", + "kind": "WorkloadRebalancer" + } + }, + "put": { + "description": "replace status of the specified WorkloadRebalancer", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "replaceAppsKarmadaIoV1alpha1WorkloadRebalancerStatus", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + }, + { + "uniqueItems": true, + "type": "string", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "name": "dryRun", + "in": "query" + }, + { + "$ref": "#/parameters/fieldManager-Qy4HdaTW" + }, + { + "uniqueItems": true, + "type": "string", + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default in v1.23+ - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "name": "fieldValidation", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + } + }, + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "apps.karmada.io", + "version": "v1alpha1", + "kind": "WorkloadRebalancer" + } + }, + "patch": { + "description": "partially update status of the specified WorkloadRebalancer", + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json", + "application/apply-patch+yaml" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "appsKarmadaIo_v1alpha1" + ], + "operationId": "patchAppsKarmadaIoV1alpha1WorkloadRebalancerStatus", + "parameters": [ + { + "$ref": "#/parameters/body-78PwaGsr" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "name": "dryRun", + "in": "query" + }, + { + "$ref": "#/parameters/fieldManager-7c6nTn1T" + }, + { + "uniqueItems": true, + "type": "string", + "description": "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default in v1.23+ - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + "name": "fieldValidation", + "in": "query" + }, + { + "$ref": "#/parameters/force-tOGGb0Yi" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + } + }, + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "apps.karmada.io", + "version": "v1alpha1", + "kind": "WorkloadRebalancer" + } + }, + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "name of the WorkloadRebalancer", + "name": "name", + "in": "path", + "required": true + }, + { + "$ref": "#/parameters/pretty-nN7o5FEq" + } + ] + }, "/apis/autoscaling.karmada.io/": { "get": { "description": "get information of a group", @@ -15780,6 +16626,179 @@ } }, "definitions": { + "com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.ObservedWorkload": { + "description": "ObservedWorkload the observed resource.", + "type": "object", + "required": [ + "apiVersion", + "kind", + "name" + ], + "properties": { + "apiVersion": { + "description": "APIVersion represents the API version of the target resource.", + "type": "string", + "default": "" + }, + "kind": { + "description": "Kind represents the Kind of the target resource.", + "type": "string", + "default": "" + }, + "name": { + "description": "Name of the target resource.", + "type": "string", + "default": "" + }, + "namespace": { + "description": "Namespace of the target resource. Default is empty, which means it is a non-namespacescoped resource.", + "type": "string" + }, + "reason": { + "description": "Reason represents a machine-readable description of why this workload failed.", + "type": "string" + }, + "state": { + "description": "State the observed state of resource.", + "type": "string" + } + } + }, + "com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.Workload": { + "description": "Workload the expected resource.", + "type": "object", + "required": [ + "apiVersion", + "kind", + "name" + ], + "properties": { + "apiVersion": { + "description": "APIVersion represents the API version of the target resource.", + "type": "string", + "default": "" + }, + "kind": { + "description": "Kind represents the Kind of the target resource.", + "type": "string", + "default": "" + }, + "name": { + "description": "Name of the target resource.", + "type": "string", + "default": "" + }, + "namespace": { + "description": "Namespace of the target resource. Default is empty, which means it is a non-namespacescoped resource.", + "type": "string" + } + } + }, + "com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer": { + "description": "WorkloadRebalancer represents the desired behavior and status of a job which can enforces a rescheduling.\n\nNotes: make sure the clocks of controller-manager and scheduler are synchronized when using this API.", + "type": "object", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "default": {}, + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Spec represents the specification of the desired behavior of WorkloadRebalancer.", + "default": {}, + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancerSpec" + }, + "status": { + "description": "Status represents the status of WorkloadRebalancer.", + "default": {}, + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancerStatus" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps.karmada.io", + "kind": "WorkloadRebalancer", + "version": "v1alpha1" + } + ] + }, + "com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancerList": { + "description": "WorkloadRebalancerList contains a list of WorkloadRebalancer", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items holds a list of WorkloadRebalancer.", + "type": "array", + "items": { + "default": {}, + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancer" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "default": {}, + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "apps.karmada.io", + "kind": "WorkloadRebalancerList", + "version": "v1alpha1" + } + ] + }, + "com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancerSpec": { + "description": "WorkloadRebalancerSpec represents the specification of the desired behavior of Reschedule.\n\nNotes: this API represents a one-time execution process, once the object is created, the execution process begins, and it will not respond to any modification of the spec field.", + "type": "object", + "required": [ + "workloads" + ], + "properties": { + "workloads": { + "description": "Workloads used to specify the list of expected resource. Nil or empty list is not allowed.", + "type": "array", + "items": { + "default": {}, + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.Workload" + } + } + } + }, + "com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.WorkloadRebalancerStatus": { + "description": "WorkloadRebalancerStatus contains information about the current status of a WorkloadRebalancer updated periodically by schedule trigger controller.", + "type": "object", + "properties": { + "observedWorkloads": { + "description": "ObservedWorkloads contains information about the execution states and messages of target resources.", + "type": "array", + "items": { + "default": {}, + "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.apps.v1alpha1.ObservedWorkload" + } + } + } + }, "com.github.karmada-io.karmada.pkg.apis.autoscaling.v1alpha1.CronFederatedHPA": { "description": "CronFederatedHPA represents a collection of repeating schedule to scale replica number of a specific workload. It can scale any resource implementing the scale subresource as well as FederatedHPA.", "type": "object", @@ -19151,6 +20170,10 @@ "$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.work.v1alpha2.BindingSnapshot" } }, + "rescheduleTriggeredAt": { + "description": "RescheduleTriggeredAt is a timestamp representing when the referenced resource is triggered rescheduling. When this field is updated, it means a rescheduling is manually triggered by user, and the expected behavior of this action is to do a complete recalculation without referring to last scheduling results. It works with the status.lastScheduledTime field, and only when this timestamp is later than timestamp in status.lastScheduledTime will the rescheduling actually execute, otherwise, ignored.\n\nIt is represented in RFC3339 form (like '2006-01-02T15:04:05Z') and is in UTC.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, "resource": { "description": "Resource represents the Kubernetes resource to be propagated.", "default": {}, @@ -19182,6 +20205,10 @@ "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Condition" } }, + "lastScheduledTime": { + "description": "LastScheduledTime representing the latest timestamp when scheduler successfully finished a scheduling. It is represented in RFC3339 form (like '2006-01-02T15:04:05Z') and is in UTC.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + }, "schedulerObservedGeneration": { "description": "SchedulerObservedGeneration is the generation(.metadata.generation) observed by the scheduler. If SchedulerObservedGeneration is less than the generation in metadata means the scheduler hasn't confirmed the scheduling result or hasn't done the schedule yet.", "type": "integer", @@ -20592,6 +21619,11 @@ "kind": "DeleteOptions", "version": "v1beta2" }, + { + "group": "apps.karmada.io", + "kind": "DeleteOptions", + "version": "v1alpha1" + }, { "group": "authentication.k8s.io", "kind": "DeleteOptions", @@ -21336,6 +22368,11 @@ "kind": "WatchEvent", "version": "v1beta2" }, + { + "group": "apps.karmada.io", + "kind": "WatchEvent", + "version": "v1alpha1" + }, { "group": "authentication.k8s.io", "kind": "WatchEvent", diff --git a/charts/karmada/_crds/bases/work/work.karmada.io_clusterresourcebindings.yaml b/charts/karmada/_crds/bases/work/work.karmada.io_clusterresourcebindings.yaml index 9c00dfe94555..9f30d9e924d1 100644 --- a/charts/karmada/_crds/bases/work/work.karmada.io_clusterresourcebindings.yaml +++ b/charts/karmada/_crds/bases/work/work.karmada.io_clusterresourcebindings.yaml @@ -1128,6 +1128,18 @@ spec: - name type: object type: array + rescheduleTriggeredAt: + description: "RescheduleTriggeredAt is a timestamp representing when + the referenced resource is triggered rescheduling. When this field + is updated, it means a rescheduling is manually triggered by user, + and the expected behavior of this action is to do a complete recalculation + without referring to last scheduling results. It works with the + status.lastScheduledTime field, and only when this timestamp is + later than timestamp in status.lastScheduledTime will the rescheduling + actually execute, otherwise, ignored. \n It is represented in RFC3339 + form (like '2006-01-02T15:04:05Z') and is in UTC." + format: date-time + type: string resource: description: Resource represents the Kubernetes resource to be propagated. properties: @@ -1279,6 +1291,12 @@ spec: - type type: object type: array + lastScheduledTime: + description: LastScheduledTime representing the latest timestamp when + scheduler successfully finished a scheduling. It is represented + in RFC3339 form (like '2006-01-02T15:04:05Z') and is in UTC. + format: date-time + type: string schedulerObservedGeneration: description: SchedulerObservedGeneration is the generation(.metadata.generation) observed by the scheduler. If SchedulerObservedGeneration is less diff --git a/charts/karmada/_crds/bases/work/work.karmada.io_resourcebindings.yaml b/charts/karmada/_crds/bases/work/work.karmada.io_resourcebindings.yaml index 6216500ea01f..8b72ba228128 100644 --- a/charts/karmada/_crds/bases/work/work.karmada.io_resourcebindings.yaml +++ b/charts/karmada/_crds/bases/work/work.karmada.io_resourcebindings.yaml @@ -1128,6 +1128,18 @@ spec: - name type: object type: array + rescheduleTriggeredAt: + description: "RescheduleTriggeredAt is a timestamp representing when + the referenced resource is triggered rescheduling. When this field + is updated, it means a rescheduling is manually triggered by user, + and the expected behavior of this action is to do a complete recalculation + without referring to last scheduling results. It works with the + status.lastScheduledTime field, and only when this timestamp is + later than timestamp in status.lastScheduledTime will the rescheduling + actually execute, otherwise, ignored. \n It is represented in RFC3339 + form (like '2006-01-02T15:04:05Z') and is in UTC." + format: date-time + type: string resource: description: Resource represents the Kubernetes resource to be propagated. properties: @@ -1279,6 +1291,12 @@ spec: - type type: object type: array + lastScheduledTime: + description: LastScheduledTime representing the latest timestamp when + scheduler successfully finished a scheduling. It is represented + in RFC3339 form (like '2006-01-02T15:04:05Z') and is in UTC. + format: date-time + type: string schedulerObservedGeneration: description: SchedulerObservedGeneration is the generation(.metadata.generation) observed by the scheduler. If SchedulerObservedGeneration is less diff --git a/cmd/controller-manager/app/controllermanager.go b/cmd/controller-manager/app/controllermanager.go index f4d40727e8d3..12498841d4f6 100644 --- a/cmd/controller-manager/app/controllermanager.go +++ b/cmd/controller-manager/app/controllermanager.go @@ -69,6 +69,7 @@ import ( "github.com/karmada-io/karmada/pkg/controllers/remediation" "github.com/karmada-io/karmada/pkg/controllers/status" "github.com/karmada-io/karmada/pkg/controllers/unifiedauth" + "github.com/karmada-io/karmada/pkg/controllers/workloadrebalancer" "github.com/karmada-io/karmada/pkg/dependenciesdistributor" "github.com/karmada-io/karmada/pkg/detector" "github.com/karmada-io/karmada/pkg/features" @@ -232,6 +233,7 @@ func init() { controllers["endpointsliceCollect"] = startEndpointSliceCollectController controllers["endpointsliceDispatch"] = startEndpointSliceDispatchController controllers["remedy"] = startRemedyController + controllers["workloadRebalancer"] = startWorkloadRebalancerController } func startClusterController(ctx controllerscontext.Context) (enabled bool, err error) { @@ -707,6 +709,18 @@ func startRemedyController(ctx controllerscontext.Context) (enabled bool, err er return true, nil } +func startWorkloadRebalancerController(ctx controllerscontext.Context) (enabled bool, err error) { + workloadRebalancer := workloadrebalancer.RebalancerController{ + Client: ctx.Mgr.GetClient(), + } + err = workloadRebalancer.SetupWithManager(ctx.Mgr) + if err != nil { + return false, err + } + + return true, nil +} + // setupControllers initialize controllers and setup one by one. func setupControllers(mgr controllerruntime.Manager, opts *options.Options, stopChan <-chan struct{}) { restConfig := mgr.GetConfig() diff --git a/hack/tools/swagger/generateswagger.go b/hack/tools/swagger/generateswagger.go index 243ddee2ae8d..d83d7e589348 100644 --- a/hack/tools/swagger/generateswagger.go +++ b/hack/tools/swagger/generateswagger.go @@ -26,6 +26,7 @@ import ( "k8s.io/kube-openapi/pkg/validation/spec" "github.com/karmada-io/karmada/hack/tools/swagger/lib" + appsv1alpha1 "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" autoscalingv1alpha1 "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1" @@ -112,6 +113,10 @@ func main() { remedyv1alpha1.SchemeGroupVersion.WithResource(remedyv1alpha1.ResourcePluralRemedy), remedyv1alpha1.SchemeGroupVersion.WithResource(remedyv1alpha1.ResourceSingularRemedy), meta.RESTScopeRoot) + mapper.AddSpecific(appsv1alpha1.SchemeGroupVersion.WithKind(appsv1alpha1.ResourceKindWorkloadRebalancer), + appsv1alpha1.SchemeGroupVersion.WithResource(appsv1alpha1.ResourcePluralWorkloadRebalancer), + appsv1alpha1.SchemeGroupVersion.WithResource(appsv1alpha1.ResourceSingularWorkloadRebalancer), meta.RESTScopeRoot) + spec, err := lib.RenderOpenAPISpec(lib.Config{ Info: spec.InfoProps{ Title: "Karmada OpenAPI", @@ -145,6 +150,7 @@ func main() { {GVR: autoscalingv1alpha1.SchemeGroupVersion.WithResource(autoscalingv1alpha1.ResourcePluralFederatedHPA), NamespaceScoped: autoscalingv1alpha1.ResourceNamespaceScopedFederatedHPA}, {GVR: autoscalingv1alpha1.SchemeGroupVersion.WithResource(autoscalingv1alpha1.ResourcePluralCronFederatedHPA), NamespaceScoped: autoscalingv1alpha1.ResourceNamespaceScopedCronFederatedHPA}, {GVR: remedyv1alpha1.SchemeGroupVersion.WithResource(remedyv1alpha1.ResourcePluralRemedy), NamespaceScoped: remedyv1alpha1.ResourceNamespaceScopedRemedy}, + {GVR: appsv1alpha1.SchemeGroupVersion.WithResource(appsv1alpha1.ResourcePluralWorkloadRebalancer), NamespaceScoped: appsv1alpha1.ResourceNamespaceScopedWorkloadRebalancer}, }, Mapper: mapper, }) diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index 490fb7e39251..9fb316ff56e6 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -110,6 +110,11 @@ deepcopy-gen \ --input-dirs=github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1 \ --output-package=github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1 \ --output-file-base=zz_generated.deepcopy +deepcopy-gen \ + --go-header-file hack/boilerplate/boilerplate.go.txt \ + --input-dirs=github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1 \ + --output-package=github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1 \ + --output-file-base=zz_generated.deepcopy echo "Generating with register-gen" register-gen \ @@ -167,6 +172,11 @@ register-gen \ --input-dirs=github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1 \ --output-package=github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1 \ --output-file-base=zz_generated.register +register-gen \ + --go-header-file hack/boilerplate/boilerplate.go.txt \ + --input-dirs=github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1 \ + --output-package=github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1 \ + --output-file-base=zz_generated.register echo "Generating with conversion-gen" conversion-gen \ @@ -184,7 +194,7 @@ echo "Generating with client-gen" client-gen \ --go-header-file hack/boilerplate/boilerplate.go.txt \ --input-base="" \ - --input=github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1,github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1,github.com/karmada-io/karmada/pkg/apis/work/v1alpha1,github.com/karmada-io/karmada/pkg/apis/work/v1alpha2,github.com/karmada-io/karmada/pkg/apis/config/v1alpha1,github.com/karmada-io/karmada/pkg/apis/networking/v1alpha1,github.com/karmada-io/karmada/pkg/apis/search/v1alpha1,github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1,github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1 \ + --input=github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1,github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1,github.com/karmada-io/karmada/pkg/apis/work/v1alpha1,github.com/karmada-io/karmada/pkg/apis/work/v1alpha2,github.com/karmada-io/karmada/pkg/apis/config/v1alpha1,github.com/karmada-io/karmada/pkg/apis/networking/v1alpha1,github.com/karmada-io/karmada/pkg/apis/search/v1alpha1,github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1,github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1,github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1 \ --output-package=github.com/karmada-io/karmada/pkg/generated/clientset \ --clientset-name=versioned client-gen \ @@ -197,7 +207,7 @@ client-gen \ echo "Generating with lister-gen" lister-gen \ --go-header-file hack/boilerplate/boilerplate.go.txt \ - --input-dirs=github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1,github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1,github.com/karmada-io/karmada/pkg/apis/work/v1alpha1,github.com/karmada-io/karmada/pkg/apis/work/v1alpha2,github.com/karmada-io/karmada/pkg/apis/config/v1alpha1,github.com/karmada-io/karmada/pkg/apis/networking/v1alpha1,github.com/karmada-io/karmada/pkg/apis/search/v1alpha1,github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1,github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1 \ + --input-dirs=github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1,github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1,github.com/karmada-io/karmada/pkg/apis/work/v1alpha1,github.com/karmada-io/karmada/pkg/apis/work/v1alpha2,github.com/karmada-io/karmada/pkg/apis/config/v1alpha1,github.com/karmada-io/karmada/pkg/apis/networking/v1alpha1,github.com/karmada-io/karmada/pkg/apis/search/v1alpha1,github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1,github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1,github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1 \ --output-package=github.com/karmada-io/karmada/pkg/generated/listers lister-gen \ --go-header-file hack/boilerplate/boilerplate.go.txt \ @@ -207,7 +217,7 @@ lister-gen \ echo "Generating with informer-gen" informer-gen \ --go-header-file hack/boilerplate/boilerplate.go.txt \ - --input-dirs=github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1,github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1,github.com/karmada-io/karmada/pkg/apis/work/v1alpha1,github.com/karmada-io/karmada/pkg/apis/work/v1alpha2,github.com/karmada-io/karmada/pkg/apis/config/v1alpha1,github.com/karmada-io/karmada/pkg/apis/networking/v1alpha1,github.com/karmada-io/karmada/pkg/apis/search/v1alpha1,github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1,github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1 \ + --input-dirs=github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1,github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1,github.com/karmada-io/karmada/pkg/apis/work/v1alpha1,github.com/karmada-io/karmada/pkg/apis/work/v1alpha2,github.com/karmada-io/karmada/pkg/apis/config/v1alpha1,github.com/karmada-io/karmada/pkg/apis/networking/v1alpha1,github.com/karmada-io/karmada/pkg/apis/search/v1alpha1,github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1,github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1,github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1 \ --versioned-clientset-package=github.com/karmada-io/karmada/pkg/generated/clientset/versioned \ --listers-package=github.com/karmada-io/karmada/pkg/generated/listers \ --output-package=github.com/karmada-io/karmada/pkg/generated/informers @@ -229,6 +239,7 @@ openapi-gen \ --input-dirs "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1" \ --input-dirs "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1" \ --input-dirs "github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1" \ + --input-dirs "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" \ --input-dirs "k8s.io/api/core/v1,k8s.io/apimachinery/pkg/api/resource" \ --input-dirs "k8s.io/apimachinery/pkg/apis/meta/v1,k8s.io/apimachinery/pkg/runtime,k8s.io/apimachinery/pkg/version" \ --input-dirs "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1,k8s.io/api/admissionregistration/v1,k8s.io/api/networking/v1" \ diff --git a/pkg/apis/apps/v1alpha1/doc.go b/pkg/apis/apps/v1alpha1/doc.go new file mode 100644 index 000000000000..0232db603b14 --- /dev/null +++ b/pkg/apis/apps/v1alpha1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2024 The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1alpha1 is the v1alpha1 version of the API. +// +k8s:deepcopy-gen=package,register +// +k8s:openapi-gen=true +// +groupName=apps.karmada.io +package v1alpha1 diff --git a/pkg/apis/apps/v1alpha1/workloadrebalancer_types.go b/pkg/apis/apps/v1alpha1/workloadrebalancer_types.go new file mode 100644 index 000000000000..ef24d96f30e1 --- /dev/null +++ b/pkg/apis/apps/v1alpha1/workloadrebalancer_types.go @@ -0,0 +1,125 @@ +/* +Copyright 2024 The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +const ( + // ResourceKindWorkloadRebalancer is kind name of WorkloadRebalancer. + ResourceKindWorkloadRebalancer = "WorkloadRebalancer" + // ResourceSingularWorkloadRebalancer is singular name of WorkloadRebalancer. + ResourceSingularWorkloadRebalancer = "workloadrebalancer" + // ResourcePluralWorkloadRebalancer is kind plural name of WorkloadRebalancer. + ResourcePluralWorkloadRebalancer = "workloadrebalancers" + // ResourceNamespaceScopedWorkloadRebalancer indicates if WorkloadRebalancer is NamespaceScoped. + ResourceNamespaceScopedWorkloadRebalancer = false +) + +// +genclient +// +genclient:nonNamespaced +// +kubebuilder:resource:path=workloadrebalancers,scope="Cluster",shortName=wr,categories={karmada-io} +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// WorkloadRebalancer represents the desired behavior and status of a job which can enforces a rescheduling. +// +// Notes: make sure the clocks of controller-manager and scheduler are synchronized when using this API. +type WorkloadRebalancer struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec represents the specification of the desired behavior of WorkloadRebalancer. + // +required + Spec WorkloadRebalancerSpec `json:"spec"` + + // Status represents the status of WorkloadRebalancer. + // +optional + Status WorkloadRebalancerStatus `json:"status,omitempty"` +} + +// WorkloadRebalancerSpec represents the specification of the desired behavior of Reschedule. +// +// Notes: this API represents a one-time execution process, once the object is created, the execution process begins, +// and it will not respond to any modification of the spec field. +type WorkloadRebalancerSpec struct { + // Workloads used to specify the list of expected resource. + // Nil or empty list is not allowed. + // +kubebuilder:validation:MinItems=1 + // +required + Workloads []Workload `json:"workloads"` +} + +// Workload the expected resource. +type Workload struct { + // APIVersion represents the API version of the target resource. + // +required + APIVersion string `json:"apiVersion"` + + // Kind represents the Kind of the target resource. + // +required + Kind string `json:"kind"` + + // Name of the target resource. + // +required + Name string `json:"name"` + + // Namespace of the target resource. + // Default is empty, which means it is a non-namespacescoped resource. + // +optional + Namespace string `json:"namespace,omitempty"` +} + +// WorkloadRebalancerStatus contains information about the current status of a WorkloadRebalancer +// updated periodically by schedule trigger controller. +type WorkloadRebalancerStatus struct { + // ObservedWorkloads contains information about the execution states and messages of target resources. + // +optional + ObservedWorkloads []ObservedWorkload `json:"observedWorkloads,omitempty"` +} + +// ObservedWorkload the observed resource. +type ObservedWorkload struct { + Workload `json:",inline"` + + // State the observed state of resource. + // +optional + State ObservedState `json:"state,omitempty"` + + // Reason represents a machine-readable description of why this workload failed. + Reason metav1.StatusReason `json:"reason,omitempty"` +} + +// ObservedState the specific extent to which the resource has been executed +type ObservedState string + +const ( + // Failed the resource has been triggered a rescheduling failed. + Failed ObservedState = "Failed" + // Success the resource has been triggered a scheduling success. + Success ObservedState = "Failed" +) + +// +kubebuilder:resource:scope="Cluster" +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// WorkloadRebalancerList contains a list of WorkloadRebalancer +type WorkloadRebalancerList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + + // Items holds a list of WorkloadRebalancer. + Items []WorkloadRebalancer `json:"items"` +} diff --git a/pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 000000000000..b4cf57ff5a53 --- /dev/null +++ b/pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,162 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObservedWorkload) DeepCopyInto(out *ObservedWorkload) { + *out = *in + out.Workload = in.Workload + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObservedWorkload. +func (in *ObservedWorkload) DeepCopy() *ObservedWorkload { + if in == nil { + return nil + } + out := new(ObservedWorkload) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Workload) DeepCopyInto(out *Workload) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Workload. +func (in *Workload) DeepCopy() *Workload { + if in == nil { + return nil + } + out := new(Workload) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkloadRebalancer) DeepCopyInto(out *WorkloadRebalancer) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadRebalancer. +func (in *WorkloadRebalancer) DeepCopy() *WorkloadRebalancer { + if in == nil { + return nil + } + out := new(WorkloadRebalancer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *WorkloadRebalancer) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkloadRebalancerList) DeepCopyInto(out *WorkloadRebalancerList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]WorkloadRebalancer, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadRebalancerList. +func (in *WorkloadRebalancerList) DeepCopy() *WorkloadRebalancerList { + if in == nil { + return nil + } + out := new(WorkloadRebalancerList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *WorkloadRebalancerList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkloadRebalancerSpec) DeepCopyInto(out *WorkloadRebalancerSpec) { + *out = *in + if in.Workloads != nil { + in, out := &in.Workloads, &out.Workloads + *out = make([]Workload, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadRebalancerSpec. +func (in *WorkloadRebalancerSpec) DeepCopy() *WorkloadRebalancerSpec { + if in == nil { + return nil + } + out := new(WorkloadRebalancerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkloadRebalancerStatus) DeepCopyInto(out *WorkloadRebalancerStatus) { + *out = *in + if in.ObservedWorkloads != nil { + in, out := &in.ObservedWorkloads, &out.ObservedWorkloads + *out = make([]ObservedWorkload, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadRebalancerStatus. +func (in *WorkloadRebalancerStatus) DeepCopy() *WorkloadRebalancerStatus { + if in == nil { + return nil + } + out := new(WorkloadRebalancerStatus) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/apis/apps/v1alpha1/zz_generated.register.go b/pkg/apis/apps/v1alpha1/zz_generated.register.go new file mode 100644 index 000000000000..a97f75390e21 --- /dev/null +++ b/pkg/apis/apps/v1alpha1/zz_generated.register.go @@ -0,0 +1,67 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by register-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "apps.karmada.io" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Depreciated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &WorkloadRebalancer{}, + &WorkloadRebalancerList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + v1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/pkg/apis/work/v1alpha2/binding_types.go b/pkg/apis/work/v1alpha2/binding_types.go index b9868f32528d..0c16b71d36ad 100644 --- a/pkg/apis/work/v1alpha2/binding_types.go +++ b/pkg/apis/work/v1alpha2/binding_types.go @@ -136,6 +136,16 @@ type ResourceBindingSpec struct { // +kubebuilder:validation:Enum=Abort;Overwrite // +optional ConflictResolution policyv1alpha1.ConflictResolution `json:"conflictResolution,omitempty"` + + // RescheduleTriggeredAt is a timestamp representing when the referenced resource is triggered rescheduling. + // When this field is updated, it means a rescheduling is manually triggered by user, and the expected behavior + // of this action is to do a complete recalculation without referring to last scheduling results. + // It works with the status.lastScheduledTime field, and only when this timestamp is later than timestamp in + // status.lastScheduledTime will the rescheduling actually execute, otherwise, ignored. + // + // It is represented in RFC3339 form (like '2006-01-02T15:04:05Z') and is in UTC. + // +optional + RescheduleTriggeredAt *metav1.Time `json:"rescheduleTriggeredAt,omitempty"` } // ObjectReference contains enough information to locate the referenced object inside current cluster. @@ -297,6 +307,11 @@ type ResourceBindingStatus struct { // +optional SchedulerObservedAffinityName string `json:"schedulerObservingAffinityName,omitempty"` + // LastScheduledTime representing the latest timestamp when scheduler successfully finished a scheduling. + // It is represented in RFC3339 form (like '2006-01-02T15:04:05Z') and is in UTC. + // +optional + LastScheduledTime *metav1.Time `json:"lastScheduledTime,omitempty"` + // Conditions contain the different condition statuses. // +optional Conditions []metav1.Condition `json:"conditions,omitempty"` diff --git a/pkg/apis/work/v1alpha2/zz_generated.deepcopy.go b/pkg/apis/work/v1alpha2/zz_generated.deepcopy.go index 0a05f8f7a486..476b0aed3746 100644 --- a/pkg/apis/work/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/apis/work/v1alpha2/zz_generated.deepcopy.go @@ -344,6 +344,10 @@ func (in *ResourceBindingSpec) DeepCopyInto(out *ResourceBindingSpec) { *out = new(v1alpha1.FailoverBehavior) (*in).DeepCopyInto(*out) } + if in.RescheduleTriggeredAt != nil { + in, out := &in.RescheduleTriggeredAt, &out.RescheduleTriggeredAt + *out = (*in).DeepCopy() + } return } @@ -360,6 +364,10 @@ func (in *ResourceBindingSpec) DeepCopy() *ResourceBindingSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceBindingStatus) DeepCopyInto(out *ResourceBindingStatus) { *out = *in + if in.LastScheduledTime != nil { + in, out := &in.LastScheduledTime, &out.LastScheduledTime + *out = (*in).DeepCopy() + } if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make([]metav1.Condition, len(*in)) diff --git a/pkg/controllers/workloadrebalancer/workloadrebalancer_controller.go b/pkg/controllers/workloadrebalancer/workloadrebalancer_controller.go new file mode 100644 index 000000000000..cc893468d8f7 --- /dev/null +++ b/pkg/controllers/workloadrebalancer/workloadrebalancer_controller.go @@ -0,0 +1,188 @@ +/* +Copyright 2024 The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package workloadrebalancer + +import ( + "context" + "fmt" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/util/retry" + "k8s.io/klog/v2" + controllerruntime "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/predicate" + + appsv1alpha1 "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" + workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2" + "github.com/karmada-io/karmada/pkg/util/names" +) + +const ( + // ControllerName is the controller name that will be used when reporting events. + ControllerName = "workload-rebalancer" +) + +// RebalancerController is to handle a rebalance to workloads selected by WorkloadRebalancer object. +type RebalancerController struct { + Client client.Client +} + +var predicateFunc = predicate.Funcs{ + CreateFunc: func(e event.CreateEvent) bool { return true }, + UpdateFunc: func(e event.UpdateEvent) bool { return false }, + DeleteFunc: func(event.DeleteEvent) bool { return false }, + GenericFunc: func(event.GenericEvent) bool { return false }, +} + +// SetupWithManager creates a controller and register to controller manager. +func (s *RebalancerController) SetupWithManager(mgr controllerruntime.Manager) error { + return controllerruntime.NewControllerManagedBy(mgr). + Named(ControllerName). + For(&appsv1alpha1.WorkloadRebalancer{}, builder.WithPredicates(predicateFunc)). + Complete(s) +} + +// Reconcile performs a full reconciliation for the object referred to by the Request. +// The Controller will requeue the Request to be processed again if an error is non-nil or +// Result.Requeue is true, otherwise upon completion it will remove the work from the queue. +func (s *RebalancerController) Reconcile(ctx context.Context, req controllerruntime.Request) (controllerruntime.Result, error) { + klog.V(4).Infof("Reconciling for WorkloadRebalancer %s", req.Name) + + // 1. get latest WorkloadRebalancer + rebalancer := &appsv1alpha1.WorkloadRebalancer{} + if err := s.Client.Get(ctx, req.NamespacedName, rebalancer); err != nil { + if apierrors.IsNotFound(err) { + klog.Infof("no need to reconcile WorkloadRebalancer for it not found") + return controllerruntime.Result{}, nil + } + return controllerruntime.Result{}, err + } + + // 2. build status of WorkloadRebalancer + if len(rebalancer.Status.ObservedWorkloads) == 0 { + s.buildWorkloadRebalancerStatus(rebalancer) + } + + // 3. get and update referenced binding to trigger a rescheduling + successNum, retryNum := int64(0), int64(0) + for _, resource := range rebalancer.Status.ObservedWorkloads { + if resource.State == appsv1alpha1.Success { + successNum++ + continue + } + if resource.State == appsv1alpha1.Failed && resource.Reason == metav1.StatusReasonNotFound { + continue + } + + bindingName := names.GenerateBindingName(resource.Kind, resource.Name) + // resource with empty namespace represents it is a cluster wide resource. + if resource.Namespace != "" { + binding := &workv1alpha2.ResourceBinding{} + if err := s.Client.Get(ctx, client.ObjectKey{Namespace: resource.Namespace, Name: bindingName}, binding); err != nil { + klog.Errorf("get binding failed: %+v", err) + s.recordWorkloadRebalanceFailed(&resource, &retryNum, err) + continue + } + // update spec.rescheduleTriggeredAt of referenced fetchTargetRefBindings to trigger a rescheduling + if s.needTriggerReschedule(rebalancer.CreationTimestamp, binding.Spec.RescheduleTriggeredAt) { + binding.Spec.RescheduleTriggeredAt = &rebalancer.CreationTimestamp + + if err := s.Client.Update(ctx, binding); err != nil { + klog.Errorf("update binding failed: %+v", err) + s.recordWorkloadRebalanceFailed(&resource, &retryNum, err) + continue + } + } + s.recordWorkloadRebalanceSuccess(&resource, &successNum) + } else { + clusterbinding := &workv1alpha2.ClusterResourceBinding{} + if err := s.Client.Get(ctx, client.ObjectKey{Name: bindingName}, clusterbinding); err != nil { + klog.Errorf("get cluster binding failed: %+v", err) + s.recordWorkloadRebalanceFailed(&resource, &retryNum, err) + continue + } + // update spec.rescheduleTriggeredAt of referenced clusterbinding to trigger a rescheduling + if s.needTriggerReschedule(rebalancer.CreationTimestamp, clusterbinding.Spec.RescheduleTriggeredAt) { + clusterbinding.Spec.RescheduleTriggeredAt = &rebalancer.CreationTimestamp + + if err := s.Client.Update(ctx, clusterbinding); err != nil { + klog.Errorf("update cluster binding failed: %+v", err) + s.recordWorkloadRebalanceFailed(&resource, &retryNum, err) + continue + } + } + s.recordWorkloadRebalanceSuccess(&resource, &successNum) + } + } + + // 4. update status of WorkloadRebalancer + if err := s.updateWorkloadRebalancerStatus(rebalancer); err != nil { + return controllerruntime.Result{}, err + } + klog.Infof("Finish handling WorkloadRebalancer (%s), %d/%d resource success in all, while %d resource need retry", + rebalancer.Name, successNum, len(rebalancer.Status.ObservedWorkloads), retryNum) + + if retryNum > 0 { + return controllerruntime.Result{}, fmt.Errorf("%d resource reschedule triggered failed and need retry", retryNum) + } + return controllerruntime.Result{}, nil +} + +func (s *RebalancerController) buildWorkloadRebalancerStatus(rebalancer *appsv1alpha1.WorkloadRebalancer) { + resourceList := make([]appsv1alpha1.ObservedWorkload, 0) + for _, resource := range rebalancer.Spec.Workloads { + resourceList = append(resourceList, appsv1alpha1.ObservedWorkload{ + Workload: resource, + }) + } + rebalancer.Status.ObservedWorkloads = resourceList +} + +func (s *RebalancerController) needTriggerReschedule(creationTimestamp metav1.Time, rescheduleTriggeredAt *metav1.Time) bool { + return rescheduleTriggeredAt == nil || creationTimestamp.After(rescheduleTriggeredAt.Time) +} + +func (s *RebalancerController) recordWorkloadRebalanceSuccess(resource *appsv1alpha1.ObservedWorkload, successNum *int64) { + resource.State = appsv1alpha1.Success + *successNum++ +} + +func (s *RebalancerController) recordWorkloadRebalanceFailed(resource *appsv1alpha1.ObservedWorkload, retryNum *int64, err error) { + resource.State = appsv1alpha1.Failed + resource.Reason = apierrors.ReasonForError(err) + if resource.Reason != metav1.StatusReasonNotFound { + *retryNum++ + } +} + +func (s *RebalancerController) updateWorkloadRebalancerStatus(rebalancer *appsv1alpha1.WorkloadRebalancer) error { + rebalancerCopy := rebalancer.DeepCopy() + rebalancerPatch := client.MergeFrom(rebalancerCopy) + + return retry.RetryOnConflict(retry.DefaultRetry, func() (err error) { + klog.V(4).Infof("Start to patch WorkloadRebalancer(%s) status", rebalancer.Name) + if err := s.Client.Patch(context.TODO(), rebalancerCopy, rebalancerPatch); err != nil { + klog.Errorf("Failed to patch WorkloadRebalancer (%s) status, err: %+v", rebalancer.Name, err) + return err + } + return nil + }) +} diff --git a/pkg/generated/clientset/versioned/clientset.go b/pkg/generated/clientset/versioned/clientset.go index 4b8ac2dfad6d..8bb42accc5c7 100644 --- a/pkg/generated/clientset/versioned/clientset.go +++ b/pkg/generated/clientset/versioned/clientset.go @@ -22,6 +22,7 @@ import ( "fmt" "net/http" + appsv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/apps/v1alpha1" autoscalingv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/autoscaling/v1alpha1" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/cluster/v1alpha1" configv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/config/v1alpha1" @@ -38,6 +39,7 @@ import ( type Interface interface { Discovery() discovery.DiscoveryInterface + AppsV1alpha1() appsv1alpha1.AppsV1alpha1Interface AutoscalingV1alpha1() autoscalingv1alpha1.AutoscalingV1alpha1Interface ClusterV1alpha1() clusterv1alpha1.ClusterV1alpha1Interface ConfigV1alpha1() configv1alpha1.ConfigV1alpha1Interface @@ -52,6 +54,7 @@ type Interface interface { // Clientset contains the clients for groups. type Clientset struct { *discovery.DiscoveryClient + appsV1alpha1 *appsv1alpha1.AppsV1alpha1Client autoscalingV1alpha1 *autoscalingv1alpha1.AutoscalingV1alpha1Client clusterV1alpha1 *clusterv1alpha1.ClusterV1alpha1Client configV1alpha1 *configv1alpha1.ConfigV1alpha1Client @@ -63,6 +66,11 @@ type Clientset struct { workV1alpha2 *workv1alpha2.WorkV1alpha2Client } +// AppsV1alpha1 retrieves the AppsV1alpha1Client +func (c *Clientset) AppsV1alpha1() appsv1alpha1.AppsV1alpha1Interface { + return c.appsV1alpha1 +} + // AutoscalingV1alpha1 retrieves the AutoscalingV1alpha1Client func (c *Clientset) AutoscalingV1alpha1() autoscalingv1alpha1.AutoscalingV1alpha1Interface { return c.autoscalingV1alpha1 @@ -152,6 +160,10 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, var cs Clientset var err error + cs.appsV1alpha1, err = appsv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } cs.autoscalingV1alpha1, err = autoscalingv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) if err != nil { return nil, err @@ -209,6 +221,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { // New creates a new Clientset for the given RESTClient. func New(c rest.Interface) *Clientset { var cs Clientset + cs.appsV1alpha1 = appsv1alpha1.New(c) cs.autoscalingV1alpha1 = autoscalingv1alpha1.New(c) cs.clusterV1alpha1 = clusterv1alpha1.New(c) cs.configV1alpha1 = configv1alpha1.New(c) diff --git a/pkg/generated/clientset/versioned/doc.go b/pkg/generated/clientset/versioned/doc.go deleted file mode 100644 index 0e0c2a8900e2..000000000000 --- a/pkg/generated/clientset/versioned/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -// This package has the automatically generated clientset. -package versioned diff --git a/pkg/generated/clientset/versioned/fake/clientset_generated.go b/pkg/generated/clientset/versioned/fake/clientset_generated.go index 615977b708fa..daa063578783 100644 --- a/pkg/generated/clientset/versioned/fake/clientset_generated.go +++ b/pkg/generated/clientset/versioned/fake/clientset_generated.go @@ -20,6 +20,8 @@ package fake import ( clientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned" + appsv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/apps/v1alpha1" + fakeappsv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake" autoscalingv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/autoscaling/v1alpha1" fakeautoscalingv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/autoscaling/v1alpha1/fake" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/cluster/v1alpha1" @@ -95,6 +97,11 @@ var ( _ testing.FakeClient = &Clientset{} ) +// AppsV1alpha1 retrieves the AppsV1alpha1Client +func (c *Clientset) AppsV1alpha1() appsv1alpha1.AppsV1alpha1Interface { + return &fakeappsv1alpha1.FakeAppsV1alpha1{Fake: &c.Fake} +} + // AutoscalingV1alpha1 retrieves the AutoscalingV1alpha1Client func (c *Clientset) AutoscalingV1alpha1() autoscalingv1alpha1.AutoscalingV1alpha1Interface { return &fakeautoscalingv1alpha1.FakeAutoscalingV1alpha1{Fake: &c.Fake} diff --git a/pkg/generated/clientset/versioned/fake/register.go b/pkg/generated/clientset/versioned/fake/register.go index a89c6fe3c2da..4ea5a3e6bd9b 100644 --- a/pkg/generated/clientset/versioned/fake/register.go +++ b/pkg/generated/clientset/versioned/fake/register.go @@ -19,6 +19,7 @@ limitations under the License. package fake import ( + appsv1alpha1 "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" autoscalingv1alpha1 "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1" @@ -39,6 +40,7 @@ var scheme = runtime.NewScheme() var codecs = serializer.NewCodecFactory(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ + appsv1alpha1.AddToScheme, autoscalingv1alpha1.AddToScheme, clusterv1alpha1.AddToScheme, configv1alpha1.AddToScheme, diff --git a/pkg/generated/clientset/versioned/scheme/register.go b/pkg/generated/clientset/versioned/scheme/register.go index e5d3cae1b722..042742612852 100644 --- a/pkg/generated/clientset/versioned/scheme/register.go +++ b/pkg/generated/clientset/versioned/scheme/register.go @@ -19,6 +19,7 @@ limitations under the License. package scheme import ( + appsv1alpha1 "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" autoscalingv1alpha1 "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1" @@ -39,6 +40,7 @@ var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) var localSchemeBuilder = runtime.SchemeBuilder{ + appsv1alpha1.AddToScheme, autoscalingv1alpha1.AddToScheme, clusterv1alpha1.AddToScheme, configv1alpha1.AddToScheme, diff --git a/pkg/generated/clientset/versioned/typed/apps/v1alpha1/apps_client.go b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/apps_client.go new file mode 100644 index 000000000000..7a1e9e50eefa --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/apps_client.go @@ -0,0 +1,107 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "net/http" + + v1alpha1 "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" + "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme" + rest "k8s.io/client-go/rest" +) + +type AppsV1alpha1Interface interface { + RESTClient() rest.Interface + WorkloadRebalancersGetter +} + +// AppsV1alpha1Client is used to interact with features provided by the apps.karmada.io group. +type AppsV1alpha1Client struct { + restClient rest.Interface +} + +func (c *AppsV1alpha1Client) WorkloadRebalancers() WorkloadRebalancerInterface { + return newWorkloadRebalancers(c) +} + +// NewForConfig creates a new AppsV1alpha1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*AppsV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new AppsV1alpha1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*AppsV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &AppsV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new AppsV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *AppsV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new AppsV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *AppsV1alpha1Client { + return &AppsV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *AppsV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/generated/clientset/versioned/typed/apps/v1alpha1/doc.go b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/doc.go new file mode 100644 index 000000000000..d7702a120bf6 --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake/doc.go b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake/doc.go new file mode 100644 index 000000000000..3a0e6b07dfb0 --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake/fake_apps_client.go b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake/fake_apps_client.go new file mode 100644 index 000000000000..5fd59b7b4909 --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake/fake_apps_client.go @@ -0,0 +1,40 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/apps/v1alpha1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeAppsV1alpha1 struct { + *testing.Fake +} + +func (c *FakeAppsV1alpha1) WorkloadRebalancers() v1alpha1.WorkloadRebalancerInterface { + return &FakeWorkloadRebalancers{c} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeAppsV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake/fake_workloadrebalancer.go b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake/fake_workloadrebalancer.go new file mode 100644 index 000000000000..21c94b19d343 --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/fake/fake_workloadrebalancer.go @@ -0,0 +1,132 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeWorkloadRebalancers implements WorkloadRebalancerInterface +type FakeWorkloadRebalancers struct { + Fake *FakeAppsV1alpha1 +} + +var workloadrebalancersResource = v1alpha1.SchemeGroupVersion.WithResource("workloadrebalancers") + +var workloadrebalancersKind = v1alpha1.SchemeGroupVersion.WithKind("WorkloadRebalancer") + +// Get takes name of the workloadRebalancer, and returns the corresponding workloadRebalancer object, and an error if there is any. +func (c *FakeWorkloadRebalancers) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.WorkloadRebalancer, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(workloadrebalancersResource, name), &v1alpha1.WorkloadRebalancer{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.WorkloadRebalancer), err +} + +// List takes label and field selectors, and returns the list of WorkloadRebalancers that match those selectors. +func (c *FakeWorkloadRebalancers) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.WorkloadRebalancerList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(workloadrebalancersResource, workloadrebalancersKind, opts), &v1alpha1.WorkloadRebalancerList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.WorkloadRebalancerList{ListMeta: obj.(*v1alpha1.WorkloadRebalancerList).ListMeta} + for _, item := range obj.(*v1alpha1.WorkloadRebalancerList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested workloadRebalancers. +func (c *FakeWorkloadRebalancers) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(workloadrebalancersResource, opts)) +} + +// Create takes the representation of a workloadRebalancer and creates it. Returns the server's representation of the workloadRebalancer, and an error, if there is any. +func (c *FakeWorkloadRebalancers) Create(ctx context.Context, workloadRebalancer *v1alpha1.WorkloadRebalancer, opts v1.CreateOptions) (result *v1alpha1.WorkloadRebalancer, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(workloadrebalancersResource, workloadRebalancer), &v1alpha1.WorkloadRebalancer{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.WorkloadRebalancer), err +} + +// Update takes the representation of a workloadRebalancer and updates it. Returns the server's representation of the workloadRebalancer, and an error, if there is any. +func (c *FakeWorkloadRebalancers) Update(ctx context.Context, workloadRebalancer *v1alpha1.WorkloadRebalancer, opts v1.UpdateOptions) (result *v1alpha1.WorkloadRebalancer, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(workloadrebalancersResource, workloadRebalancer), &v1alpha1.WorkloadRebalancer{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.WorkloadRebalancer), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeWorkloadRebalancers) UpdateStatus(ctx context.Context, workloadRebalancer *v1alpha1.WorkloadRebalancer, opts v1.UpdateOptions) (*v1alpha1.WorkloadRebalancer, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(workloadrebalancersResource, "status", workloadRebalancer), &v1alpha1.WorkloadRebalancer{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.WorkloadRebalancer), err +} + +// Delete takes name of the workloadRebalancer and deletes it. Returns an error if one occurs. +func (c *FakeWorkloadRebalancers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteActionWithOptions(workloadrebalancersResource, name, opts), &v1alpha1.WorkloadRebalancer{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeWorkloadRebalancers) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(workloadrebalancersResource, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.WorkloadRebalancerList{}) + return err +} + +// Patch applies the patch and returns the patched workloadRebalancer. +func (c *FakeWorkloadRebalancers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.WorkloadRebalancer, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(workloadrebalancersResource, name, pt, data, subresources...), &v1alpha1.WorkloadRebalancer{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.WorkloadRebalancer), err +} diff --git a/pkg/generated/clientset/versioned/typed/apps/v1alpha1/generated_expansion.go b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/generated_expansion.go new file mode 100644 index 000000000000..6a18fc43f2cd --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type WorkloadRebalancerExpansion interface{} diff --git a/pkg/generated/clientset/versioned/typed/apps/v1alpha1/workloadrebalancer.go b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/workloadrebalancer.go new file mode 100644 index 000000000000..b0a317f965c8 --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/apps/v1alpha1/workloadrebalancer.go @@ -0,0 +1,184 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" + scheme "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// WorkloadRebalancersGetter has a method to return a WorkloadRebalancerInterface. +// A group's client should implement this interface. +type WorkloadRebalancersGetter interface { + WorkloadRebalancers() WorkloadRebalancerInterface +} + +// WorkloadRebalancerInterface has methods to work with WorkloadRebalancer resources. +type WorkloadRebalancerInterface interface { + Create(ctx context.Context, workloadRebalancer *v1alpha1.WorkloadRebalancer, opts v1.CreateOptions) (*v1alpha1.WorkloadRebalancer, error) + Update(ctx context.Context, workloadRebalancer *v1alpha1.WorkloadRebalancer, opts v1.UpdateOptions) (*v1alpha1.WorkloadRebalancer, error) + UpdateStatus(ctx context.Context, workloadRebalancer *v1alpha1.WorkloadRebalancer, opts v1.UpdateOptions) (*v1alpha1.WorkloadRebalancer, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.WorkloadRebalancer, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.WorkloadRebalancerList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.WorkloadRebalancer, err error) + WorkloadRebalancerExpansion +} + +// workloadRebalancers implements WorkloadRebalancerInterface +type workloadRebalancers struct { + client rest.Interface +} + +// newWorkloadRebalancers returns a WorkloadRebalancers +func newWorkloadRebalancers(c *AppsV1alpha1Client) *workloadRebalancers { + return &workloadRebalancers{ + client: c.RESTClient(), + } +} + +// Get takes name of the workloadRebalancer, and returns the corresponding workloadRebalancer object, and an error if there is any. +func (c *workloadRebalancers) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.WorkloadRebalancer, err error) { + result = &v1alpha1.WorkloadRebalancer{} + err = c.client.Get(). + Resource("workloadrebalancers"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of WorkloadRebalancers that match those selectors. +func (c *workloadRebalancers) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.WorkloadRebalancerList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.WorkloadRebalancerList{} + err = c.client.Get(). + Resource("workloadrebalancers"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested workloadRebalancers. +func (c *workloadRebalancers) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("workloadrebalancers"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a workloadRebalancer and creates it. Returns the server's representation of the workloadRebalancer, and an error, if there is any. +func (c *workloadRebalancers) Create(ctx context.Context, workloadRebalancer *v1alpha1.WorkloadRebalancer, opts v1.CreateOptions) (result *v1alpha1.WorkloadRebalancer, err error) { + result = &v1alpha1.WorkloadRebalancer{} + err = c.client.Post(). + Resource("workloadrebalancers"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(workloadRebalancer). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a workloadRebalancer and updates it. Returns the server's representation of the workloadRebalancer, and an error, if there is any. +func (c *workloadRebalancers) Update(ctx context.Context, workloadRebalancer *v1alpha1.WorkloadRebalancer, opts v1.UpdateOptions) (result *v1alpha1.WorkloadRebalancer, err error) { + result = &v1alpha1.WorkloadRebalancer{} + err = c.client.Put(). + Resource("workloadrebalancers"). + Name(workloadRebalancer.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(workloadRebalancer). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *workloadRebalancers) UpdateStatus(ctx context.Context, workloadRebalancer *v1alpha1.WorkloadRebalancer, opts v1.UpdateOptions) (result *v1alpha1.WorkloadRebalancer, err error) { + result = &v1alpha1.WorkloadRebalancer{} + err = c.client.Put(). + Resource("workloadrebalancers"). + Name(workloadRebalancer.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(workloadRebalancer). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the workloadRebalancer and deletes it. Returns an error if one occurs. +func (c *workloadRebalancers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Resource("workloadrebalancers"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *workloadRebalancers) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("workloadrebalancers"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched workloadRebalancer. +func (c *workloadRebalancers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.WorkloadRebalancer, err error) { + result = &v1alpha1.WorkloadRebalancer{} + err = c.client.Patch(pt). + Resource("workloadrebalancers"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/generated/informers/externalversions/apps/interface.go b/pkg/generated/informers/externalversions/apps/interface.go new file mode 100644 index 000000000000..d04cd8301f67 --- /dev/null +++ b/pkg/generated/informers/externalversions/apps/interface.go @@ -0,0 +1,46 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package apps + +import ( + v1alpha1 "github.com/karmada-io/karmada/pkg/generated/informers/externalversions/apps/v1alpha1" + internalinterfaces "github.com/karmada-io/karmada/pkg/generated/informers/externalversions/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/generated/informers/externalversions/apps/v1alpha1/interface.go b/pkg/generated/informers/externalversions/apps/v1alpha1/interface.go new file mode 100644 index 000000000000..6869b7cafa78 --- /dev/null +++ b/pkg/generated/informers/externalversions/apps/v1alpha1/interface.go @@ -0,0 +1,45 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + internalinterfaces "github.com/karmada-io/karmada/pkg/generated/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // WorkloadRebalancers returns a WorkloadRebalancerInformer. + WorkloadRebalancers() WorkloadRebalancerInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// WorkloadRebalancers returns a WorkloadRebalancerInformer. +func (v *version) WorkloadRebalancers() WorkloadRebalancerInformer { + return &workloadRebalancerInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/generated/informers/externalversions/apps/v1alpha1/workloadrebalancer.go b/pkg/generated/informers/externalversions/apps/v1alpha1/workloadrebalancer.go new file mode 100644 index 000000000000..7128df60fa1e --- /dev/null +++ b/pkg/generated/informers/externalversions/apps/v1alpha1/workloadrebalancer.go @@ -0,0 +1,89 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + appsv1alpha1 "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" + versioned "github.com/karmada-io/karmada/pkg/generated/clientset/versioned" + internalinterfaces "github.com/karmada-io/karmada/pkg/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/karmada-io/karmada/pkg/generated/listers/apps/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// WorkloadRebalancerInformer provides access to a shared informer and lister for +// WorkloadRebalancers. +type WorkloadRebalancerInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.WorkloadRebalancerLister +} + +type workloadRebalancerInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewWorkloadRebalancerInformer constructs a new informer for WorkloadRebalancer type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewWorkloadRebalancerInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredWorkloadRebalancerInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredWorkloadRebalancerInformer constructs a new informer for WorkloadRebalancer type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredWorkloadRebalancerInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.AppsV1alpha1().WorkloadRebalancers().List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.AppsV1alpha1().WorkloadRebalancers().Watch(context.TODO(), options) + }, + }, + &appsv1alpha1.WorkloadRebalancer{}, + resyncPeriod, + indexers, + ) +} + +func (f *workloadRebalancerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredWorkloadRebalancerInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *workloadRebalancerInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&appsv1alpha1.WorkloadRebalancer{}, f.defaultInformer) +} + +func (f *workloadRebalancerInformer) Lister() v1alpha1.WorkloadRebalancerLister { + return v1alpha1.NewWorkloadRebalancerLister(f.Informer().GetIndexer()) +} diff --git a/pkg/generated/informers/externalversions/factory.go b/pkg/generated/informers/externalversions/factory.go index fb3feb1f23bc..f656f030fcdc 100644 --- a/pkg/generated/informers/externalversions/factory.go +++ b/pkg/generated/informers/externalversions/factory.go @@ -24,6 +24,7 @@ import ( time "time" versioned "github.com/karmada-io/karmada/pkg/generated/clientset/versioned" + apps "github.com/karmada-io/karmada/pkg/generated/informers/externalversions/apps" autoscaling "github.com/karmada-io/karmada/pkg/generated/informers/externalversions/autoscaling" cluster "github.com/karmada-io/karmada/pkg/generated/informers/externalversions/cluster" config "github.com/karmada-io/karmada/pkg/generated/informers/externalversions/config" @@ -250,6 +251,7 @@ type SharedInformerFactory interface { // client. InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer + Apps() apps.Interface Autoscaling() autoscaling.Interface Cluster() cluster.Interface Config() config.Interface @@ -260,6 +262,10 @@ type SharedInformerFactory interface { Work() work.Interface } +func (f *sharedInformerFactory) Apps() apps.Interface { + return apps.New(f, f.namespace, f.tweakListOptions) +} + func (f *sharedInformerFactory) Autoscaling() autoscaling.Interface { return autoscaling.New(f, f.namespace, f.tweakListOptions) } diff --git a/pkg/generated/informers/externalversions/generic.go b/pkg/generated/informers/externalversions/generic.go index db1d70ed164c..0793b637e0b3 100644 --- a/pkg/generated/informers/externalversions/generic.go +++ b/pkg/generated/informers/externalversions/generic.go @@ -21,7 +21,8 @@ package externalversions import ( "fmt" - v1alpha1 "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1" + v1alpha1 "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" + autoscalingv1alpha1 "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1" networkingv1alpha1 "github.com/karmada-io/karmada/pkg/apis/networking/v1alpha1" @@ -60,10 +61,14 @@ func (f *genericInformer) Lister() cache.GenericLister { // TODO extend this to unknown resources with a client pool func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { - // Group=autoscaling.karmada.io, Version=v1alpha1 - case v1alpha1.SchemeGroupVersion.WithResource("cronfederatedhpas"): + // Group=apps.karmada.io, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("workloadrebalancers"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Apps().V1alpha1().WorkloadRebalancers().Informer()}, nil + + // Group=autoscaling.karmada.io, Version=v1alpha1 + case autoscalingv1alpha1.SchemeGroupVersion.WithResource("cronfederatedhpas"): return &genericInformer{resource: resource.GroupResource(), informer: f.Autoscaling().V1alpha1().CronFederatedHPAs().Informer()}, nil - case v1alpha1.SchemeGroupVersion.WithResource("federatedhpas"): + case autoscalingv1alpha1.SchemeGroupVersion.WithResource("federatedhpas"): return &genericInformer{resource: resource.GroupResource(), informer: f.Autoscaling().V1alpha1().FederatedHPAs().Informer()}, nil // Group=cluster.karmada.io, Version=v1alpha1 diff --git a/pkg/generated/listers/apps/v1alpha1/expansion_generated.go b/pkg/generated/listers/apps/v1alpha1/expansion_generated.go new file mode 100644 index 000000000000..9b7a454a4341 --- /dev/null +++ b/pkg/generated/listers/apps/v1alpha1/expansion_generated.go @@ -0,0 +1,23 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// WorkloadRebalancerListerExpansion allows custom methods to be added to +// WorkloadRebalancerLister. +type WorkloadRebalancerListerExpansion interface{} diff --git a/pkg/generated/listers/apps/v1alpha1/workloadrebalancer.go b/pkg/generated/listers/apps/v1alpha1/workloadrebalancer.go new file mode 100644 index 000000000000..b75ec7773347 --- /dev/null +++ b/pkg/generated/listers/apps/v1alpha1/workloadrebalancer.go @@ -0,0 +1,68 @@ +/* +Copyright The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// WorkloadRebalancerLister helps list WorkloadRebalancers. +// All objects returned here must be treated as read-only. +type WorkloadRebalancerLister interface { + // List lists all WorkloadRebalancers in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.WorkloadRebalancer, err error) + // Get retrieves the WorkloadRebalancer from the index for a given name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.WorkloadRebalancer, error) + WorkloadRebalancerListerExpansion +} + +// workloadRebalancerLister implements the WorkloadRebalancerLister interface. +type workloadRebalancerLister struct { + indexer cache.Indexer +} + +// NewWorkloadRebalancerLister returns a new WorkloadRebalancerLister. +func NewWorkloadRebalancerLister(indexer cache.Indexer) WorkloadRebalancerLister { + return &workloadRebalancerLister{indexer: indexer} +} + +// List lists all WorkloadRebalancers in the indexer. +func (s *workloadRebalancerLister) List(selector labels.Selector) (ret []*v1alpha1.WorkloadRebalancer, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.WorkloadRebalancer)) + }) + return ret, err +} + +// Get retrieves the WorkloadRebalancer from the index for a given name. +func (s *workloadRebalancerLister) Get(name string) (*v1alpha1.WorkloadRebalancer, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("workloadrebalancer"), name) + } + return obj.(*v1alpha1.WorkloadRebalancer), nil +} diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go old mode 100755 new mode 100644 index 722792e6877c..e7245a78f3ae --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -33,6 +33,12 @@ import ( func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ + "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.ObservedWorkload": schema_pkg_apis_apps_v1alpha1_ObservedWorkload(ref), + "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.Workload": schema_pkg_apis_apps_v1alpha1_Workload(ref), + "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.WorkloadRebalancer": schema_pkg_apis_apps_v1alpha1_WorkloadRebalancer(ref), + "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.WorkloadRebalancerList": schema_pkg_apis_apps_v1alpha1_WorkloadRebalancerList(ref), + "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.WorkloadRebalancerSpec": schema_pkg_apis_apps_v1alpha1_WorkloadRebalancerSpec(ref), + "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.WorkloadRebalancerStatus": schema_pkg_apis_apps_v1alpha1_WorkloadRebalancerStatus(ref), "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1.CronFederatedHPA": schema_pkg_apis_autoscaling_v1alpha1_CronFederatedHPA(ref), "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1.CronFederatedHPAList": schema_pkg_apis_autoscaling_v1alpha1_CronFederatedHPAList(ref), "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1.CronFederatedHPARule": schema_pkg_apis_autoscaling_v1alpha1_CronFederatedHPARule(ref), @@ -546,6 +552,269 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA } } +func schema_pkg_apis_apps_v1alpha1_ObservedWorkload(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ObservedWorkload the observed resource.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion represents the API version of the target resource.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind represents the Kind of the target resource.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name of the target resource.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "namespace": { + SchemaProps: spec.SchemaProps{ + Description: "Namespace of the target resource. Default is empty, which means it is a non-namespacescoped resource.", + Type: []string{"string"}, + Format: "", + }, + }, + "state": { + SchemaProps: spec.SchemaProps{ + Description: "State the observed state of resource.", + Type: []string{"string"}, + Format: "", + }, + }, + "reason": { + SchemaProps: spec.SchemaProps{ + Description: "Reason represents a machine-readable description of why this workload failed.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"apiVersion", "kind", "name"}, + }, + }, + } +} + +func schema_pkg_apis_apps_v1alpha1_Workload(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Workload the expected resource.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion represents the API version of the target resource.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind represents the Kind of the target resource.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name of the target resource.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "namespace": { + SchemaProps: spec.SchemaProps{ + Description: "Namespace of the target resource. Default is empty, which means it is a non-namespacescoped resource.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"apiVersion", "kind", "name"}, + }, + }, + } +} + +func schema_pkg_apis_apps_v1alpha1_WorkloadRebalancer(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "WorkloadRebalancer represents the desired behavior and status of a job which can enforces a rescheduling.\n\nNotes: make sure the clocks of controller-manager and scheduler are synchronized when using this API.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "Spec represents the specification of the desired behavior of WorkloadRebalancer.", + Default: map[string]interface{}{}, + Ref: ref("github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.WorkloadRebalancerSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "Status represents the status of WorkloadRebalancer.", + Default: map[string]interface{}{}, + Ref: ref("github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.WorkloadRebalancerStatus"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.WorkloadRebalancerSpec", "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.WorkloadRebalancerStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_pkg_apis_apps_v1alpha1_WorkloadRebalancerList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "WorkloadRebalancerList contains a list of WorkloadRebalancer", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Description: "Items holds a list of WorkloadRebalancer.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.WorkloadRebalancer"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.WorkloadRebalancer", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_pkg_apis_apps_v1alpha1_WorkloadRebalancerSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "WorkloadRebalancerSpec represents the specification of the desired behavior of Reschedule.\n\nNotes: this API represents a one-time execution process, once the object is created, the execution process begins, and it will not respond to any modification of the spec field.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "workloads": { + SchemaProps: spec.SchemaProps{ + Description: "Workloads used to specify the list of expected resource. Nil or empty list is not allowed.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.Workload"), + }, + }, + }, + }, + }, + }, + Required: []string{"workloads"}, + }, + }, + Dependencies: []string{ + "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.Workload"}, + } +} + +func schema_pkg_apis_apps_v1alpha1_WorkloadRebalancerStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "WorkloadRebalancerStatus contains information about the current status of a WorkloadRebalancer updated periodically by schedule trigger controller.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "observedWorkloads": { + SchemaProps: spec.SchemaProps{ + Description: "ObservedWorkloads contains information about the execution states and messages of target resources.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.ObservedWorkload"), + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1.ObservedWorkload"}, + } +} + func schema_pkg_apis_autoscaling_v1alpha1_CronFederatedHPA(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -6748,12 +7017,18 @@ func schema_pkg_apis_work_v1alpha2_ResourceBindingSpec(ref common.ReferenceCallb Format: "", }, }, + "rescheduleTriggeredAt": { + SchemaProps: spec.SchemaProps{ + Description: "RescheduleTriggeredAt is a timestamp representing when the referenced resource is triggered rescheduling. When this field is updated, it means a rescheduling is manually triggered by user, and the expected behavior of this action is to do a complete recalculation without referring to last scheduling results. It works with the status.lastScheduledTime field, and only when this timestamp is later than timestamp in status.lastScheduledTime will the rescheduling actually execute, otherwise, ignored.\n\nIt is represented in RFC3339 form (like '2006-01-02T15:04:05Z') and is in UTC.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, }, Required: []string{"resource"}, }, }, Dependencies: []string{ - "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1.FailoverBehavior", "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1.Placement", "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2.BindingSnapshot", "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2.GracefulEvictionTask", "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2.ObjectReference", "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2.ReplicaRequirements", "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2.TargetCluster"}, + "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1.FailoverBehavior", "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1.Placement", "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2.BindingSnapshot", "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2.GracefulEvictionTask", "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2.ObjectReference", "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2.ReplicaRequirements", "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2.TargetCluster", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, } } @@ -6778,6 +7053,12 @@ func schema_pkg_apis_work_v1alpha2_ResourceBindingStatus(ref common.ReferenceCal Format: "", }, }, + "lastScheduledTime": { + SchemaProps: spec.SchemaProps{ + Description: "LastScheduledTime representing the latest timestamp when scheduler successfully finished a scheduling. It is represented in RFC3339 form (like '2006-01-02T15:04:05Z') and is in UTC.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, "conditions": { SchemaProps: spec.SchemaProps{ Description: "Conditions contain the different condition statuses.", @@ -6810,7 +7091,7 @@ func schema_pkg_apis_work_v1alpha2_ResourceBindingStatus(ref common.ReferenceCal }, }, Dependencies: []string{ - "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2.AggregatedStatusItem", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"}, + "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2.AggregatedStatusItem", "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, } } diff --git a/pkg/util/apigroup.go b/pkg/util/apigroup.go index c7d4ac259c56..ef002e9cb27c 100644 --- a/pkg/util/apigroup.go +++ b/pkg/util/apigroup.go @@ -24,6 +24,7 @@ import ( eventsv1 "k8s.io/api/events/v1" "k8s.io/apimachinery/pkg/runtime/schema" + appsv1alpha1 "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" autoscalingv1alpha1 "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1" @@ -64,6 +65,7 @@ func NewSkippedResourceConfig() *SkippedResourceConfig { r.DisableGroup(networkingv1alpha1.GroupVersion.Group) r.DisableGroup(autoscalingv1alpha1.GroupVersion.Group) r.DisableGroup(remedyv1alpha1.GroupVersion.Group) + r.DisableGroup(appsv1alpha1.GroupVersion.Group) // disable event by default r.DisableGroup(eventsv1.GroupName) r.DisableGroupVersionKind(corev1EventGVK) diff --git a/pkg/util/gclient/gclient.go b/pkg/util/gclient/gclient.go index c089136a0c58..6e7a99a18764 100644 --- a/pkg/util/gclient/gclient.go +++ b/pkg/util/gclient/gclient.go @@ -25,6 +25,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" mcsv1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" + appsv1alpha1 "github.com/karmada-io/karmada/pkg/apis/apps/v1alpha1" autoscalingv1alpha1 "github.com/karmada-io/karmada/pkg/apis/autoscaling/v1alpha1" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1" @@ -51,7 +52,8 @@ func init() { utilruntime.Must(mcsv1alpha1.AddToScheme(aggregatedScheme)) // add mcs-api schemes utilruntime.Must(clusterapiv1beta1.AddToScheme(aggregatedScheme)) // add cluster-api v1beta1 schemes utilruntime.Must(autoscalingv1alpha1.AddToScheme(aggregatedScheme)) // add autoscaling v1alpha1 schemes - utilruntime.Must(remedyv1alpha1.AddToScheme(aggregatedScheme)) // add autoscaling v1alpha1 schemes + utilruntime.Must(remedyv1alpha1.AddToScheme(aggregatedScheme)) // add remedy v1alpha1 schemes + utilruntime.Must(appsv1alpha1.AddToScheme(aggregatedScheme)) // add apps v1alpha1 schemes } // NewSchema returns a singleton schema set which aggregated Kubernetes's schemes and extended schemes.