From 3d25d95aebd66f24a549200edcebc5ea423b317a Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Wed, 26 Feb 2025 14:25:45 -0800 Subject: [PATCH] Use random seed for xxhash Signed-off-by: Varun Gupta --- .gitignore | 1 + Makefile | 16 +- README.md | 2 +- api/orchestration/v1alpha1/kvcache_types.go | 2 +- benchmarks/client/client.py | 140 +++++----- cmd/controllers/main.go | 41 ++- config/default/kustomization.yaml | 9 +- config/default/manager_webhook_patch.yaml | 23 ++ config/default/webhookcainjection_patch.yaml | 29 ++ config/internalcert/kustomization.yaml | 2 + config/internalcert/secret.yaml | 5 + config/rbac/controller-manager/role.yaml | 19 ++ config/webhook/kustomization.yaml | 6 + config/webhook/kustomizeconfig.yaml | 22 ++ config/webhook/manifests.yaml | 52 ++++ config/webhook/service.yaml | 19 ++ .../installation/installation.rst | 4 +- docs/source/getting_started/quickstart.rst | 4 +- go.mod | 60 +++-- go.sum | 134 +++++----- hack/update-codegen.sh | 55 ++-- pkg/cert/cert.go | 66 +++++ .../autoscaling/v1alpha1/metricsource.go | 4 +- .../autoscaling/v1alpha1/podautoscaler.go | 10 +- .../autoscaling/v1alpha1/podautoscalerspec.go | 4 +- .../v1alpha1/podautoscalerstatus.go | 20 +- .../model/v1alpha1/modeladapter.go | 10 +- .../model/v1alpha1/modeladapterspec.go | 24 +- .../model/v1alpha1/modeladapterstatus.go | 19 +- .../orchestration/v1alpha1/rayclusterfleet.go | 10 +- .../v1alpha1/rayclusterfleetcondition.go | 4 +- .../v1alpha1/rayclusterfleetspec.go | 12 +- .../v1alpha1/rayclusterfleetstatus.go | 4 +- .../v1alpha1/rayclusterreplicaset.go | 10 +- .../v1alpha1/rayclusterreplicasetspec.go | 12 +- .../v1alpha1/rayclusterreplicasetstatus.go | 25 +- .../v1alpha1/rayclustertemplatespec.go | 10 +- pkg/client/applyconfiguration/utils.go | 7 + .../versioned/fake/clientset_generated.go | 39 ++- .../v1alpha1/fake/fake_podautoscaler.go | 46 ++-- .../autoscaling/v1alpha1/podautoscaler.go | 205 +-------------- .../model/v1alpha1/fake/fake_modeladapter.go | 46 ++-- .../typed/model/v1alpha1/modeladapter.go | 205 +-------------- .../v1alpha1/fake/fake_rayclusterfleet.go | 46 ++-- .../fake/fake_rayclusterreplicaset.go | 46 ++-- .../orchestration/v1alpha1/rayclusterfleet.go | 205 +-------------- .../v1alpha1/rayclusterreplicaset.go | 205 +-------------- .../informers/externalversions/factory.go | 1 + .../autoscaling/v1alpha1/podautoscaler.go | 39 +-- .../listers/model/v1alpha1/modeladapter.go | 39 +-- .../orchestration/v1alpha1/rayclusterfleet.go | 39 +-- .../v1alpha1/rayclusterreplicaset.go | 39 +-- .../podautoscaler/podautoscaler_controller.go | 6 +- .../algorithms/prefix_cache_and_load.go | 57 ++-- .../gateway/prefixcacheindexer/hash.go | 17 +- .../gateway/prefixcacheindexer/hash_test.go | 12 + .../gateway/prefixcacheindexer/tree.go | 247 ++++++++++++++---- pkg/utils/util_test.go | 6 +- pkg/webhook/modeladapter_webhook.go | 79 ++++++ test/integration/webhook/modeladapter_test.go | 80 ++++++ test/integration/webhook/suit_test.go | 157 +++++++++++ 61 files changed, 1386 insertions(+), 1371 deletions(-) create mode 100644 config/default/manager_webhook_patch.yaml create mode 100644 config/default/webhookcainjection_patch.yaml create mode 100644 config/internalcert/kustomization.yaml create mode 100644 config/internalcert/secret.yaml create mode 100644 config/webhook/kustomization.yaml create mode 100644 config/webhook/kustomizeconfig.yaml create mode 100644 config/webhook/manifests.yaml create mode 100644 config/webhook/service.yaml create mode 100644 pkg/cert/cert.go create mode 100644 pkg/webhook/modeladapter_webhook.go create mode 100644 test/integration/webhook/modeladapter_test.go create mode 100644 test/integration/webhook/suit_test.go diff --git a/.gitignore b/.gitignore index ec8dd8a2..09644309 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ go.work.sum .DS_Store __pycache__ +*.xml # Python virtual environment directory .venv diff --git a/Makefile b/Makefile index 2c887772..763d2787 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,15 @@ help: ## Display this help. ##@ Development +GINKGO_VERSION ?= $(shell go list -m -f '{{.Version}}' github.com/onsi/ginkgo/v2) +INTEGRATION_TARGET ?= ./test/integration/... + +GINKGO = $(shell pwd)/bin/ginkgo +.PHONY: ginkgo +ginkgo: ## Download ginkgo locally if necessary. + test -s $(LOCALBIN)/ginkgo || \ + GOBIN=$(LOCALBIN) go install github.com/onsi/ginkgo/v2/ginkgo@$(GINKGO_VERSION) + .PHONY: manifests manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. $(CONTROLLER_GEN) rbac:roleName=controller-manager-role crd:maxDescLen=0,generateEmbeddedObjectMeta=true webhook paths="./..." output:crd:artifacts:config=config/crd/bases @@ -81,6 +90,11 @@ vet: ## Run go vet against code. test: manifests generate fmt vet envtest ## Run tests. KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out +.PHONY: test-integration +test-integration: manifests fmt vet envtest ginkgo ## Run integration tests. + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" \ + $(GINKGO) --junit-report=junit.xml --output-dir=$(ARTIFACTS) -v $(INTEGRATION_TARGET) + # Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors. .PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up. test-e2e: @@ -272,7 +286,7 @@ GOLANGCI_LINT = $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION) ## Tool Versions KUSTOMIZE_VERSION ?= v5.3.0 -CONTROLLER_TOOLS_VERSION ?= v0.14.0 +CONTROLLER_TOOLS_VERSION ?= v0.16.1 ENVTEST_VERSION ?= release-0.17 GOLANGCI_LINT_VERSION ?= v1.57.2 diff --git a/README.md b/README.md index 7c0db636..db234cfc 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ Slack Channel: [#aibrix](https://vllm-dev.slack.com/archives/C08EQ883CSV) ## License -AIBrix is licensed under the [APACHE 2.0 License](https://github.com/vllm-project/aibrix/LICENSE). +AIBrix is licensed under the [Apache 2.0 License](LICENSE). ## Support diff --git a/api/orchestration/v1alpha1/kvcache_types.go b/api/orchestration/v1alpha1/kvcache_types.go index e6b47ba8..2492996b 100644 --- a/api/orchestration/v1alpha1/kvcache_types.go +++ b/api/orchestration/v1alpha1/kvcache_types.go @@ -69,7 +69,7 @@ type MetadataStorage struct { type CacheSpec struct { // Replicas is the number of kvcache pods to deploy - // +kubebuilder:validation:Required + // +kubebuilder:validation:Optional // +kubebuilder:default:=3 Replicas int `json:"replicas,omitempty"` diff --git a/benchmarks/client/client.py b/benchmarks/client/client.py index 36af0a65..7eb3a3d7 100755 --- a/benchmarks/client/client.py +++ b/benchmarks/client/client.py @@ -13,15 +13,18 @@ logging.basicConfig(level=logging.INFO) + async def send_request_streaming(client: openai.AsyncOpenAI, - model: str, - endpoint: str, - prompt: str, - output_file: str, - ): + model: str, + endpoint: str, + prompt: str, + output_file: str, + request_id: int): start_time = asyncio.get_event_loop().time() first_response_time = None + try: + logging.info(f"Request {request_id}: Starting streaming request to {endpoint}") stream = await client.chat.completions.create( model=model, messages=prompt, @@ -30,74 +33,89 @@ async def send_request_streaming(client: openai.AsyncOpenAI, stream=True, stream_options={"include_usage": True}, ) + text_chunks = [] prompt_tokens = 0 output_tokens = 0 total_tokens = 0 - async for chunk in stream: - if chunk.choices: - if chunk.choices[0].delta.content is not None: - if not first_response_time: - first_response_time = asyncio.get_event_loop().time() - output_text = chunk.choices[0].delta.content - text_chunks.append(output_text) - prompt_tokens = chunk.usage.prompt_tokens - output_tokens = chunk.usage.completion_tokens - total_tokens = chunk.usage.total_tokens - response = "".join(text_chunks) - logging.info(result) - if response.status_code == 200: - response_time = asyncio.get_event_loop().time() - latency = response_time - start_time - throughput = output_tokens / latency - ttft = first_response_time - start_time - tpot = (response_time - first_response_time) / output_tokens - result = { - "status_code": response.status_code, - "input": prompt, - "output": response, - "prompt_tokens": prompt_tokens, - "output_tokens": output_tokens, - "total_tokens": total_tokens, - "latency": latency, - "throughput": throughput, - "start_time": start_time, - "current_time": asyncio.get_event_loop().time(), - "ttft": ttft, - "tpot": tpot, - } - else: - logging.error(f"Request failed status-code: {response.status_code}, raw response: {response.text}") - result = { - "status_code": response.status_code, - "input": prompt, - "output": response, - "prompt_tokens": prompt_tokens, - "output_tokens": None, - "total_tokens": total_tokens, - "latency": latency, - "throughput": None, - "start_time": start_time, - "current_time": asyncio.get_event_loop().time(), - "ttft": None, - "tpot": None, - } + try: + async for chunk in stream: + if chunk.choices: + if chunk.choices[0].delta.content is not None: + if not first_response_time: + first_response_time = asyncio.get_event_loop().time() + output_text = chunk.choices[0].delta.content + text_chunks.append(output_text) + if hasattr(chunk, 'usage') and chunk.usage is not None: + # For OpenAI, we expect to get complete usage stats, not partial ones to accumulate + # So we can safely overwrite previous values if they exist + if chunk.usage.prompt_tokens is not None: + prompt_tokens = chunk.usage.prompt_tokens + if chunk.usage.completion_tokens is not None: + output_tokens = chunk.usage.completion_tokens + if chunk.usage.total_tokens is not None: + total_tokens = chunk.usage.total_tokens + except Exception as stream_error: + # Handle errors during streaming + logging.error(f"Request {request_id}: Stream interrupted: {type(stream_error).__name__}: {str(stream_error)}") + + response_text = "".join(text_chunks) + response_time = asyncio.get_event_loop().time() + latency = response_time - start_time + throughput = output_tokens / latency if output_tokens > 0 else 0 + ttft = first_response_time - start_time if first_response_time else None + tpot = (response_time - first_response_time) / output_tokens if first_response_time and output_tokens > 0 else None + + result = { + "request_id": request_id, + "status": "success", + "input": prompt, + "output": response_text, + "prompt_tokens": prompt_tokens, + "output_tokens": output_tokens, + "total_tokens": total_tokens, + "latency": latency, + "throughput": throughput, + "start_time": start_time, + "end_time": response_time, + "ttft": ttft, + "tpot": tpot, + } + # Write result to JSONL file + logging.info(f"Request {request_id}: Completed successfully. Tokens: {total_tokens}, Latency: {latency:.2f}s") output_file.write(json.dumps(result) + "\n") output_file.flush() # Ensure data is written immediately to the file return result + except Exception as e: - logging.error(f"Error sending request to at {endpoint}: {str(e)}") - traceback.print_exc() - return None + error_time = asyncio.get_event_loop().time() + # Determine error type based on exception class + error_type = type(e).__name__ + + error_result = { + "request_id": request_id, + "status": "error", + "error_type": error_type, + "error_message": str(e), + "error_traceback": traceback.format_exc(), + "input": prompt, + "latency": error_time - start_time, + "start_time": start_time, + "end_time": error_time + } + logging.error(f"Request {request_id}: Error ({error_type}): {str(e)}") + output_file.write(json.dumps(error_result) + "\n") + output_file.flush() + return error_result async def benchmark_streaming(client: openai.AsyncOpenAI, endpoint: str, model: str, load_struct: List, output_file: io.TextIOWrapper): - + request_id = 0 batch_tasks = [] base_time = time.time() num_requests = 0 @@ -116,8 +134,10 @@ async def benchmark_streaming(client: openai.AsyncOpenAI, model = model, endpoint = endpoint, prompt = formatted_prompt, - output_file = output_file) + output_file = output_file, + request_id = request_id) ) + request_id += 1 batch_tasks.append(task) num_requests += len(requests) await asyncio.gather(*batch_tasks) @@ -199,7 +219,9 @@ def main(args): base_url=args.endpoint + "/v1", ) if args.routing_strategy is not None: - client.default_headers["routing-strategy"] = args.routing_strategy + client = client.with_options( + default_headers={"routing-strategy": args.routing_strategy} + ) if not args.streaming: logging.info("Using batch client") start_time = time.time() diff --git a/cmd/controllers/main.go b/cmd/controllers/main.go index cf8bd45d..349a7c1c 100644 --- a/cmd/controllers/main.go +++ b/cmd/controllers/main.go @@ -1,5 +1,5 @@ /* -Copyright 2024. +Copyright 2024 The Aibrix Team. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -32,6 +32,7 @@ import ( "github.com/vllm-project/aibrix/pkg/features" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/vllm-project/aibrix/pkg/cert" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" _ "k8s.io/client-go/plugin/pkg/client/auth" @@ -48,6 +49,7 @@ import ( "github.com/vllm-project/aibrix/pkg/cache" "github.com/vllm-project/aibrix/pkg/config" "github.com/vllm-project/aibrix/pkg/controller" + apiwebhook "github.com/vllm-project/aibrix/pkg/webhook" //+kubebuilder:scaffold:imports ) @@ -233,16 +235,21 @@ func main() { cache.NewCache(config, stopCh, nil) } - // Initialize controllers - controller.Initialize() + certsReady := make(chan struct{}) - // Kind controller registration is encapsulated inside the pkg/controller/controller.go - // So here we can use more clean registration flow and there's no need to change logics in future. - if err = controller.SetupWithManager(mgr, runtimeConfig); err != nil { - setupLog.Error(err, "unable to setup controller") + if err = cert.CertsManager(mgr, leaderElectionNamespace, certsReady); err != nil { + setupLog.Error(err, "unable to setup cert rotation") os.Exit(1) } + // Initialize controllers + controller.Initialize() + + // Cert won't be ready until manager starts, so start a goroutine here which + // will block until the cert is ready before setting up the controllers. + // Controllers who register after manager starts will start directly. + go setupControllers(mgr, runtimeConfig, certsReady) + //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { @@ -260,3 +267,23 @@ func main() { os.Exit(1) } } + +func setupControllers(mgr ctrl.Manager, runtimeConfig config.RuntimeConfig, certsReady chan struct{}) { + // The controllers won't work until the webhooks are operating, + // and the webhook won't work until the certs are all in places. + setupLog.Info("waiting for the cert generation to complete") + <-certsReady + setupLog.Info("certs ready") + + // Kind controller registration is encapsulated inside the pkg/controller/controller.go + // So here we can use more clean registration flow and there's no need to change logics in future. + if err := controller.SetupWithManager(mgr, runtimeConfig); err != nil { + setupLog.Error(err, "unable to setup controller") + os.Exit(1) + } + + if err := apiwebhook.SetupBackendRuntimeWebhook(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "Model") + os.Exit(1) + } +} diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index ee09a30a..876549b1 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -28,7 +28,11 @@ resources: - ../dependency/kuberay-operator # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml -#- ../webhook +- ../webhook + +# [INTERNALCERT] +- ../internalcert + # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. #- ../certmanager # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. @@ -54,6 +58,9 @@ patches: - kind: ServiceAccount name: aibrix-kuberay-operator-leader-election namespace: aibrix-system +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in +# crd/kustomization.yaml +- path: manager_webhook_patch.yaml images: - name: controller diff --git a/config/default/manager_webhook_patch.yaml b/config/default/manager_webhook_patch.yaml new file mode 100644 index 00000000..738de350 --- /dev/null +++ b/config/default/manager_webhook_patch.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: webhook-server-cert diff --git a/config/default/webhookcainjection_patch.yaml b/config/default/webhookcainjection_patch.yaml new file mode 100644 index 00000000..14c90fc6 --- /dev/null +++ b/config/default/webhookcainjection_patch.yaml @@ -0,0 +1,29 @@ +# This patch add annotation to admission webhook config and +# CERTIFICATE_NAMESPACE and CERTIFICATE_NAME will be substituted by kustomize +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + labels: + app.kubernetes.io/name: mutatingwebhookconfiguration + app.kubernetes.io/instance: mutating-webhook-configuration + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: aibrix + app.kubernetes.io/part-of: aibrix + app.kubernetes.io/managed-by: kustomize + name: mutating-webhook-configuration + annotations: + cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + labels: + app.kubernetes.io/name: validatingwebhookconfiguration + app.kubernetes.io/instance: validating-webhook-configuration + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: aibrix + app.kubernetes.io/part-of: aibrix + app.kubernetes.io/managed-by: kustomize + name: validating-webhook-configuration + annotations: + cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME diff --git a/config/internalcert/kustomization.yaml b/config/internalcert/kustomization.yaml new file mode 100644 index 00000000..26167d8e --- /dev/null +++ b/config/internalcert/kustomization.yaml @@ -0,0 +1,2 @@ +resources: +- secret.yaml diff --git a/config/internalcert/secret.yaml b/config/internalcert/secret.yaml new file mode 100644 index 00000000..af960e6c --- /dev/null +++ b/config/internalcert/secret.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: Secret +metadata: + name: webhook-server-cert + namespace: system diff --git a/config/rbac/controller-manager/role.yaml b/config/rbac/controller-manager/role.yaml index 8f976b0f..dac8c0b0 100644 --- a/config/rbac/controller-manager/role.yaml +++ b/config/rbac/controller-manager/role.yaml @@ -289,3 +289,22 @@ rules: - get - patch - update +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - update + - watch +- apiGroups: + - admissionregistration.k8s.io + resources: + - mutatingwebhookconfigurations + - validatingwebhookconfigurations + verbs: + - get + - list + - update + - watch diff --git a/config/webhook/kustomization.yaml b/config/webhook/kustomization.yaml new file mode 100644 index 00000000..9cf26134 --- /dev/null +++ b/config/webhook/kustomization.yaml @@ -0,0 +1,6 @@ +resources: +- manifests.yaml +- service.yaml + +configurations: +- kustomizeconfig.yaml diff --git a/config/webhook/kustomizeconfig.yaml b/config/webhook/kustomizeconfig.yaml new file mode 100644 index 00000000..206316e5 --- /dev/null +++ b/config/webhook/kustomizeconfig.yaml @@ -0,0 +1,22 @@ +# the following config is for teaching kustomize where to look at when substituting nameReference. +# It requires kustomize v2.1.0 or newer to work properly. +nameReference: +- kind: Service + version: v1 + fieldSpecs: + - kind: MutatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/name + - kind: ValidatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/name + +namespace: +- kind: MutatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/namespace + create: true +- kind: ValidatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/namespace + create: true diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml new file mode 100644 index 00000000..8d09d3ee --- /dev/null +++ b/config/webhook/manifests.yaml @@ -0,0 +1,52 @@ +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: mutating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-model-aibrix-ai-v1alpha1-modeladapter + failurePolicy: Fail + name: mmodeladapter.kb.io + rules: + - apiGroups: + - model.aibrix.ai + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - modeladapters + sideEffects: None +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-model-aibrix-ai-v1alpha1-modeladapter + failurePolicy: Fail + name: vmodeladapter.kb.io + rules: + - apiGroups: + - model.aibrix.ai + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - modeladapters + sideEffects: None diff --git a/config/webhook/service.yaml b/config/webhook/service.yaml new file mode 100644 index 00000000..3ea79513 --- /dev/null +++ b/config/webhook/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: service + app.kubernetes.io/instance: webhook-service + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: aibrix + app.kubernetes.io/part-of: aibrix + app.kubernetes.io/managed-by: kustomize + name: webhook-service + namespace: system +spec: + ports: + - port: 443 + protocol: TCP + targetPort: 9443 + selector: + control-plane: controller-manager diff --git a/docs/source/getting_started/installation/installation.rst b/docs/source/getting_started/installation/installation.rst index 1179b849..8c93c93b 100644 --- a/docs/source/getting_started/installation/installation.rst +++ b/docs/source/getting_started/installation/installation.rst @@ -23,10 +23,10 @@ Stable Version .. code:: bash # Install component dependencies - kubectl apply -f https://github.com/vllm-project/aibrix/releases/download/v0.2.0/aibrix-dependency-v0.2.0.yaml + kubectl create -f https://github.com/vllm-project/aibrix/releases/download/v0.2.0/aibrix-dependency-v0.2.0.yaml # Install aibrix components - kubectl apply -f https://github.com/vllm-project/aibrix/releases/download/v0.2.0/aibrix-core-v0.2.0.yaml + kubectl create -f https://github.com/vllm-project/aibrix/releases/download/v0.2.0/aibrix-core-v0.2.0.yaml Nightly Version diff --git a/docs/source/getting_started/quickstart.rst b/docs/source/getting_started/quickstart.rst index f693374c..2122310b 100644 --- a/docs/source/getting_started/quickstart.rst +++ b/docs/source/getting_started/quickstart.rst @@ -14,8 +14,8 @@ Get your kubernetes cluster ready, run following commands to install aibrix comp .. code-block:: bash - kubectl apply -f https://github.com/vllm-project/aibrix/releases/download/v0.2.0/aibrix-dependency-v0.2.0.yaml - kubectl apply -f https://github.com/vllm-project/aibrix/releases/download/v0.2.0/aibrix-core-v0.2.0.yaml + kubectl create -f https://github.com/vllm-project/aibrix/releases/download/v0.2.0/aibrix-dependency-v0.2.0.yaml + kubectl create -f https://github.com/vllm-project/aibrix/releases/download/v0.2.0/aibrix-core-v0.2.0.yaml Wait for few minutes and run `kubectl get pods -n aibrix-system` to check pod status util they are ready. diff --git a/go.mod b/go.mod index 5cd92cb2..cfeb80d9 100644 --- a/go.mod +++ b/go.mod @@ -5,49 +5,49 @@ go 1.22.5 toolchain go1.22.6 require ( - github.com/cespare/xxhash v1.1.0 + github.com/cespare/xxhash/v2 v2.3.0 github.com/envoyproxy/go-control-plane v0.12.0 github.com/go-playground/validator/v10 v10.22.1 github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.1 github.com/onsi/ginkgo v1.16.5 - github.com/onsi/ginkgo/v2 v2.17.2 - github.com/onsi/gomega v1.33.1 + github.com/onsi/ginkgo/v2 v2.20.1 + github.com/onsi/gomega v1.35.1 + github.com/open-policy-agent/cert-controller v0.12.0 github.com/openai/openai-go v0.1.0-alpha.37 github.com/pkoukk/tiktoken-go v0.1.7 github.com/pkoukk/tiktoken-go-loader v0.0.1 - github.com/prometheus/client_golang v1.19.1 + github.com/prometheus/client_golang v1.20.2 github.com/prometheus/client_model v0.6.1 github.com/prometheus/common v0.55.0 github.com/ray-project/kuberay/ray-operator v1.2.1 github.com/redis/go-redis/v9 v9.6.1 github.com/stretchr/testify v1.9.0 google.golang.org/grpc v1.65.0 - k8s.io/api v0.30.2 - k8s.io/apimachinery v0.30.2 - k8s.io/client-go v0.29.6 - k8s.io/code-generator v0.29.6 + k8s.io/api v0.31.2 + k8s.io/apimachinery v0.31.2 + k8s.io/client-go v0.31.2 + k8s.io/code-generator v0.31.2 k8s.io/klog/v2 v2.130.1 k8s.io/kube-openapi v0.0.0-20240620174524-b456828f718b k8s.io/metrics v0.29.6 - k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 - sigs.k8s.io/controller-runtime v0.17.5 + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 + sigs.k8s.io/controller-runtime v0.19.1 sigs.k8s.io/gateway-api v1.0.0 sigs.k8s.io/structured-merge-diff/v4 v4.4.1 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dlclark/regexp2 v1.10.0 // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect - github.com/evanphx/json-patch v5.9.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect @@ -63,11 +63,12 @@ require ( github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect + github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect github.com/imdario/mergo v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -76,36 +77,37 @@ require ( github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect + github.com/x448/float16 v0.8.4 // indirect + go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect - golang.org/x/mod v0.18.0 // indirect - golang.org/x/net v0.27.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.22.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/term v0.25.0 // indirect + golang.org/x/text v0.19.0 // indirect + golang.org/x/time v0.6.0 // indirect + golang.org/x/tools v0.24.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/protobuf v1.35.1 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.29.6 // indirect - k8s.io/component-base v0.29.6 // indirect - k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 // indirect + k8s.io/apiextensions-apiserver v0.31.2 // indirect k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/go.sum b/go.sum index 108cd729..71d0f112 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,11 @@ dario.cat/mergo v0.3.16 h1:wrt7QIfeqlABnUvmf9WpFwB0mGBwtySAJKTgCpnsbOE= dario.cat/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= @@ -36,9 +32,10 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= @@ -82,11 +79,10 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= @@ -100,13 +96,14 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -127,12 +124,16 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= -github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo= +github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= +github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/open-policy-agent/cert-controller v0.12.0 h1:RKXlBafMcCh+++I1geJetXo77tAjyb4542DQc/+aZIw= +github.com/open-policy-agent/cert-controller v0.12.0/go.mod h1:N5bCFXdAXMYx0PdS6ZQ9lrDQQMz+F6deoChym6VleXw= +github.com/open-policy-agent/frameworks/constraint v0.0.0-20241101234656-e78c8abd754a h1:gQtOJ50XFyL2Xh3lDD9zP4KQ2PY4mZKQ9hDcWc81Sp8= +github.com/open-policy-agent/frameworks/constraint v0.0.0-20241101234656-e78c8abd754a/go.mod h1:tI7nc6H6os2UYZRvSm9Y7bq4oMoXqhwA0WfnqKpoAgc= github.com/openai/openai-go v0.1.0-alpha.37 h1:dstNWRmODNmcvVrNhJ1tzmD8J9hy+aaycwKAqLZVx2Q= github.com/openai/openai-go v0.1.0-alpha.37/go.mod h1:3SdE6BffOX9HPEQv8IL/fi3LYZ5TUpRYaqGQZbyk11A= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -141,10 +142,11 @@ github.com/pkoukk/tiktoken-go v0.1.7 h1:qOBHXX4PHtvIvmOtyg1EeKlwFRiMKAcoMp4Q+bLQ github.com/pkoukk/tiktoken-go v0.1.7/go.mod h1:9NiV+i9mJKGj1rYOT+njbv+ZwA/zJxYdewGl6qVatpg= github.com/pkoukk/tiktoken-go-loader v0.0.1 h1:aOB2gRFzZTCCPi3YsOQXJO771P/5876JAsdebMyazig= github.com/pkoukk/tiktoken-go-loader v0.0.1/go.mod h1:4mIkYyZooFlnenDlormIo6cd5wrlUKNr97wp9nGgEKo= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg= +github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= @@ -155,8 +157,8 @@ github.com/ray-project/kuberay/ray-operator v1.2.1 h1:H7ofodGclghsU2TxbDHs+gvqvs github.com/ray-project/kuberay/ray-operator v1.2.1/go.mod h1:osTiIyaDoWi5IN1f0tOOtZ4TzVf+5kJXZor8VFvcEiI= github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -176,8 +178,12 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -187,30 +193,30 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= -golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= -golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -220,32 +226,31 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -254,12 +259,13 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -273,39 +279,35 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI= -k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI= -k8s.io/apiextensions-apiserver v0.29.6 h1:tUu1N6Zt9GT8KVcPF5aGDqfISz1mveM4yFh7eL5bxmE= -k8s.io/apiextensions-apiserver v0.29.6/go.mod h1:iw1EbwZat08I219qrQKoFMHGo7J9KxPqMpVKxCbNbCs= -k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg= -k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= -k8s.io/client-go v0.29.6 h1:5E2ebuB/p0F0THuQatyvhDvPL2SIeqwTPrtnrwKob/8= -k8s.io/client-go v0.29.6/go.mod h1:jHZcrQqDplyv20v7eu+iFM4gTpglZSZoMVcKrh8sRGg= -k8s.io/code-generator v0.29.6 h1:Z8T9VMR0mr7V5GG66c6GVAZrIiEy2uFoQwbeVeWLqPA= -k8s.io/code-generator v0.29.6/go.mod h1:7TYnI0dYItL2cKuhhgPSuF3WED9uMdELgbVXFfn/joE= -k8s.io/component-base v0.29.6 h1:XkVJI67FvBgNb/3kKqvaGKokxUrIR0RrksCPNI+JYCs= -k8s.io/component-base v0.29.6/go.mod h1:kIahZm8aw9lV8Vw17LF89REmeBrv5+QEl3v7HsrmITY= -k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks= -k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= +k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= +k8s.io/apiextensions-apiserver v0.31.2 h1:W8EwUb8+WXBLu56ser5IudT2cOho0gAKeTOnywBLxd0= +k8s.io/apiextensions-apiserver v0.31.2/go.mod h1:i+Geh+nGCJEGiCGR3MlBDkS7koHIIKWVfWeRFiOsUcM= +k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= +k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= +k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs= +k8s.io/code-generator v0.31.2 h1:xLWxG0HEpMSHfcM//3u3Ro2Hmc6AyyLINQS//Z2GEOI= +k8s.io/code-generator v0.31.2/go.mod h1:eEQHXgBU/m7LDaToDoiz3t97dUUVyOblQdwOr8rivqc= k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo= k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-aggregator v0.31.2 h1:Uw1zUP2D/4wiSjKWVVzSOcCGLuW/+IdRwjjC0FJooYU= +k8s.io/kube-aggregator v0.31.2/go.mod h1:41/VIXH+/Qcg9ERNAY6bRF/WQR6xL1wFgYagdHac1X4= k8s.io/kube-openapi v0.0.0-20240620174524-b456828f718b h1:Q9xmGWBvOGd8UJyccgpYlLosk/JlfP3xQLNkQlHJeXw= k8s.io/kube-openapi v0.0.0-20240620174524-b456828f718b/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= k8s.io/metrics v0.29.6 h1:kjMGPYxtCi4OO0fUar76y0CiUoeGYDNmUV0LXJIis4Q= k8s.io/metrics v0.29.6/go.mod h1:vqGzOaYGuNSSAI7GM1+v6L5z8aAUSzui1W0eQB3wVJY= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.17.5 h1:1FI9Lm7NiOOmBsgTV36/s2XrEFXnO2C4sbg/Zme72Rw= -sigs.k8s.io/controller-runtime v0.17.5/go.mod h1:N0jpP5Lo7lMTF9aL56Z/B2oWBJjey6StQM0jRbKQXtY= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.19.1 h1:Son+Q40+Be3QWb+niBXAg2vFiYWolDjjRfO8hn/cxOk= +sigs.k8s.io/controller-runtime v0.19.1/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/gateway-api v1.0.0 h1:iPTStSv41+d9p0xFydll6d7f7MOBGuqXM6p2/zVYMAs= sigs.k8s.io/gateway-api v1.0.0/go.mod h1:4cUgr0Lnp5FZ0Cdq8FdRwCvpiWws7LVhLHGIudLlf4c= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index 8a3ec483..eda313f6 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -7,48 +7,31 @@ set -o errexit set -o nounset set -o pipefail -SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. -ROOT_PKG=github.com/vllm-project/aibrix +cd "$(dirname "${0}")/.." -# Grab code-generator version from go.sum CODEGEN_VERSION=$(grep 'k8s.io/code-generator' go.sum | awk '{print $2}' | sed 's/\/go.mod//g' | head -1) CODEGEN_PKG=$(echo `go env GOPATH`"/pkg/mod/k8s.io/code-generator@${CODEGEN_VERSION}") - if [[ ! -d ${CODEGEN_PKG} ]]; then echo "${CODEGEN_PKG} is missing. Running 'go mod download'." go mod download fi - echo ">> Using ${CODEGEN_PKG}" -# code-generator does work with go.mod but makes assumptions about -# the project living in `$GOPATH/src`. To work around this and support -# any location; create a temporary directory, use this as an output -# base, and copy everything back once generated. -TEMP_DIR=$(mktemp -d) -cleanup() { - echo ">> Removing ${TEMP_DIR}" -# rm -rf ${TEMP_DIR} -} -trap "cleanup" EXIT SIGINT - -echo ">> Temporary output directory ${TEMP_DIR}" - -# Ensure we can execute. -chmod +x ${CODEGEN_PKG}/generate-groups.sh -chmod +x ${CODEGEN_PKG}/generate-internal-groups.sh - -# generate the code with: -# --output-base because this script should also be able to run inside the vendor dir of -# k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir -# instead of the $GOPATH directly. For normal projects this can be dropped. -# -cd ${SCRIPT_ROOT} -${CODEGEN_PKG}/generate-groups.sh applyconfiguration,client,informer,lister \ - github.com/vllm-project/aibrix/pkg/client github.com/vllm-project/aibrix/api \ - "model:v1alpha1 autoscaling:v1alpha1 orchestration:v1alpha1" \ - --output-base "${TEMP_DIR}" \ - --go-header-file hack/boilerplate.go.txt - -# Copy everything back. -cp -a "${TEMP_DIR}/${ROOT_PKG}/." "${SCRIPT_ROOT}/" +REPO_ROOT="$(git rev-parse --show-toplevel)" + +source "${CODEGEN_PKG}/kube_codegen.sh" + +# TODO: remove the workaround when the issue is solved in the code-generator +# (https://github.com/kubernetes/code-generator/issues/165). +mkdir -p github.com && ln -s ../.. github.com/vllm-project +trap "rm -r github.com" EXIT + +kube::codegen::gen_helpers github.com/vllm-project/aibrix/api \ + --boilerplate "${REPO_ROOT}/hack/boilerplate.go.txt" + +kube::codegen::gen_client github.com/vllm-project/aibrix/api \ + --with-watch \ + --with-applyconfig \ + --output-dir "$REPO_ROOT"/pkg/client \ + --output-pkg github.com/vllm-project/aibrix/pkg/client \ + --boilerplate "${REPO_ROOT}/hack/boilerplate.go.txt" diff --git a/pkg/cert/cert.go b/pkg/cert/cert.go new file mode 100644 index 00000000..5e774243 --- /dev/null +++ b/pkg/cert/cert.go @@ -0,0 +1,66 @@ +/* +Copyright 2024 The Aibrix Team. + +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 cert + +import ( + "fmt" + + cert "github.com/open-policy-agent/cert-controller/pkg/rotator" + "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" +) + +const ( + serviceName = "aibrix-webhook-service" + secretName = "aibrix-webhook-server-cert" + certDir = "/tmp/k8s-webhook-server/serving-certs" + validateWebhookConfName = "aibrix-validating-webhook-configuration" + mutatingWebhookConfName = "aibrix-mutating-webhook-configuration" + caName = "aibrix-ca" + caOrg = "aibrix" +) + +//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;update +//+kubebuilder:rbac:groups="admissionregistration.k8s.io",resources=mutatingwebhookconfigurations,verbs=get;list;watch;update +//+kubebuilder:rbac:groups="admissionregistration.k8s.io",resources=validatingwebhookconfigurations,verbs=get;list;watch;update + +// CertsManager creates certs for webhooks. +func CertsManager(mgr ctrl.Manager, namespace string, setupFinish chan struct{}) error { + // dnsName is the format of ..svc + dnsName := fmt.Sprintf("%s.%s.svc", serviceName, namespace) + return cert.AddRotator(mgr, &cert.CertRotator{ + SecretKey: types.NamespacedName{ + Namespace: namespace, + Name: secretName, + }, + CertDir: certDir, + CAName: caName, + CAOrganization: caOrg, + DNSName: dnsName, + IsReady: setupFinish, + Webhooks: []cert.WebhookInfo{ + { + Type: cert.Validating, + Name: validateWebhookConfName, + }, + { + Type: cert.Mutating, + Name: mutatingWebhookConfName, + }, + }, + }) +} diff --git a/pkg/client/applyconfiguration/autoscaling/v1alpha1/metricsource.go b/pkg/client/applyconfiguration/autoscaling/v1alpha1/metricsource.go index 4051e6a8..c521a2df 100644 --- a/pkg/client/applyconfiguration/autoscaling/v1alpha1/metricsource.go +++ b/pkg/client/applyconfiguration/autoscaling/v1alpha1/metricsource.go @@ -21,7 +21,7 @@ import ( v1alpha1 "github.com/vllm-project/aibrix/api/autoscaling/v1alpha1" ) -// MetricSourceApplyConfiguration represents an declarative configuration of the MetricSource type for use +// MetricSourceApplyConfiguration represents a declarative configuration of the MetricSource type for use // with apply. type MetricSourceApplyConfiguration struct { MetricSourceType *v1alpha1.MetricSourceType `json:"metricSourceType,omitempty"` @@ -33,7 +33,7 @@ type MetricSourceApplyConfiguration struct { TargetValue *string `json:"targetValue,omitempty"` } -// MetricSourceApplyConfiguration constructs an declarative configuration of the MetricSource type for use with +// MetricSourceApplyConfiguration constructs a declarative configuration of the MetricSource type for use with // apply. func MetricSource() *MetricSourceApplyConfiguration { return &MetricSourceApplyConfiguration{} diff --git a/pkg/client/applyconfiguration/autoscaling/v1alpha1/podautoscaler.go b/pkg/client/applyconfiguration/autoscaling/v1alpha1/podautoscaler.go index af590461..aa770b48 100644 --- a/pkg/client/applyconfiguration/autoscaling/v1alpha1/podautoscaler.go +++ b/pkg/client/applyconfiguration/autoscaling/v1alpha1/podautoscaler.go @@ -23,7 +23,7 @@ import ( v1 "k8s.io/client-go/applyconfigurations/meta/v1" ) -// PodAutoscalerApplyConfiguration represents an declarative configuration of the PodAutoscaler type for use +// PodAutoscalerApplyConfiguration represents a declarative configuration of the PodAutoscaler type for use // with apply. type PodAutoscalerApplyConfiguration struct { v1.TypeMetaApplyConfiguration `json:",inline"` @@ -32,7 +32,7 @@ type PodAutoscalerApplyConfiguration struct { Status *PodAutoscalerStatusApplyConfiguration `json:"status,omitempty"` } -// PodAutoscaler constructs an declarative configuration of the PodAutoscaler type for use with +// PodAutoscaler constructs a declarative configuration of the PodAutoscaler type for use with // apply. func PodAutoscaler(name, namespace string) *PodAutoscalerApplyConfiguration { b := &PodAutoscalerApplyConfiguration{} @@ -216,3 +216,9 @@ func (b *PodAutoscalerApplyConfiguration) WithStatus(value *PodAutoscalerStatusA b.Status = value return b } + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *PodAutoscalerApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.Name +} diff --git a/pkg/client/applyconfiguration/autoscaling/v1alpha1/podautoscalerspec.go b/pkg/client/applyconfiguration/autoscaling/v1alpha1/podautoscalerspec.go index f3ce72d0..1e020cb9 100644 --- a/pkg/client/applyconfiguration/autoscaling/v1alpha1/podautoscalerspec.go +++ b/pkg/client/applyconfiguration/autoscaling/v1alpha1/podautoscalerspec.go @@ -22,7 +22,7 @@ import ( v1 "k8s.io/api/core/v1" ) -// PodAutoscalerSpecApplyConfiguration represents an declarative configuration of the PodAutoscalerSpec type for use +// PodAutoscalerSpecApplyConfiguration represents a declarative configuration of the PodAutoscalerSpec type for use // with apply. type PodAutoscalerSpecApplyConfiguration struct { ScaleTargetRef *v1.ObjectReference `json:"scaleTargetRef,omitempty"` @@ -32,7 +32,7 @@ type PodAutoscalerSpecApplyConfiguration struct { ScalingStrategy *autoscalingv1alpha1.ScalingStrategyType `json:"scalingStrategy,omitempty"` } -// PodAutoscalerSpecApplyConfiguration constructs an declarative configuration of the PodAutoscalerSpec type for use with +// PodAutoscalerSpecApplyConfiguration constructs a declarative configuration of the PodAutoscalerSpec type for use with // apply. func PodAutoscalerSpec() *PodAutoscalerSpecApplyConfiguration { return &PodAutoscalerSpecApplyConfiguration{} diff --git a/pkg/client/applyconfiguration/autoscaling/v1alpha1/podautoscalerstatus.go b/pkg/client/applyconfiguration/autoscaling/v1alpha1/podautoscalerstatus.go index 228fb6c9..9b664972 100644 --- a/pkg/client/applyconfiguration/autoscaling/v1alpha1/podautoscalerstatus.go +++ b/pkg/client/applyconfiguration/autoscaling/v1alpha1/podautoscalerstatus.go @@ -19,18 +19,19 @@ package v1alpha1 import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/client-go/applyconfigurations/meta/v1" ) -// PodAutoscalerStatusApplyConfiguration represents an declarative configuration of the PodAutoscalerStatus type for use +// PodAutoscalerStatusApplyConfiguration represents a declarative configuration of the PodAutoscalerStatus type for use // with apply. type PodAutoscalerStatusApplyConfiguration struct { - LastScaleTime *v1.Time `json:"lastScaleTime,omitempty"` - DesiredScale *int32 `json:"desiredScale,omitempty"` - ActualScale *int32 `json:"actualScale,omitempty"` - Conditions []v1.Condition `json:"conditions,omitempty"` + LastScaleTime *v1.Time `json:"lastScaleTime,omitempty"` + DesiredScale *int32 `json:"desiredScale,omitempty"` + ActualScale *int32 `json:"actualScale,omitempty"` + Conditions []metav1.ConditionApplyConfiguration `json:"conditions,omitempty"` } -// PodAutoscalerStatusApplyConfiguration constructs an declarative configuration of the PodAutoscalerStatus type for use with +// PodAutoscalerStatusApplyConfiguration constructs a declarative configuration of the PodAutoscalerStatus type for use with // apply. func PodAutoscalerStatus() *PodAutoscalerStatusApplyConfiguration { return &PodAutoscalerStatusApplyConfiguration{} @@ -63,9 +64,12 @@ func (b *PodAutoscalerStatusApplyConfiguration) WithActualScale(value int32) *Po // WithConditions adds the given value to the Conditions field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Conditions field. -func (b *PodAutoscalerStatusApplyConfiguration) WithConditions(values ...v1.Condition) *PodAutoscalerStatusApplyConfiguration { +func (b *PodAutoscalerStatusApplyConfiguration) WithConditions(values ...*metav1.ConditionApplyConfiguration) *PodAutoscalerStatusApplyConfiguration { for i := range values { - b.Conditions = append(b.Conditions, values[i]) + if values[i] == nil { + panic("nil value passed to WithConditions") + } + b.Conditions = append(b.Conditions, *values[i]) } return b } diff --git a/pkg/client/applyconfiguration/model/v1alpha1/modeladapter.go b/pkg/client/applyconfiguration/model/v1alpha1/modeladapter.go index 0b9c61cd..a1f33e6a 100644 --- a/pkg/client/applyconfiguration/model/v1alpha1/modeladapter.go +++ b/pkg/client/applyconfiguration/model/v1alpha1/modeladapter.go @@ -23,7 +23,7 @@ import ( v1 "k8s.io/client-go/applyconfigurations/meta/v1" ) -// ModelAdapterApplyConfiguration represents an declarative configuration of the ModelAdapter type for use +// ModelAdapterApplyConfiguration represents a declarative configuration of the ModelAdapter type for use // with apply. type ModelAdapterApplyConfiguration struct { v1.TypeMetaApplyConfiguration `json:",inline"` @@ -32,7 +32,7 @@ type ModelAdapterApplyConfiguration struct { Status *ModelAdapterStatusApplyConfiguration `json:"status,omitempty"` } -// ModelAdapter constructs an declarative configuration of the ModelAdapter type for use with +// ModelAdapter constructs a declarative configuration of the ModelAdapter type for use with // apply. func ModelAdapter(name, namespace string) *ModelAdapterApplyConfiguration { b := &ModelAdapterApplyConfiguration{} @@ -216,3 +216,9 @@ func (b *ModelAdapterApplyConfiguration) WithStatus(value *ModelAdapterStatusApp b.Status = value return b } + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *ModelAdapterApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.Name +} diff --git a/pkg/client/applyconfiguration/model/v1alpha1/modeladapterspec.go b/pkg/client/applyconfiguration/model/v1alpha1/modeladapterspec.go index 7856a63f..f244bda2 100644 --- a/pkg/client/applyconfiguration/model/v1alpha1/modeladapterspec.go +++ b/pkg/client/applyconfiguration/model/v1alpha1/modeladapterspec.go @@ -19,22 +19,22 @@ package v1alpha1 import ( corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/client-go/applyconfigurations/meta/v1" ) -// ModelAdapterSpecApplyConfiguration represents an declarative configuration of the ModelAdapterSpec type for use +// ModelAdapterSpecApplyConfiguration represents a declarative configuration of the ModelAdapterSpec type for use // with apply. type ModelAdapterSpecApplyConfiguration struct { - BaseModel *string `json:"baseModel,omitempty"` - PodSelector *v1.LabelSelector `json:"podSelector,omitempty"` - SchedulerName *string `json:"schedulerName,omitempty"` - ArtifactURL *string `json:"artifactURL,omitempty"` - CredentialsSecretRef *corev1.LocalObjectReference `json:"credentialsSecretRef,omitempty"` - Replicas *int32 `json:"replicas,omitempty"` - AdditionalConfig map[string]string `json:"additionalConfig,omitempty"` + BaseModel *string `json:"baseModel,omitempty"` + PodSelector *v1.LabelSelectorApplyConfiguration `json:"podSelector,omitempty"` + SchedulerName *string `json:"schedulerName,omitempty"` + ArtifactURL *string `json:"artifactURL,omitempty"` + CredentialsSecretRef *corev1.LocalObjectReference `json:"credentialsSecretRef,omitempty"` + Replicas *int32 `json:"replicas,omitempty"` + AdditionalConfig map[string]string `json:"additionalConfig,omitempty"` } -// ModelAdapterSpecApplyConfiguration constructs an declarative configuration of the ModelAdapterSpec type for use with +// ModelAdapterSpecApplyConfiguration constructs a declarative configuration of the ModelAdapterSpec type for use with // apply. func ModelAdapterSpec() *ModelAdapterSpecApplyConfiguration { return &ModelAdapterSpecApplyConfiguration{} @@ -51,8 +51,8 @@ func (b *ModelAdapterSpecApplyConfiguration) WithBaseModel(value string) *ModelA // WithPodSelector sets the PodSelector field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the PodSelector field is set to the value of the last call. -func (b *ModelAdapterSpecApplyConfiguration) WithPodSelector(value v1.LabelSelector) *ModelAdapterSpecApplyConfiguration { - b.PodSelector = &value +func (b *ModelAdapterSpecApplyConfiguration) WithPodSelector(value *v1.LabelSelectorApplyConfiguration) *ModelAdapterSpecApplyConfiguration { + b.PodSelector = value return b } diff --git a/pkg/client/applyconfiguration/model/v1alpha1/modeladapterstatus.go b/pkg/client/applyconfiguration/model/v1alpha1/modeladapterstatus.go index e567f7da..ebd1c994 100644 --- a/pkg/client/applyconfiguration/model/v1alpha1/modeladapterstatus.go +++ b/pkg/client/applyconfiguration/model/v1alpha1/modeladapterstatus.go @@ -19,18 +19,18 @@ package v1alpha1 import ( v1alpha1 "github.com/vllm-project/aibrix/api/model/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/client-go/applyconfigurations/meta/v1" ) -// ModelAdapterStatusApplyConfiguration represents an declarative configuration of the ModelAdapterStatus type for use +// ModelAdapterStatusApplyConfiguration represents a declarative configuration of the ModelAdapterStatus type for use // with apply. type ModelAdapterStatusApplyConfiguration struct { - Phase *v1alpha1.ModelAdapterPhase `json:"phase,omitempty"` - Conditions []v1.Condition `json:"conditions,omitempty"` - Instances []string `json:"instances,omitempty"` + Phase *v1alpha1.ModelAdapterPhase `json:"phase,omitempty"` + Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"` + Instances []string `json:"instances,omitempty"` } -// ModelAdapterStatusApplyConfiguration constructs an declarative configuration of the ModelAdapterStatus type for use with +// ModelAdapterStatusApplyConfiguration constructs a declarative configuration of the ModelAdapterStatus type for use with // apply. func ModelAdapterStatus() *ModelAdapterStatusApplyConfiguration { return &ModelAdapterStatusApplyConfiguration{} @@ -47,9 +47,12 @@ func (b *ModelAdapterStatusApplyConfiguration) WithPhase(value v1alpha1.ModelAda // WithConditions adds the given value to the Conditions field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Conditions field. -func (b *ModelAdapterStatusApplyConfiguration) WithConditions(values ...v1.Condition) *ModelAdapterStatusApplyConfiguration { +func (b *ModelAdapterStatusApplyConfiguration) WithConditions(values ...*v1.ConditionApplyConfiguration) *ModelAdapterStatusApplyConfiguration { for i := range values { - b.Conditions = append(b.Conditions, values[i]) + if values[i] == nil { + panic("nil value passed to WithConditions") + } + b.Conditions = append(b.Conditions, *values[i]) } return b } diff --git a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleet.go b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleet.go index a694a802..7e7fb98a 100644 --- a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleet.go +++ b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleet.go @@ -23,7 +23,7 @@ import ( v1 "k8s.io/client-go/applyconfigurations/meta/v1" ) -// RayClusterFleetApplyConfiguration represents an declarative configuration of the RayClusterFleet type for use +// RayClusterFleetApplyConfiguration represents a declarative configuration of the RayClusterFleet type for use // with apply. type RayClusterFleetApplyConfiguration struct { v1.TypeMetaApplyConfiguration `json:",inline"` @@ -32,7 +32,7 @@ type RayClusterFleetApplyConfiguration struct { Status *RayClusterFleetStatusApplyConfiguration `json:"status,omitempty"` } -// RayClusterFleet constructs an declarative configuration of the RayClusterFleet type for use with +// RayClusterFleet constructs a declarative configuration of the RayClusterFleet type for use with // apply. func RayClusterFleet(name, namespace string) *RayClusterFleetApplyConfiguration { b := &RayClusterFleetApplyConfiguration{} @@ -216,3 +216,9 @@ func (b *RayClusterFleetApplyConfiguration) WithStatus(value *RayClusterFleetSta b.Status = value return b } + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *RayClusterFleetApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.Name +} diff --git a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleetcondition.go b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleetcondition.go index 2954a634..d0ba29fc 100644 --- a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleetcondition.go +++ b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleetcondition.go @@ -23,7 +23,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// RayClusterFleetConditionApplyConfiguration represents an declarative configuration of the RayClusterFleetCondition type for use +// RayClusterFleetConditionApplyConfiguration represents a declarative configuration of the RayClusterFleetCondition type for use // with apply. type RayClusterFleetConditionApplyConfiguration struct { Type *v1alpha1.RayClusterFleetConditionType `json:"type,omitempty"` @@ -34,7 +34,7 @@ type RayClusterFleetConditionApplyConfiguration struct { Message *string `json:"message,omitempty"` } -// RayClusterFleetConditionApplyConfiguration constructs an declarative configuration of the RayClusterFleetCondition type for use with +// RayClusterFleetConditionApplyConfiguration constructs a declarative configuration of the RayClusterFleetCondition type for use with // apply. func RayClusterFleetCondition() *RayClusterFleetConditionApplyConfiguration { return &RayClusterFleetConditionApplyConfiguration{} diff --git a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleetspec.go b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleetspec.go index 74eb8fb2..0e339f64 100644 --- a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleetspec.go +++ b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleetspec.go @@ -19,14 +19,14 @@ package v1alpha1 import ( appsv1 "k8s.io/api/apps/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/client-go/applyconfigurations/meta/v1" ) -// RayClusterFleetSpecApplyConfiguration represents an declarative configuration of the RayClusterFleetSpec type for use +// RayClusterFleetSpecApplyConfiguration represents a declarative configuration of the RayClusterFleetSpec type for use // with apply. type RayClusterFleetSpecApplyConfiguration struct { Replicas *int32 `json:"replicas,omitempty"` - Selector *v1.LabelSelector `json:"selector,omitempty"` + Selector *v1.LabelSelectorApplyConfiguration `json:"selector,omitempty"` Template *RayClusterTemplateSpecApplyConfiguration `json:"template,omitempty"` Strategy *appsv1.DeploymentStrategy `json:"strategy,omitempty"` MinReadySeconds *int32 `json:"minReadySeconds,omitempty"` @@ -35,7 +35,7 @@ type RayClusterFleetSpecApplyConfiguration struct { ProgressDeadlineSeconds *int32 `json:"progressDeadlineSeconds,omitempty"` } -// RayClusterFleetSpecApplyConfiguration constructs an declarative configuration of the RayClusterFleetSpec type for use with +// RayClusterFleetSpecApplyConfiguration constructs a declarative configuration of the RayClusterFleetSpec type for use with // apply. func RayClusterFleetSpec() *RayClusterFleetSpecApplyConfiguration { return &RayClusterFleetSpecApplyConfiguration{} @@ -52,8 +52,8 @@ func (b *RayClusterFleetSpecApplyConfiguration) WithReplicas(value int32) *RayCl // WithSelector sets the Selector field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Selector field is set to the value of the last call. -func (b *RayClusterFleetSpecApplyConfiguration) WithSelector(value v1.LabelSelector) *RayClusterFleetSpecApplyConfiguration { - b.Selector = &value +func (b *RayClusterFleetSpecApplyConfiguration) WithSelector(value *v1.LabelSelectorApplyConfiguration) *RayClusterFleetSpecApplyConfiguration { + b.Selector = value return b } diff --git a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleetstatus.go b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleetstatus.go index a47c4d9e..30473391 100644 --- a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleetstatus.go +++ b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterfleetstatus.go @@ -17,7 +17,7 @@ limitations under the License. package v1alpha1 -// RayClusterFleetStatusApplyConfiguration represents an declarative configuration of the RayClusterFleetStatus type for use +// RayClusterFleetStatusApplyConfiguration represents a declarative configuration of the RayClusterFleetStatus type for use // with apply. type RayClusterFleetStatusApplyConfiguration struct { ObservedGeneration *int64 `json:"observedGeneration,omitempty"` @@ -30,7 +30,7 @@ type RayClusterFleetStatusApplyConfiguration struct { CollisionCount *int32 `json:"collisionCount,omitempty"` } -// RayClusterFleetStatusApplyConfiguration constructs an declarative configuration of the RayClusterFleetStatus type for use with +// RayClusterFleetStatusApplyConfiguration constructs a declarative configuration of the RayClusterFleetStatus type for use with // apply. func RayClusterFleetStatus() *RayClusterFleetStatusApplyConfiguration { return &RayClusterFleetStatusApplyConfiguration{} diff --git a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterreplicaset.go b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterreplicaset.go index 0caca32d..7a36dcb4 100644 --- a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterreplicaset.go +++ b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterreplicaset.go @@ -23,7 +23,7 @@ import ( v1 "k8s.io/client-go/applyconfigurations/meta/v1" ) -// RayClusterReplicaSetApplyConfiguration represents an declarative configuration of the RayClusterReplicaSet type for use +// RayClusterReplicaSetApplyConfiguration represents a declarative configuration of the RayClusterReplicaSet type for use // with apply. type RayClusterReplicaSetApplyConfiguration struct { v1.TypeMetaApplyConfiguration `json:",inline"` @@ -32,7 +32,7 @@ type RayClusterReplicaSetApplyConfiguration struct { Status *RayClusterReplicaSetStatusApplyConfiguration `json:"status,omitempty"` } -// RayClusterReplicaSet constructs an declarative configuration of the RayClusterReplicaSet type for use with +// RayClusterReplicaSet constructs a declarative configuration of the RayClusterReplicaSet type for use with // apply. func RayClusterReplicaSet(name, namespace string) *RayClusterReplicaSetApplyConfiguration { b := &RayClusterReplicaSetApplyConfiguration{} @@ -216,3 +216,9 @@ func (b *RayClusterReplicaSetApplyConfiguration) WithStatus(value *RayClusterRep b.Status = value return b } + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *RayClusterReplicaSetApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.Name +} diff --git a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterreplicasetspec.go b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterreplicasetspec.go index 1860ed1a..b992db2c 100644 --- a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterreplicasetspec.go +++ b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterreplicasetspec.go @@ -18,19 +18,19 @@ limitations under the License. package v1alpha1 import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/client-go/applyconfigurations/meta/v1" ) -// RayClusterReplicaSetSpecApplyConfiguration represents an declarative configuration of the RayClusterReplicaSetSpec type for use +// RayClusterReplicaSetSpecApplyConfiguration represents a declarative configuration of the RayClusterReplicaSetSpec type for use // with apply. type RayClusterReplicaSetSpecApplyConfiguration struct { Replicas *int32 `json:"replicas,omitempty"` MinReadySeconds *int32 `json:"minReadySeconds,omitempty"` - Selector *v1.LabelSelector `json:"selector,omitempty"` + Selector *v1.LabelSelectorApplyConfiguration `json:"selector,omitempty"` Template *RayClusterTemplateSpecApplyConfiguration `json:"template,omitempty"` } -// RayClusterReplicaSetSpecApplyConfiguration constructs an declarative configuration of the RayClusterReplicaSetSpec type for use with +// RayClusterReplicaSetSpecApplyConfiguration constructs a declarative configuration of the RayClusterReplicaSetSpec type for use with // apply. func RayClusterReplicaSetSpec() *RayClusterReplicaSetSpecApplyConfiguration { return &RayClusterReplicaSetSpecApplyConfiguration{} @@ -55,8 +55,8 @@ func (b *RayClusterReplicaSetSpecApplyConfiguration) WithMinReadySeconds(value i // WithSelector sets the Selector field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Selector field is set to the value of the last call. -func (b *RayClusterReplicaSetSpecApplyConfiguration) WithSelector(value v1.LabelSelector) *RayClusterReplicaSetSpecApplyConfiguration { - b.Selector = &value +func (b *RayClusterReplicaSetSpecApplyConfiguration) WithSelector(value *v1.LabelSelectorApplyConfiguration) *RayClusterReplicaSetSpecApplyConfiguration { + b.Selector = value return b } diff --git a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterreplicasetstatus.go b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterreplicasetstatus.go index 59b40929..0816cb24 100644 --- a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterreplicasetstatus.go +++ b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclusterreplicasetstatus.go @@ -18,21 +18,21 @@ limitations under the License. package v1alpha1 import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/client-go/applyconfigurations/meta/v1" ) -// RayClusterReplicaSetStatusApplyConfiguration represents an declarative configuration of the RayClusterReplicaSetStatus type for use +// RayClusterReplicaSetStatusApplyConfiguration represents a declarative configuration of the RayClusterReplicaSetStatus type for use // with apply. type RayClusterReplicaSetStatusApplyConfiguration struct { - Replicas *int32 `json:"replicas,omitempty"` - FullyLabeledReplicas *int32 `json:"fullyLabeledReplicas,omitempty"` - ReadyReplicas *int32 `json:"readyReplicas,omitempty"` - AvailableReplicas *int32 `json:"availableReplicas,omitempty"` - ObservedGeneration *int64 `json:"observedGeneration,omitempty"` - Conditions []v1.Condition `json:"conditions,omitempty"` + Replicas *int32 `json:"replicas,omitempty"` + FullyLabeledReplicas *int32 `json:"fullyLabeledReplicas,omitempty"` + ReadyReplicas *int32 `json:"readyReplicas,omitempty"` + AvailableReplicas *int32 `json:"availableReplicas,omitempty"` + ObservedGeneration *int64 `json:"observedGeneration,omitempty"` + Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"` } -// RayClusterReplicaSetStatusApplyConfiguration constructs an declarative configuration of the RayClusterReplicaSetStatus type for use with +// RayClusterReplicaSetStatusApplyConfiguration constructs a declarative configuration of the RayClusterReplicaSetStatus type for use with // apply. func RayClusterReplicaSetStatus() *RayClusterReplicaSetStatusApplyConfiguration { return &RayClusterReplicaSetStatusApplyConfiguration{} @@ -81,9 +81,12 @@ func (b *RayClusterReplicaSetStatusApplyConfiguration) WithObservedGeneration(va // WithConditions adds the given value to the Conditions field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Conditions field. -func (b *RayClusterReplicaSetStatusApplyConfiguration) WithConditions(values ...v1.Condition) *RayClusterReplicaSetStatusApplyConfiguration { +func (b *RayClusterReplicaSetStatusApplyConfiguration) WithConditions(values ...*v1.ConditionApplyConfiguration) *RayClusterReplicaSetStatusApplyConfiguration { for i := range values { - b.Conditions = append(b.Conditions, values[i]) + if values[i] == nil { + panic("nil value passed to WithConditions") + } + b.Conditions = append(b.Conditions, *values[i]) } return b } diff --git a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclustertemplatespec.go b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclustertemplatespec.go index 7631674a..495cc921 100644 --- a/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclustertemplatespec.go +++ b/pkg/client/applyconfiguration/orchestration/v1alpha1/rayclustertemplatespec.go @@ -24,14 +24,14 @@ import ( v1 "k8s.io/client-go/applyconfigurations/meta/v1" ) -// RayClusterTemplateSpecApplyConfiguration represents an declarative configuration of the RayClusterTemplateSpec type for use +// RayClusterTemplateSpecApplyConfiguration represents a declarative configuration of the RayClusterTemplateSpec type for use // with apply. type RayClusterTemplateSpecApplyConfiguration struct { *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` Spec *rayv1.RayClusterSpec `json:"spec,omitempty"` } -// RayClusterTemplateSpecApplyConfiguration constructs an declarative configuration of the RayClusterTemplateSpec type for use with +// RayClusterTemplateSpecApplyConfiguration constructs a declarative configuration of the RayClusterTemplateSpec type for use with // apply. func RayClusterTemplateSpec() *RayClusterTemplateSpecApplyConfiguration { return &RayClusterTemplateSpecApplyConfiguration{} @@ -186,3 +186,9 @@ func (b *RayClusterTemplateSpecApplyConfiguration) WithSpec(value rayv1.RayClust b.Spec = &value return b } + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *RayClusterTemplateSpecApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.Name +} diff --git a/pkg/client/applyconfiguration/utils.go b/pkg/client/applyconfiguration/utils.go index cbf6e318..6032b0f8 100644 --- a/pkg/client/applyconfiguration/utils.go +++ b/pkg/client/applyconfiguration/utils.go @@ -22,9 +22,12 @@ import ( modelv1alpha1 "github.com/vllm-project/aibrix/api/model/v1alpha1" orchestrationv1alpha1 "github.com/vllm-project/aibrix/api/orchestration/v1alpha1" autoscalingv1alpha1 "github.com/vllm-project/aibrix/pkg/client/applyconfiguration/autoscaling/v1alpha1" + internal "github.com/vllm-project/aibrix/pkg/client/applyconfiguration/internal" applyconfigurationmodelv1alpha1 "github.com/vllm-project/aibrix/pkg/client/applyconfiguration/model/v1alpha1" applyconfigurationorchestrationv1alpha1 "github.com/vllm-project/aibrix/pkg/client/applyconfiguration/orchestration/v1alpha1" + runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" + testing "k8s.io/client-go/testing" ) // ForKind returns an apply configuration type for the given GroupVersionKind, or nil if no @@ -70,3 +73,7 @@ func ForKind(kind schema.GroupVersionKind) interface{} { } return nil } + +func NewTypeConverter(scheme *runtime.Scheme) *testing.TypeConverter { + return &testing.TypeConverter{Scheme: scheme, TypeResolver: internal.Parser()} +} diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index 0b2c40e9..15920711 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -18,6 +18,7 @@ limitations under the License. package fake import ( + applyconfiguration "github.com/vllm-project/aibrix/pkg/client/applyconfiguration" clientset "github.com/vllm-project/aibrix/pkg/client/clientset/versioned" autoscalingv1alpha1 "github.com/vllm-project/aibrix/pkg/client/clientset/versioned/typed/autoscaling/v1alpha1" fakeautoscalingv1alpha1 "github.com/vllm-project/aibrix/pkg/client/clientset/versioned/typed/autoscaling/v1alpha1/fake" @@ -34,8 +35,12 @@ import ( // NewSimpleClientset returns a clientset that will respond with the provided objects. // It's backed by a very simple object tracker that processes creates, updates and deletions as-is, -// without applying any validations and/or defaults. It shouldn't be considered a replacement +// without applying any field management, validations and/or defaults. It shouldn't be considered a replacement // for a real clientset and is mostly useful in simple unit tests. +// +// DEPRECATED: NewClientset replaces this with support for field management, which significantly improves +// server side apply testing. NewClientset is only available when apply configurations are generated (e.g. +// via --with-applyconfig). func NewSimpleClientset(objects ...runtime.Object) *Clientset { o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) for _, obj := range objects { @@ -77,6 +82,38 @@ func (c *Clientset) Tracker() testing.ObjectTracker { return c.tracker } +// NewClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +func NewClientset(objects ...runtime.Object) *Clientset { + o := testing.NewFieldManagedObjectTracker( + scheme, + codecs.UniversalDecoder(), + applyconfiguration.NewTypeConverter(scheme), + ) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{tracker: o} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + var ( _ clientset.Interface = &Clientset{} _ testing.FakeClient = &Clientset{} diff --git a/pkg/client/clientset/versioned/typed/autoscaling/v1alpha1/fake/fake_podautoscaler.go b/pkg/client/clientset/versioned/typed/autoscaling/v1alpha1/fake/fake_podautoscaler.go index e5e1f9c8..2268e524 100644 --- a/pkg/client/clientset/versioned/typed/autoscaling/v1alpha1/fake/fake_podautoscaler.go +++ b/pkg/client/clientset/versioned/typed/autoscaling/v1alpha1/fake/fake_podautoscaler.go @@ -43,22 +43,24 @@ var podautoscalersKind = v1alpha1.SchemeGroupVersion.WithKind("PodAutoscaler") // Get takes name of the podAutoscaler, and returns the corresponding podAutoscaler object, and an error if there is any. func (c *FakePodAutoscalers) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PodAutoscaler, err error) { + emptyResult := &v1alpha1.PodAutoscaler{} obj, err := c.Fake. - Invokes(testing.NewGetAction(podautoscalersResource, c.ns, name), &v1alpha1.PodAutoscaler{}) + Invokes(testing.NewGetActionWithOptions(podautoscalersResource, c.ns, name, options), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.PodAutoscaler), err } // List takes label and field selectors, and returns the list of PodAutoscalers that match those selectors. func (c *FakePodAutoscalers) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PodAutoscalerList, err error) { + emptyResult := &v1alpha1.PodAutoscalerList{} obj, err := c.Fake. - Invokes(testing.NewListAction(podautoscalersResource, podautoscalersKind, c.ns, opts), &v1alpha1.PodAutoscalerList{}) + Invokes(testing.NewListActionWithOptions(podautoscalersResource, podautoscalersKind, c.ns, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } label, _, _ := testing.ExtractFromListOptions(opts) @@ -77,40 +79,43 @@ func (c *FakePodAutoscalers) List(ctx context.Context, opts v1.ListOptions) (res // Watch returns a watch.Interface that watches the requested podAutoscalers. func (c *FakePodAutoscalers) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { return c.Fake. - InvokesWatch(testing.NewWatchAction(podautoscalersResource, c.ns, opts)) + InvokesWatch(testing.NewWatchActionWithOptions(podautoscalersResource, c.ns, opts)) } // Create takes the representation of a podAutoscaler and creates it. Returns the server's representation of the podAutoscaler, and an error, if there is any. func (c *FakePodAutoscalers) Create(ctx context.Context, podAutoscaler *v1alpha1.PodAutoscaler, opts v1.CreateOptions) (result *v1alpha1.PodAutoscaler, err error) { + emptyResult := &v1alpha1.PodAutoscaler{} obj, err := c.Fake. - Invokes(testing.NewCreateAction(podautoscalersResource, c.ns, podAutoscaler), &v1alpha1.PodAutoscaler{}) + Invokes(testing.NewCreateActionWithOptions(podautoscalersResource, c.ns, podAutoscaler, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.PodAutoscaler), err } // Update takes the representation of a podAutoscaler and updates it. Returns the server's representation of the podAutoscaler, and an error, if there is any. func (c *FakePodAutoscalers) Update(ctx context.Context, podAutoscaler *v1alpha1.PodAutoscaler, opts v1.UpdateOptions) (result *v1alpha1.PodAutoscaler, err error) { + emptyResult := &v1alpha1.PodAutoscaler{} obj, err := c.Fake. - Invokes(testing.NewUpdateAction(podautoscalersResource, c.ns, podAutoscaler), &v1alpha1.PodAutoscaler{}) + Invokes(testing.NewUpdateActionWithOptions(podautoscalersResource, c.ns, podAutoscaler, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.PodAutoscaler), 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 *FakePodAutoscalers) UpdateStatus(ctx context.Context, podAutoscaler *v1alpha1.PodAutoscaler, opts v1.UpdateOptions) (*v1alpha1.PodAutoscaler, error) { +func (c *FakePodAutoscalers) UpdateStatus(ctx context.Context, podAutoscaler *v1alpha1.PodAutoscaler, opts v1.UpdateOptions) (result *v1alpha1.PodAutoscaler, err error) { + emptyResult := &v1alpha1.PodAutoscaler{} obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(podautoscalersResource, "status", c.ns, podAutoscaler), &v1alpha1.PodAutoscaler{}) + Invokes(testing.NewUpdateSubresourceActionWithOptions(podautoscalersResource, "status", c.ns, podAutoscaler, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.PodAutoscaler), err } @@ -125,7 +130,7 @@ func (c *FakePodAutoscalers) Delete(ctx context.Context, name string, opts v1.De // DeleteCollection deletes a collection of objects. func (c *FakePodAutoscalers) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(podautoscalersResource, c.ns, listOpts) + action := testing.NewDeleteCollectionActionWithOptions(podautoscalersResource, c.ns, opts, listOpts) _, err := c.Fake.Invokes(action, &v1alpha1.PodAutoscalerList{}) return err @@ -133,11 +138,12 @@ func (c *FakePodAutoscalers) DeleteCollection(ctx context.Context, opts v1.Delet // Patch applies the patch and returns the patched podAutoscaler. func (c *FakePodAutoscalers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PodAutoscaler, err error) { + emptyResult := &v1alpha1.PodAutoscaler{} obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(podautoscalersResource, c.ns, name, pt, data, subresources...), &v1alpha1.PodAutoscaler{}) + Invokes(testing.NewPatchSubresourceActionWithOptions(podautoscalersResource, c.ns, name, pt, data, opts, subresources...), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.PodAutoscaler), err } @@ -155,11 +161,12 @@ func (c *FakePodAutoscalers) Apply(ctx context.Context, podAutoscaler *autoscali if name == nil { return nil, fmt.Errorf("podAutoscaler.Name must be provided to Apply") } + emptyResult := &v1alpha1.PodAutoscaler{} obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(podautoscalersResource, c.ns, *name, types.ApplyPatchType, data), &v1alpha1.PodAutoscaler{}) + Invokes(testing.NewPatchSubresourceActionWithOptions(podautoscalersResource, c.ns, *name, types.ApplyPatchType, data, opts.ToPatchOptions()), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.PodAutoscaler), err } @@ -178,11 +185,12 @@ func (c *FakePodAutoscalers) ApplyStatus(ctx context.Context, podAutoscaler *aut if name == nil { return nil, fmt.Errorf("podAutoscaler.Name must be provided to Apply") } + emptyResult := &v1alpha1.PodAutoscaler{} obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(podautoscalersResource, c.ns, *name, types.ApplyPatchType, data, "status"), &v1alpha1.PodAutoscaler{}) + Invokes(testing.NewPatchSubresourceActionWithOptions(podautoscalersResource, c.ns, *name, types.ApplyPatchType, data, opts.ToPatchOptions(), "status"), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.PodAutoscaler), err } diff --git a/pkg/client/clientset/versioned/typed/autoscaling/v1alpha1/podautoscaler.go b/pkg/client/clientset/versioned/typed/autoscaling/v1alpha1/podautoscaler.go index 601e982b..8a1ab8d6 100644 --- a/pkg/client/clientset/versioned/typed/autoscaling/v1alpha1/podautoscaler.go +++ b/pkg/client/clientset/versioned/typed/autoscaling/v1alpha1/podautoscaler.go @@ -19,9 +19,6 @@ package v1alpha1 import ( "context" - json "encoding/json" - "fmt" - "time" v1alpha1 "github.com/vllm-project/aibrix/api/autoscaling/v1alpha1" autoscalingv1alpha1 "github.com/vllm-project/aibrix/pkg/client/applyconfiguration/autoscaling/v1alpha1" @@ -29,7 +26,7 @@ import ( 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" + gentype "k8s.io/client-go/gentype" ) // PodAutoscalersGetter has a method to return a PodAutoscalerInterface. @@ -42,6 +39,7 @@ type PodAutoscalersGetter interface { type PodAutoscalerInterface interface { Create(ctx context.Context, podAutoscaler *v1alpha1.PodAutoscaler, opts v1.CreateOptions) (*v1alpha1.PodAutoscaler, error) Update(ctx context.Context, podAutoscaler *v1alpha1.PodAutoscaler, opts v1.UpdateOptions) (*v1alpha1.PodAutoscaler, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). UpdateStatus(ctx context.Context, podAutoscaler *v1alpha1.PodAutoscaler, opts v1.UpdateOptions) (*v1alpha1.PodAutoscaler, error) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error @@ -50,206 +48,25 @@ type PodAutoscalerInterface interface { 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.PodAutoscaler, err error) Apply(ctx context.Context, podAutoscaler *autoscalingv1alpha1.PodAutoscalerApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.PodAutoscaler, err error) + // Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). ApplyStatus(ctx context.Context, podAutoscaler *autoscalingv1alpha1.PodAutoscalerApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.PodAutoscaler, err error) PodAutoscalerExpansion } // podAutoscalers implements PodAutoscalerInterface type podAutoscalers struct { - client rest.Interface - ns string + *gentype.ClientWithListAndApply[*v1alpha1.PodAutoscaler, *v1alpha1.PodAutoscalerList, *autoscalingv1alpha1.PodAutoscalerApplyConfiguration] } // newPodAutoscalers returns a PodAutoscalers func newPodAutoscalers(c *AutoscalingV1alpha1Client, namespace string) *podAutoscalers { return &podAutoscalers{ - client: c.RESTClient(), - ns: namespace, + gentype.NewClientWithListAndApply[*v1alpha1.PodAutoscaler, *v1alpha1.PodAutoscalerList, *autoscalingv1alpha1.PodAutoscalerApplyConfiguration]( + "podautoscalers", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *v1alpha1.PodAutoscaler { return &v1alpha1.PodAutoscaler{} }, + func() *v1alpha1.PodAutoscalerList { return &v1alpha1.PodAutoscalerList{} }), } } - -// Get takes name of the podAutoscaler, and returns the corresponding podAutoscaler object, and an error if there is any. -func (c *podAutoscalers) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PodAutoscaler, err error) { - result = &v1alpha1.PodAutoscaler{} - err = c.client.Get(). - Namespace(c.ns). - Resource("podautoscalers"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of PodAutoscalers that match those selectors. -func (c *podAutoscalers) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PodAutoscalerList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha1.PodAutoscalerList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("podautoscalers"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested podAutoscalers. -func (c *podAutoscalers) 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(). - Namespace(c.ns). - Resource("podautoscalers"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a podAutoscaler and creates it. Returns the server's representation of the podAutoscaler, and an error, if there is any. -func (c *podAutoscalers) Create(ctx context.Context, podAutoscaler *v1alpha1.PodAutoscaler, opts v1.CreateOptions) (result *v1alpha1.PodAutoscaler, err error) { - result = &v1alpha1.PodAutoscaler{} - err = c.client.Post(). - Namespace(c.ns). - Resource("podautoscalers"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(podAutoscaler). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a podAutoscaler and updates it. Returns the server's representation of the podAutoscaler, and an error, if there is any. -func (c *podAutoscalers) Update(ctx context.Context, podAutoscaler *v1alpha1.PodAutoscaler, opts v1.UpdateOptions) (result *v1alpha1.PodAutoscaler, err error) { - result = &v1alpha1.PodAutoscaler{} - err = c.client.Put(). - Namespace(c.ns). - Resource("podautoscalers"). - Name(podAutoscaler.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(podAutoscaler). - 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 *podAutoscalers) UpdateStatus(ctx context.Context, podAutoscaler *v1alpha1.PodAutoscaler, opts v1.UpdateOptions) (result *v1alpha1.PodAutoscaler, err error) { - result = &v1alpha1.PodAutoscaler{} - err = c.client.Put(). - Namespace(c.ns). - Resource("podautoscalers"). - Name(podAutoscaler.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(podAutoscaler). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the podAutoscaler and deletes it. Returns an error if one occurs. -func (c *podAutoscalers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("podautoscalers"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *podAutoscalers) 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(). - Namespace(c.ns). - Resource("podautoscalers"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched podAutoscaler. -func (c *podAutoscalers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PodAutoscaler, err error) { - result = &v1alpha1.PodAutoscaler{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("podautoscalers"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} - -// Apply takes the given apply declarative configuration, applies it and returns the applied podAutoscaler. -func (c *podAutoscalers) Apply(ctx context.Context, podAutoscaler *autoscalingv1alpha1.PodAutoscalerApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.PodAutoscaler, err error) { - if podAutoscaler == nil { - return nil, fmt.Errorf("podAutoscaler provided to Apply must not be nil") - } - patchOpts := opts.ToPatchOptions() - data, err := json.Marshal(podAutoscaler) - if err != nil { - return nil, err - } - name := podAutoscaler.Name - if name == nil { - return nil, fmt.Errorf("podAutoscaler.Name must be provided to Apply") - } - result = &v1alpha1.PodAutoscaler{} - err = c.client.Patch(types.ApplyPatchType). - Namespace(c.ns). - Resource("podautoscalers"). - Name(*name). - VersionedParams(&patchOpts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} - -// ApplyStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). -func (c *podAutoscalers) ApplyStatus(ctx context.Context, podAutoscaler *autoscalingv1alpha1.PodAutoscalerApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.PodAutoscaler, err error) { - if podAutoscaler == nil { - return nil, fmt.Errorf("podAutoscaler provided to Apply must not be nil") - } - patchOpts := opts.ToPatchOptions() - data, err := json.Marshal(podAutoscaler) - if err != nil { - return nil, err - } - - name := podAutoscaler.Name - if name == nil { - return nil, fmt.Errorf("podAutoscaler.Name must be provided to Apply") - } - - result = &v1alpha1.PodAutoscaler{} - err = c.client.Patch(types.ApplyPatchType). - Namespace(c.ns). - Resource("podautoscalers"). - Name(*name). - SubResource("status"). - VersionedParams(&patchOpts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/pkg/client/clientset/versioned/typed/model/v1alpha1/fake/fake_modeladapter.go b/pkg/client/clientset/versioned/typed/model/v1alpha1/fake/fake_modeladapter.go index 370dce0d..7c205a31 100644 --- a/pkg/client/clientset/versioned/typed/model/v1alpha1/fake/fake_modeladapter.go +++ b/pkg/client/clientset/versioned/typed/model/v1alpha1/fake/fake_modeladapter.go @@ -43,22 +43,24 @@ var modeladaptersKind = v1alpha1.SchemeGroupVersion.WithKind("ModelAdapter") // Get takes name of the modelAdapter, and returns the corresponding modelAdapter object, and an error if there is any. func (c *FakeModelAdapters) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ModelAdapter, err error) { + emptyResult := &v1alpha1.ModelAdapter{} obj, err := c.Fake. - Invokes(testing.NewGetAction(modeladaptersResource, c.ns, name), &v1alpha1.ModelAdapter{}) + Invokes(testing.NewGetActionWithOptions(modeladaptersResource, c.ns, name, options), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.ModelAdapter), err } // List takes label and field selectors, and returns the list of ModelAdapters that match those selectors. func (c *FakeModelAdapters) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ModelAdapterList, err error) { + emptyResult := &v1alpha1.ModelAdapterList{} obj, err := c.Fake. - Invokes(testing.NewListAction(modeladaptersResource, modeladaptersKind, c.ns, opts), &v1alpha1.ModelAdapterList{}) + Invokes(testing.NewListActionWithOptions(modeladaptersResource, modeladaptersKind, c.ns, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } label, _, _ := testing.ExtractFromListOptions(opts) @@ -77,40 +79,43 @@ func (c *FakeModelAdapters) List(ctx context.Context, opts v1.ListOptions) (resu // Watch returns a watch.Interface that watches the requested modelAdapters. func (c *FakeModelAdapters) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { return c.Fake. - InvokesWatch(testing.NewWatchAction(modeladaptersResource, c.ns, opts)) + InvokesWatch(testing.NewWatchActionWithOptions(modeladaptersResource, c.ns, opts)) } // Create takes the representation of a modelAdapter and creates it. Returns the server's representation of the modelAdapter, and an error, if there is any. func (c *FakeModelAdapters) Create(ctx context.Context, modelAdapter *v1alpha1.ModelAdapter, opts v1.CreateOptions) (result *v1alpha1.ModelAdapter, err error) { + emptyResult := &v1alpha1.ModelAdapter{} obj, err := c.Fake. - Invokes(testing.NewCreateAction(modeladaptersResource, c.ns, modelAdapter), &v1alpha1.ModelAdapter{}) + Invokes(testing.NewCreateActionWithOptions(modeladaptersResource, c.ns, modelAdapter, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.ModelAdapter), err } // Update takes the representation of a modelAdapter and updates it. Returns the server's representation of the modelAdapter, and an error, if there is any. func (c *FakeModelAdapters) Update(ctx context.Context, modelAdapter *v1alpha1.ModelAdapter, opts v1.UpdateOptions) (result *v1alpha1.ModelAdapter, err error) { + emptyResult := &v1alpha1.ModelAdapter{} obj, err := c.Fake. - Invokes(testing.NewUpdateAction(modeladaptersResource, c.ns, modelAdapter), &v1alpha1.ModelAdapter{}) + Invokes(testing.NewUpdateActionWithOptions(modeladaptersResource, c.ns, modelAdapter, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.ModelAdapter), 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 *FakeModelAdapters) UpdateStatus(ctx context.Context, modelAdapter *v1alpha1.ModelAdapter, opts v1.UpdateOptions) (*v1alpha1.ModelAdapter, error) { +func (c *FakeModelAdapters) UpdateStatus(ctx context.Context, modelAdapter *v1alpha1.ModelAdapter, opts v1.UpdateOptions) (result *v1alpha1.ModelAdapter, err error) { + emptyResult := &v1alpha1.ModelAdapter{} obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(modeladaptersResource, "status", c.ns, modelAdapter), &v1alpha1.ModelAdapter{}) + Invokes(testing.NewUpdateSubresourceActionWithOptions(modeladaptersResource, "status", c.ns, modelAdapter, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.ModelAdapter), err } @@ -125,7 +130,7 @@ func (c *FakeModelAdapters) Delete(ctx context.Context, name string, opts v1.Del // DeleteCollection deletes a collection of objects. func (c *FakeModelAdapters) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(modeladaptersResource, c.ns, listOpts) + action := testing.NewDeleteCollectionActionWithOptions(modeladaptersResource, c.ns, opts, listOpts) _, err := c.Fake.Invokes(action, &v1alpha1.ModelAdapterList{}) return err @@ -133,11 +138,12 @@ func (c *FakeModelAdapters) DeleteCollection(ctx context.Context, opts v1.Delete // Patch applies the patch and returns the patched modelAdapter. func (c *FakeModelAdapters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ModelAdapter, err error) { + emptyResult := &v1alpha1.ModelAdapter{} obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(modeladaptersResource, c.ns, name, pt, data, subresources...), &v1alpha1.ModelAdapter{}) + Invokes(testing.NewPatchSubresourceActionWithOptions(modeladaptersResource, c.ns, name, pt, data, opts, subresources...), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.ModelAdapter), err } @@ -155,11 +161,12 @@ func (c *FakeModelAdapters) Apply(ctx context.Context, modelAdapter *modelv1alph if name == nil { return nil, fmt.Errorf("modelAdapter.Name must be provided to Apply") } + emptyResult := &v1alpha1.ModelAdapter{} obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(modeladaptersResource, c.ns, *name, types.ApplyPatchType, data), &v1alpha1.ModelAdapter{}) + Invokes(testing.NewPatchSubresourceActionWithOptions(modeladaptersResource, c.ns, *name, types.ApplyPatchType, data, opts.ToPatchOptions()), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.ModelAdapter), err } @@ -178,11 +185,12 @@ func (c *FakeModelAdapters) ApplyStatus(ctx context.Context, modelAdapter *model if name == nil { return nil, fmt.Errorf("modelAdapter.Name must be provided to Apply") } + emptyResult := &v1alpha1.ModelAdapter{} obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(modeladaptersResource, c.ns, *name, types.ApplyPatchType, data, "status"), &v1alpha1.ModelAdapter{}) + Invokes(testing.NewPatchSubresourceActionWithOptions(modeladaptersResource, c.ns, *name, types.ApplyPatchType, data, opts.ToPatchOptions(), "status"), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.ModelAdapter), err } diff --git a/pkg/client/clientset/versioned/typed/model/v1alpha1/modeladapter.go b/pkg/client/clientset/versioned/typed/model/v1alpha1/modeladapter.go index 20c28b69..722fa088 100644 --- a/pkg/client/clientset/versioned/typed/model/v1alpha1/modeladapter.go +++ b/pkg/client/clientset/versioned/typed/model/v1alpha1/modeladapter.go @@ -19,9 +19,6 @@ package v1alpha1 import ( "context" - json "encoding/json" - "fmt" - "time" v1alpha1 "github.com/vllm-project/aibrix/api/model/v1alpha1" modelv1alpha1 "github.com/vllm-project/aibrix/pkg/client/applyconfiguration/model/v1alpha1" @@ -29,7 +26,7 @@ import ( 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" + gentype "k8s.io/client-go/gentype" ) // ModelAdaptersGetter has a method to return a ModelAdapterInterface. @@ -42,6 +39,7 @@ type ModelAdaptersGetter interface { type ModelAdapterInterface interface { Create(ctx context.Context, modelAdapter *v1alpha1.ModelAdapter, opts v1.CreateOptions) (*v1alpha1.ModelAdapter, error) Update(ctx context.Context, modelAdapter *v1alpha1.ModelAdapter, opts v1.UpdateOptions) (*v1alpha1.ModelAdapter, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). UpdateStatus(ctx context.Context, modelAdapter *v1alpha1.ModelAdapter, opts v1.UpdateOptions) (*v1alpha1.ModelAdapter, error) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error @@ -50,206 +48,25 @@ type ModelAdapterInterface interface { 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.ModelAdapter, err error) Apply(ctx context.Context, modelAdapter *modelv1alpha1.ModelAdapterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ModelAdapter, err error) + // Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). ApplyStatus(ctx context.Context, modelAdapter *modelv1alpha1.ModelAdapterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ModelAdapter, err error) ModelAdapterExpansion } // modelAdapters implements ModelAdapterInterface type modelAdapters struct { - client rest.Interface - ns string + *gentype.ClientWithListAndApply[*v1alpha1.ModelAdapter, *v1alpha1.ModelAdapterList, *modelv1alpha1.ModelAdapterApplyConfiguration] } // newModelAdapters returns a ModelAdapters func newModelAdapters(c *ModelV1alpha1Client, namespace string) *modelAdapters { return &modelAdapters{ - client: c.RESTClient(), - ns: namespace, + gentype.NewClientWithListAndApply[*v1alpha1.ModelAdapter, *v1alpha1.ModelAdapterList, *modelv1alpha1.ModelAdapterApplyConfiguration]( + "modeladapters", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *v1alpha1.ModelAdapter { return &v1alpha1.ModelAdapter{} }, + func() *v1alpha1.ModelAdapterList { return &v1alpha1.ModelAdapterList{} }), } } - -// Get takes name of the modelAdapter, and returns the corresponding modelAdapter object, and an error if there is any. -func (c *modelAdapters) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ModelAdapter, err error) { - result = &v1alpha1.ModelAdapter{} - err = c.client.Get(). - Namespace(c.ns). - Resource("modeladapters"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of ModelAdapters that match those selectors. -func (c *modelAdapters) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ModelAdapterList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha1.ModelAdapterList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("modeladapters"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested modelAdapters. -func (c *modelAdapters) 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(). - Namespace(c.ns). - Resource("modeladapters"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a modelAdapter and creates it. Returns the server's representation of the modelAdapter, and an error, if there is any. -func (c *modelAdapters) Create(ctx context.Context, modelAdapter *v1alpha1.ModelAdapter, opts v1.CreateOptions) (result *v1alpha1.ModelAdapter, err error) { - result = &v1alpha1.ModelAdapter{} - err = c.client.Post(). - Namespace(c.ns). - Resource("modeladapters"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(modelAdapter). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a modelAdapter and updates it. Returns the server's representation of the modelAdapter, and an error, if there is any. -func (c *modelAdapters) Update(ctx context.Context, modelAdapter *v1alpha1.ModelAdapter, opts v1.UpdateOptions) (result *v1alpha1.ModelAdapter, err error) { - result = &v1alpha1.ModelAdapter{} - err = c.client.Put(). - Namespace(c.ns). - Resource("modeladapters"). - Name(modelAdapter.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(modelAdapter). - 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 *modelAdapters) UpdateStatus(ctx context.Context, modelAdapter *v1alpha1.ModelAdapter, opts v1.UpdateOptions) (result *v1alpha1.ModelAdapter, err error) { - result = &v1alpha1.ModelAdapter{} - err = c.client.Put(). - Namespace(c.ns). - Resource("modeladapters"). - Name(modelAdapter.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(modelAdapter). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the modelAdapter and deletes it. Returns an error if one occurs. -func (c *modelAdapters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("modeladapters"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *modelAdapters) 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(). - Namespace(c.ns). - Resource("modeladapters"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched modelAdapter. -func (c *modelAdapters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ModelAdapter, err error) { - result = &v1alpha1.ModelAdapter{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("modeladapters"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} - -// Apply takes the given apply declarative configuration, applies it and returns the applied modelAdapter. -func (c *modelAdapters) Apply(ctx context.Context, modelAdapter *modelv1alpha1.ModelAdapterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ModelAdapter, err error) { - if modelAdapter == nil { - return nil, fmt.Errorf("modelAdapter provided to Apply must not be nil") - } - patchOpts := opts.ToPatchOptions() - data, err := json.Marshal(modelAdapter) - if err != nil { - return nil, err - } - name := modelAdapter.Name - if name == nil { - return nil, fmt.Errorf("modelAdapter.Name must be provided to Apply") - } - result = &v1alpha1.ModelAdapter{} - err = c.client.Patch(types.ApplyPatchType). - Namespace(c.ns). - Resource("modeladapters"). - Name(*name). - VersionedParams(&patchOpts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} - -// ApplyStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). -func (c *modelAdapters) ApplyStatus(ctx context.Context, modelAdapter *modelv1alpha1.ModelAdapterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ModelAdapter, err error) { - if modelAdapter == nil { - return nil, fmt.Errorf("modelAdapter provided to Apply must not be nil") - } - patchOpts := opts.ToPatchOptions() - data, err := json.Marshal(modelAdapter) - if err != nil { - return nil, err - } - - name := modelAdapter.Name - if name == nil { - return nil, fmt.Errorf("modelAdapter.Name must be provided to Apply") - } - - result = &v1alpha1.ModelAdapter{} - err = c.client.Patch(types.ApplyPatchType). - Namespace(c.ns). - Resource("modeladapters"). - Name(*name). - SubResource("status"). - VersionedParams(&patchOpts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/fake/fake_rayclusterfleet.go b/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/fake/fake_rayclusterfleet.go index 5a465016..5a150726 100644 --- a/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/fake/fake_rayclusterfleet.go +++ b/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/fake/fake_rayclusterfleet.go @@ -43,22 +43,24 @@ var rayclusterfleetsKind = v1alpha1.SchemeGroupVersion.WithKind("RayClusterFleet // Get takes name of the rayClusterFleet, and returns the corresponding rayClusterFleet object, and an error if there is any. func (c *FakeRayClusterFleets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.RayClusterFleet, err error) { + emptyResult := &v1alpha1.RayClusterFleet{} obj, err := c.Fake. - Invokes(testing.NewGetAction(rayclusterfleetsResource, c.ns, name), &v1alpha1.RayClusterFleet{}) + Invokes(testing.NewGetActionWithOptions(rayclusterfleetsResource, c.ns, name, options), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterFleet), err } // List takes label and field selectors, and returns the list of RayClusterFleets that match those selectors. func (c *FakeRayClusterFleets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.RayClusterFleetList, err error) { + emptyResult := &v1alpha1.RayClusterFleetList{} obj, err := c.Fake. - Invokes(testing.NewListAction(rayclusterfleetsResource, rayclusterfleetsKind, c.ns, opts), &v1alpha1.RayClusterFleetList{}) + Invokes(testing.NewListActionWithOptions(rayclusterfleetsResource, rayclusterfleetsKind, c.ns, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } label, _, _ := testing.ExtractFromListOptions(opts) @@ -77,40 +79,43 @@ func (c *FakeRayClusterFleets) List(ctx context.Context, opts v1.ListOptions) (r // Watch returns a watch.Interface that watches the requested rayClusterFleets. func (c *FakeRayClusterFleets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { return c.Fake. - InvokesWatch(testing.NewWatchAction(rayclusterfleetsResource, c.ns, opts)) + InvokesWatch(testing.NewWatchActionWithOptions(rayclusterfleetsResource, c.ns, opts)) } // Create takes the representation of a rayClusterFleet and creates it. Returns the server's representation of the rayClusterFleet, and an error, if there is any. func (c *FakeRayClusterFleets) Create(ctx context.Context, rayClusterFleet *v1alpha1.RayClusterFleet, opts v1.CreateOptions) (result *v1alpha1.RayClusterFleet, err error) { + emptyResult := &v1alpha1.RayClusterFleet{} obj, err := c.Fake. - Invokes(testing.NewCreateAction(rayclusterfleetsResource, c.ns, rayClusterFleet), &v1alpha1.RayClusterFleet{}) + Invokes(testing.NewCreateActionWithOptions(rayclusterfleetsResource, c.ns, rayClusterFleet, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterFleet), err } // Update takes the representation of a rayClusterFleet and updates it. Returns the server's representation of the rayClusterFleet, and an error, if there is any. func (c *FakeRayClusterFleets) Update(ctx context.Context, rayClusterFleet *v1alpha1.RayClusterFleet, opts v1.UpdateOptions) (result *v1alpha1.RayClusterFleet, err error) { + emptyResult := &v1alpha1.RayClusterFleet{} obj, err := c.Fake. - Invokes(testing.NewUpdateAction(rayclusterfleetsResource, c.ns, rayClusterFleet), &v1alpha1.RayClusterFleet{}) + Invokes(testing.NewUpdateActionWithOptions(rayclusterfleetsResource, c.ns, rayClusterFleet, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterFleet), 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 *FakeRayClusterFleets) UpdateStatus(ctx context.Context, rayClusterFleet *v1alpha1.RayClusterFleet, opts v1.UpdateOptions) (*v1alpha1.RayClusterFleet, error) { +func (c *FakeRayClusterFleets) UpdateStatus(ctx context.Context, rayClusterFleet *v1alpha1.RayClusterFleet, opts v1.UpdateOptions) (result *v1alpha1.RayClusterFleet, err error) { + emptyResult := &v1alpha1.RayClusterFleet{} obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(rayclusterfleetsResource, "status", c.ns, rayClusterFleet), &v1alpha1.RayClusterFleet{}) + Invokes(testing.NewUpdateSubresourceActionWithOptions(rayclusterfleetsResource, "status", c.ns, rayClusterFleet, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterFleet), err } @@ -125,7 +130,7 @@ func (c *FakeRayClusterFleets) Delete(ctx context.Context, name string, opts v1. // DeleteCollection deletes a collection of objects. func (c *FakeRayClusterFleets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(rayclusterfleetsResource, c.ns, listOpts) + action := testing.NewDeleteCollectionActionWithOptions(rayclusterfleetsResource, c.ns, opts, listOpts) _, err := c.Fake.Invokes(action, &v1alpha1.RayClusterFleetList{}) return err @@ -133,11 +138,12 @@ func (c *FakeRayClusterFleets) DeleteCollection(ctx context.Context, opts v1.Del // Patch applies the patch and returns the patched rayClusterFleet. func (c *FakeRayClusterFleets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.RayClusterFleet, err error) { + emptyResult := &v1alpha1.RayClusterFleet{} obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(rayclusterfleetsResource, c.ns, name, pt, data, subresources...), &v1alpha1.RayClusterFleet{}) + Invokes(testing.NewPatchSubresourceActionWithOptions(rayclusterfleetsResource, c.ns, name, pt, data, opts, subresources...), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterFleet), err } @@ -155,11 +161,12 @@ func (c *FakeRayClusterFleets) Apply(ctx context.Context, rayClusterFleet *orche if name == nil { return nil, fmt.Errorf("rayClusterFleet.Name must be provided to Apply") } + emptyResult := &v1alpha1.RayClusterFleet{} obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(rayclusterfleetsResource, c.ns, *name, types.ApplyPatchType, data), &v1alpha1.RayClusterFleet{}) + Invokes(testing.NewPatchSubresourceActionWithOptions(rayclusterfleetsResource, c.ns, *name, types.ApplyPatchType, data, opts.ToPatchOptions()), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterFleet), err } @@ -178,11 +185,12 @@ func (c *FakeRayClusterFleets) ApplyStatus(ctx context.Context, rayClusterFleet if name == nil { return nil, fmt.Errorf("rayClusterFleet.Name must be provided to Apply") } + emptyResult := &v1alpha1.RayClusterFleet{} obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(rayclusterfleetsResource, c.ns, *name, types.ApplyPatchType, data, "status"), &v1alpha1.RayClusterFleet{}) + Invokes(testing.NewPatchSubresourceActionWithOptions(rayclusterfleetsResource, c.ns, *name, types.ApplyPatchType, data, opts.ToPatchOptions(), "status"), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterFleet), err } diff --git a/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/fake/fake_rayclusterreplicaset.go b/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/fake/fake_rayclusterreplicaset.go index 7ef32888..cbb0225e 100644 --- a/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/fake/fake_rayclusterreplicaset.go +++ b/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/fake/fake_rayclusterreplicaset.go @@ -43,22 +43,24 @@ var rayclusterreplicasetsKind = v1alpha1.SchemeGroupVersion.WithKind("RayCluster // Get takes name of the rayClusterReplicaSet, and returns the corresponding rayClusterReplicaSet object, and an error if there is any. func (c *FakeRayClusterReplicaSets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.RayClusterReplicaSet, err error) { + emptyResult := &v1alpha1.RayClusterReplicaSet{} obj, err := c.Fake. - Invokes(testing.NewGetAction(rayclusterreplicasetsResource, c.ns, name), &v1alpha1.RayClusterReplicaSet{}) + Invokes(testing.NewGetActionWithOptions(rayclusterreplicasetsResource, c.ns, name, options), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterReplicaSet), err } // List takes label and field selectors, and returns the list of RayClusterReplicaSets that match those selectors. func (c *FakeRayClusterReplicaSets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.RayClusterReplicaSetList, err error) { + emptyResult := &v1alpha1.RayClusterReplicaSetList{} obj, err := c.Fake. - Invokes(testing.NewListAction(rayclusterreplicasetsResource, rayclusterreplicasetsKind, c.ns, opts), &v1alpha1.RayClusterReplicaSetList{}) + Invokes(testing.NewListActionWithOptions(rayclusterreplicasetsResource, rayclusterreplicasetsKind, c.ns, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } label, _, _ := testing.ExtractFromListOptions(opts) @@ -77,40 +79,43 @@ func (c *FakeRayClusterReplicaSets) List(ctx context.Context, opts v1.ListOption // Watch returns a watch.Interface that watches the requested rayClusterReplicaSets. func (c *FakeRayClusterReplicaSets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { return c.Fake. - InvokesWatch(testing.NewWatchAction(rayclusterreplicasetsResource, c.ns, opts)) + InvokesWatch(testing.NewWatchActionWithOptions(rayclusterreplicasetsResource, c.ns, opts)) } // Create takes the representation of a rayClusterReplicaSet and creates it. Returns the server's representation of the rayClusterReplicaSet, and an error, if there is any. func (c *FakeRayClusterReplicaSets) Create(ctx context.Context, rayClusterReplicaSet *v1alpha1.RayClusterReplicaSet, opts v1.CreateOptions) (result *v1alpha1.RayClusterReplicaSet, err error) { + emptyResult := &v1alpha1.RayClusterReplicaSet{} obj, err := c.Fake. - Invokes(testing.NewCreateAction(rayclusterreplicasetsResource, c.ns, rayClusterReplicaSet), &v1alpha1.RayClusterReplicaSet{}) + Invokes(testing.NewCreateActionWithOptions(rayclusterreplicasetsResource, c.ns, rayClusterReplicaSet, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterReplicaSet), err } // Update takes the representation of a rayClusterReplicaSet and updates it. Returns the server's representation of the rayClusterReplicaSet, and an error, if there is any. func (c *FakeRayClusterReplicaSets) Update(ctx context.Context, rayClusterReplicaSet *v1alpha1.RayClusterReplicaSet, opts v1.UpdateOptions) (result *v1alpha1.RayClusterReplicaSet, err error) { + emptyResult := &v1alpha1.RayClusterReplicaSet{} obj, err := c.Fake. - Invokes(testing.NewUpdateAction(rayclusterreplicasetsResource, c.ns, rayClusterReplicaSet), &v1alpha1.RayClusterReplicaSet{}) + Invokes(testing.NewUpdateActionWithOptions(rayclusterreplicasetsResource, c.ns, rayClusterReplicaSet, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterReplicaSet), 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 *FakeRayClusterReplicaSets) UpdateStatus(ctx context.Context, rayClusterReplicaSet *v1alpha1.RayClusterReplicaSet, opts v1.UpdateOptions) (*v1alpha1.RayClusterReplicaSet, error) { +func (c *FakeRayClusterReplicaSets) UpdateStatus(ctx context.Context, rayClusterReplicaSet *v1alpha1.RayClusterReplicaSet, opts v1.UpdateOptions) (result *v1alpha1.RayClusterReplicaSet, err error) { + emptyResult := &v1alpha1.RayClusterReplicaSet{} obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(rayclusterreplicasetsResource, "status", c.ns, rayClusterReplicaSet), &v1alpha1.RayClusterReplicaSet{}) + Invokes(testing.NewUpdateSubresourceActionWithOptions(rayclusterreplicasetsResource, "status", c.ns, rayClusterReplicaSet, opts), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterReplicaSet), err } @@ -125,7 +130,7 @@ func (c *FakeRayClusterReplicaSets) Delete(ctx context.Context, name string, opt // DeleteCollection deletes a collection of objects. func (c *FakeRayClusterReplicaSets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(rayclusterreplicasetsResource, c.ns, listOpts) + action := testing.NewDeleteCollectionActionWithOptions(rayclusterreplicasetsResource, c.ns, opts, listOpts) _, err := c.Fake.Invokes(action, &v1alpha1.RayClusterReplicaSetList{}) return err @@ -133,11 +138,12 @@ func (c *FakeRayClusterReplicaSets) DeleteCollection(ctx context.Context, opts v // Patch applies the patch and returns the patched rayClusterReplicaSet. func (c *FakeRayClusterReplicaSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.RayClusterReplicaSet, err error) { + emptyResult := &v1alpha1.RayClusterReplicaSet{} obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(rayclusterreplicasetsResource, c.ns, name, pt, data, subresources...), &v1alpha1.RayClusterReplicaSet{}) + Invokes(testing.NewPatchSubresourceActionWithOptions(rayclusterreplicasetsResource, c.ns, name, pt, data, opts, subresources...), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterReplicaSet), err } @@ -155,11 +161,12 @@ func (c *FakeRayClusterReplicaSets) Apply(ctx context.Context, rayClusterReplica if name == nil { return nil, fmt.Errorf("rayClusterReplicaSet.Name must be provided to Apply") } + emptyResult := &v1alpha1.RayClusterReplicaSet{} obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(rayclusterreplicasetsResource, c.ns, *name, types.ApplyPatchType, data), &v1alpha1.RayClusterReplicaSet{}) + Invokes(testing.NewPatchSubresourceActionWithOptions(rayclusterreplicasetsResource, c.ns, *name, types.ApplyPatchType, data, opts.ToPatchOptions()), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterReplicaSet), err } @@ -178,11 +185,12 @@ func (c *FakeRayClusterReplicaSets) ApplyStatus(ctx context.Context, rayClusterR if name == nil { return nil, fmt.Errorf("rayClusterReplicaSet.Name must be provided to Apply") } + emptyResult := &v1alpha1.RayClusterReplicaSet{} obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(rayclusterreplicasetsResource, c.ns, *name, types.ApplyPatchType, data, "status"), &v1alpha1.RayClusterReplicaSet{}) + Invokes(testing.NewPatchSubresourceActionWithOptions(rayclusterreplicasetsResource, c.ns, *name, types.ApplyPatchType, data, opts.ToPatchOptions(), "status"), emptyResult) if obj == nil { - return nil, err + return emptyResult, err } return obj.(*v1alpha1.RayClusterReplicaSet), err } diff --git a/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/rayclusterfleet.go b/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/rayclusterfleet.go index 4a3250d3..dbbf7a5a 100644 --- a/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/rayclusterfleet.go +++ b/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/rayclusterfleet.go @@ -19,9 +19,6 @@ package v1alpha1 import ( "context" - json "encoding/json" - "fmt" - "time" v1alpha1 "github.com/vllm-project/aibrix/api/orchestration/v1alpha1" orchestrationv1alpha1 "github.com/vllm-project/aibrix/pkg/client/applyconfiguration/orchestration/v1alpha1" @@ -29,7 +26,7 @@ import ( 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" + gentype "k8s.io/client-go/gentype" ) // RayClusterFleetsGetter has a method to return a RayClusterFleetInterface. @@ -42,6 +39,7 @@ type RayClusterFleetsGetter interface { type RayClusterFleetInterface interface { Create(ctx context.Context, rayClusterFleet *v1alpha1.RayClusterFleet, opts v1.CreateOptions) (*v1alpha1.RayClusterFleet, error) Update(ctx context.Context, rayClusterFleet *v1alpha1.RayClusterFleet, opts v1.UpdateOptions) (*v1alpha1.RayClusterFleet, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). UpdateStatus(ctx context.Context, rayClusterFleet *v1alpha1.RayClusterFleet, opts v1.UpdateOptions) (*v1alpha1.RayClusterFleet, error) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error @@ -50,206 +48,25 @@ type RayClusterFleetInterface interface { 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.RayClusterFleet, err error) Apply(ctx context.Context, rayClusterFleet *orchestrationv1alpha1.RayClusterFleetApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.RayClusterFleet, err error) + // Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). ApplyStatus(ctx context.Context, rayClusterFleet *orchestrationv1alpha1.RayClusterFleetApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.RayClusterFleet, err error) RayClusterFleetExpansion } // rayClusterFleets implements RayClusterFleetInterface type rayClusterFleets struct { - client rest.Interface - ns string + *gentype.ClientWithListAndApply[*v1alpha1.RayClusterFleet, *v1alpha1.RayClusterFleetList, *orchestrationv1alpha1.RayClusterFleetApplyConfiguration] } // newRayClusterFleets returns a RayClusterFleets func newRayClusterFleets(c *OrchestrationV1alpha1Client, namespace string) *rayClusterFleets { return &rayClusterFleets{ - client: c.RESTClient(), - ns: namespace, + gentype.NewClientWithListAndApply[*v1alpha1.RayClusterFleet, *v1alpha1.RayClusterFleetList, *orchestrationv1alpha1.RayClusterFleetApplyConfiguration]( + "rayclusterfleets", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *v1alpha1.RayClusterFleet { return &v1alpha1.RayClusterFleet{} }, + func() *v1alpha1.RayClusterFleetList { return &v1alpha1.RayClusterFleetList{} }), } } - -// Get takes name of the rayClusterFleet, and returns the corresponding rayClusterFleet object, and an error if there is any. -func (c *rayClusterFleets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.RayClusterFleet, err error) { - result = &v1alpha1.RayClusterFleet{} - err = c.client.Get(). - Namespace(c.ns). - Resource("rayclusterfleets"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of RayClusterFleets that match those selectors. -func (c *rayClusterFleets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.RayClusterFleetList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha1.RayClusterFleetList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("rayclusterfleets"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested rayClusterFleets. -func (c *rayClusterFleets) 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(). - Namespace(c.ns). - Resource("rayclusterfleets"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a rayClusterFleet and creates it. Returns the server's representation of the rayClusterFleet, and an error, if there is any. -func (c *rayClusterFleets) Create(ctx context.Context, rayClusterFleet *v1alpha1.RayClusterFleet, opts v1.CreateOptions) (result *v1alpha1.RayClusterFleet, err error) { - result = &v1alpha1.RayClusterFleet{} - err = c.client.Post(). - Namespace(c.ns). - Resource("rayclusterfleets"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(rayClusterFleet). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a rayClusterFleet and updates it. Returns the server's representation of the rayClusterFleet, and an error, if there is any. -func (c *rayClusterFleets) Update(ctx context.Context, rayClusterFleet *v1alpha1.RayClusterFleet, opts v1.UpdateOptions) (result *v1alpha1.RayClusterFleet, err error) { - result = &v1alpha1.RayClusterFleet{} - err = c.client.Put(). - Namespace(c.ns). - Resource("rayclusterfleets"). - Name(rayClusterFleet.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(rayClusterFleet). - 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 *rayClusterFleets) UpdateStatus(ctx context.Context, rayClusterFleet *v1alpha1.RayClusterFleet, opts v1.UpdateOptions) (result *v1alpha1.RayClusterFleet, err error) { - result = &v1alpha1.RayClusterFleet{} - err = c.client.Put(). - Namespace(c.ns). - Resource("rayclusterfleets"). - Name(rayClusterFleet.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(rayClusterFleet). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the rayClusterFleet and deletes it. Returns an error if one occurs. -func (c *rayClusterFleets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("rayclusterfleets"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *rayClusterFleets) 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(). - Namespace(c.ns). - Resource("rayclusterfleets"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched rayClusterFleet. -func (c *rayClusterFleets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.RayClusterFleet, err error) { - result = &v1alpha1.RayClusterFleet{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("rayclusterfleets"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} - -// Apply takes the given apply declarative configuration, applies it and returns the applied rayClusterFleet. -func (c *rayClusterFleets) Apply(ctx context.Context, rayClusterFleet *orchestrationv1alpha1.RayClusterFleetApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.RayClusterFleet, err error) { - if rayClusterFleet == nil { - return nil, fmt.Errorf("rayClusterFleet provided to Apply must not be nil") - } - patchOpts := opts.ToPatchOptions() - data, err := json.Marshal(rayClusterFleet) - if err != nil { - return nil, err - } - name := rayClusterFleet.Name - if name == nil { - return nil, fmt.Errorf("rayClusterFleet.Name must be provided to Apply") - } - result = &v1alpha1.RayClusterFleet{} - err = c.client.Patch(types.ApplyPatchType). - Namespace(c.ns). - Resource("rayclusterfleets"). - Name(*name). - VersionedParams(&patchOpts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} - -// ApplyStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). -func (c *rayClusterFleets) ApplyStatus(ctx context.Context, rayClusterFleet *orchestrationv1alpha1.RayClusterFleetApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.RayClusterFleet, err error) { - if rayClusterFleet == nil { - return nil, fmt.Errorf("rayClusterFleet provided to Apply must not be nil") - } - patchOpts := opts.ToPatchOptions() - data, err := json.Marshal(rayClusterFleet) - if err != nil { - return nil, err - } - - name := rayClusterFleet.Name - if name == nil { - return nil, fmt.Errorf("rayClusterFleet.Name must be provided to Apply") - } - - result = &v1alpha1.RayClusterFleet{} - err = c.client.Patch(types.ApplyPatchType). - Namespace(c.ns). - Resource("rayclusterfleets"). - Name(*name). - SubResource("status"). - VersionedParams(&patchOpts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/rayclusterreplicaset.go b/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/rayclusterreplicaset.go index ae434681..77dda332 100644 --- a/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/rayclusterreplicaset.go +++ b/pkg/client/clientset/versioned/typed/orchestration/v1alpha1/rayclusterreplicaset.go @@ -19,9 +19,6 @@ package v1alpha1 import ( "context" - json "encoding/json" - "fmt" - "time" v1alpha1 "github.com/vllm-project/aibrix/api/orchestration/v1alpha1" orchestrationv1alpha1 "github.com/vllm-project/aibrix/pkg/client/applyconfiguration/orchestration/v1alpha1" @@ -29,7 +26,7 @@ import ( 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" + gentype "k8s.io/client-go/gentype" ) // RayClusterReplicaSetsGetter has a method to return a RayClusterReplicaSetInterface. @@ -42,6 +39,7 @@ type RayClusterReplicaSetsGetter interface { type RayClusterReplicaSetInterface interface { Create(ctx context.Context, rayClusterReplicaSet *v1alpha1.RayClusterReplicaSet, opts v1.CreateOptions) (*v1alpha1.RayClusterReplicaSet, error) Update(ctx context.Context, rayClusterReplicaSet *v1alpha1.RayClusterReplicaSet, opts v1.UpdateOptions) (*v1alpha1.RayClusterReplicaSet, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). UpdateStatus(ctx context.Context, rayClusterReplicaSet *v1alpha1.RayClusterReplicaSet, opts v1.UpdateOptions) (*v1alpha1.RayClusterReplicaSet, error) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error @@ -50,206 +48,25 @@ type RayClusterReplicaSetInterface interface { 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.RayClusterReplicaSet, err error) Apply(ctx context.Context, rayClusterReplicaSet *orchestrationv1alpha1.RayClusterReplicaSetApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.RayClusterReplicaSet, err error) + // Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). ApplyStatus(ctx context.Context, rayClusterReplicaSet *orchestrationv1alpha1.RayClusterReplicaSetApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.RayClusterReplicaSet, err error) RayClusterReplicaSetExpansion } // rayClusterReplicaSets implements RayClusterReplicaSetInterface type rayClusterReplicaSets struct { - client rest.Interface - ns string + *gentype.ClientWithListAndApply[*v1alpha1.RayClusterReplicaSet, *v1alpha1.RayClusterReplicaSetList, *orchestrationv1alpha1.RayClusterReplicaSetApplyConfiguration] } // newRayClusterReplicaSets returns a RayClusterReplicaSets func newRayClusterReplicaSets(c *OrchestrationV1alpha1Client, namespace string) *rayClusterReplicaSets { return &rayClusterReplicaSets{ - client: c.RESTClient(), - ns: namespace, + gentype.NewClientWithListAndApply[*v1alpha1.RayClusterReplicaSet, *v1alpha1.RayClusterReplicaSetList, *orchestrationv1alpha1.RayClusterReplicaSetApplyConfiguration]( + "rayclusterreplicasets", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *v1alpha1.RayClusterReplicaSet { return &v1alpha1.RayClusterReplicaSet{} }, + func() *v1alpha1.RayClusterReplicaSetList { return &v1alpha1.RayClusterReplicaSetList{} }), } } - -// Get takes name of the rayClusterReplicaSet, and returns the corresponding rayClusterReplicaSet object, and an error if there is any. -func (c *rayClusterReplicaSets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.RayClusterReplicaSet, err error) { - result = &v1alpha1.RayClusterReplicaSet{} - err = c.client.Get(). - Namespace(c.ns). - Resource("rayclusterreplicasets"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of RayClusterReplicaSets that match those selectors. -func (c *rayClusterReplicaSets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.RayClusterReplicaSetList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha1.RayClusterReplicaSetList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("rayclusterreplicasets"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested rayClusterReplicaSets. -func (c *rayClusterReplicaSets) 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(). - Namespace(c.ns). - Resource("rayclusterreplicasets"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a rayClusterReplicaSet and creates it. Returns the server's representation of the rayClusterReplicaSet, and an error, if there is any. -func (c *rayClusterReplicaSets) Create(ctx context.Context, rayClusterReplicaSet *v1alpha1.RayClusterReplicaSet, opts v1.CreateOptions) (result *v1alpha1.RayClusterReplicaSet, err error) { - result = &v1alpha1.RayClusterReplicaSet{} - err = c.client.Post(). - Namespace(c.ns). - Resource("rayclusterreplicasets"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(rayClusterReplicaSet). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a rayClusterReplicaSet and updates it. Returns the server's representation of the rayClusterReplicaSet, and an error, if there is any. -func (c *rayClusterReplicaSets) Update(ctx context.Context, rayClusterReplicaSet *v1alpha1.RayClusterReplicaSet, opts v1.UpdateOptions) (result *v1alpha1.RayClusterReplicaSet, err error) { - result = &v1alpha1.RayClusterReplicaSet{} - err = c.client.Put(). - Namespace(c.ns). - Resource("rayclusterreplicasets"). - Name(rayClusterReplicaSet.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(rayClusterReplicaSet). - 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 *rayClusterReplicaSets) UpdateStatus(ctx context.Context, rayClusterReplicaSet *v1alpha1.RayClusterReplicaSet, opts v1.UpdateOptions) (result *v1alpha1.RayClusterReplicaSet, err error) { - result = &v1alpha1.RayClusterReplicaSet{} - err = c.client.Put(). - Namespace(c.ns). - Resource("rayclusterreplicasets"). - Name(rayClusterReplicaSet.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(rayClusterReplicaSet). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the rayClusterReplicaSet and deletes it. Returns an error if one occurs. -func (c *rayClusterReplicaSets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("rayclusterreplicasets"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *rayClusterReplicaSets) 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(). - Namespace(c.ns). - Resource("rayclusterreplicasets"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched rayClusterReplicaSet. -func (c *rayClusterReplicaSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.RayClusterReplicaSet, err error) { - result = &v1alpha1.RayClusterReplicaSet{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("rayclusterreplicasets"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} - -// Apply takes the given apply declarative configuration, applies it and returns the applied rayClusterReplicaSet. -func (c *rayClusterReplicaSets) Apply(ctx context.Context, rayClusterReplicaSet *orchestrationv1alpha1.RayClusterReplicaSetApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.RayClusterReplicaSet, err error) { - if rayClusterReplicaSet == nil { - return nil, fmt.Errorf("rayClusterReplicaSet provided to Apply must not be nil") - } - patchOpts := opts.ToPatchOptions() - data, err := json.Marshal(rayClusterReplicaSet) - if err != nil { - return nil, err - } - name := rayClusterReplicaSet.Name - if name == nil { - return nil, fmt.Errorf("rayClusterReplicaSet.Name must be provided to Apply") - } - result = &v1alpha1.RayClusterReplicaSet{} - err = c.client.Patch(types.ApplyPatchType). - Namespace(c.ns). - Resource("rayclusterreplicasets"). - Name(*name). - VersionedParams(&patchOpts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} - -// ApplyStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). -func (c *rayClusterReplicaSets) ApplyStatus(ctx context.Context, rayClusterReplicaSet *orchestrationv1alpha1.RayClusterReplicaSetApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.RayClusterReplicaSet, err error) { - if rayClusterReplicaSet == nil { - return nil, fmt.Errorf("rayClusterReplicaSet provided to Apply must not be nil") - } - patchOpts := opts.ToPatchOptions() - data, err := json.Marshal(rayClusterReplicaSet) - if err != nil { - return nil, err - } - - name := rayClusterReplicaSet.Name - if name == nil { - return nil, fmt.Errorf("rayClusterReplicaSet.Name must be provided to Apply") - } - - result = &v1alpha1.RayClusterReplicaSet{} - err = c.client.Patch(types.ApplyPatchType). - Namespace(c.ns). - Resource("rayclusterreplicasets"). - Name(*name). - SubResource("status"). - VersionedParams(&patchOpts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go index 98dcbfb6..8847c99b 100644 --- a/pkg/client/informers/externalversions/factory.go +++ b/pkg/client/informers/externalversions/factory.go @@ -229,6 +229,7 @@ type SharedInformerFactory interface { // Start initializes all requested informers. They are handled in goroutines // which run until the stop channel gets closed. + // Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync. Start(stopCh <-chan struct{}) // Shutdown marks a factory as shutting down. At that point no new diff --git a/pkg/client/listers/autoscaling/v1alpha1/podautoscaler.go b/pkg/client/listers/autoscaling/v1alpha1/podautoscaler.go index df223f5c..f44b3cc9 100644 --- a/pkg/client/listers/autoscaling/v1alpha1/podautoscaler.go +++ b/pkg/client/listers/autoscaling/v1alpha1/podautoscaler.go @@ -19,8 +19,8 @@ package v1alpha1 import ( v1alpha1 "github.com/vllm-project/aibrix/api/autoscaling/v1alpha1" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/listers" "k8s.io/client-go/tools/cache" ) @@ -37,25 +37,17 @@ type PodAutoscalerLister interface { // podAutoscalerLister implements the PodAutoscalerLister interface. type podAutoscalerLister struct { - indexer cache.Indexer + listers.ResourceIndexer[*v1alpha1.PodAutoscaler] } // NewPodAutoscalerLister returns a new PodAutoscalerLister. func NewPodAutoscalerLister(indexer cache.Indexer) PodAutoscalerLister { - return &podAutoscalerLister{indexer: indexer} -} - -// List lists all PodAutoscalers in the indexer. -func (s *podAutoscalerLister) List(selector labels.Selector) (ret []*v1alpha1.PodAutoscaler, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.PodAutoscaler)) - }) - return ret, err + return &podAutoscalerLister{listers.New[*v1alpha1.PodAutoscaler](indexer, v1alpha1.Resource("podautoscaler"))} } // PodAutoscalers returns an object that can list and get PodAutoscalers. func (s *podAutoscalerLister) PodAutoscalers(namespace string) PodAutoscalerNamespaceLister { - return podAutoscalerNamespaceLister{indexer: s.indexer, namespace: namespace} + return podAutoscalerNamespaceLister{listers.NewNamespaced[*v1alpha1.PodAutoscaler](s.ResourceIndexer, namespace)} } // PodAutoscalerNamespaceLister helps list and get PodAutoscalers. @@ -73,26 +65,5 @@ type PodAutoscalerNamespaceLister interface { // podAutoscalerNamespaceLister implements the PodAutoscalerNamespaceLister // interface. type podAutoscalerNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all PodAutoscalers in the indexer for a given namespace. -func (s podAutoscalerNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.PodAutoscaler, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.PodAutoscaler)) - }) - return ret, err -} - -// Get retrieves the PodAutoscaler from the indexer for a given namespace and name. -func (s podAutoscalerNamespaceLister) Get(name string) (*v1alpha1.PodAutoscaler, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("podautoscaler"), name) - } - return obj.(*v1alpha1.PodAutoscaler), nil + listers.ResourceIndexer[*v1alpha1.PodAutoscaler] } diff --git a/pkg/client/listers/model/v1alpha1/modeladapter.go b/pkg/client/listers/model/v1alpha1/modeladapter.go index cacd9782..8e725735 100644 --- a/pkg/client/listers/model/v1alpha1/modeladapter.go +++ b/pkg/client/listers/model/v1alpha1/modeladapter.go @@ -19,8 +19,8 @@ package v1alpha1 import ( v1alpha1 "github.com/vllm-project/aibrix/api/model/v1alpha1" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/listers" "k8s.io/client-go/tools/cache" ) @@ -37,25 +37,17 @@ type ModelAdapterLister interface { // modelAdapterLister implements the ModelAdapterLister interface. type modelAdapterLister struct { - indexer cache.Indexer + listers.ResourceIndexer[*v1alpha1.ModelAdapter] } // NewModelAdapterLister returns a new ModelAdapterLister. func NewModelAdapterLister(indexer cache.Indexer) ModelAdapterLister { - return &modelAdapterLister{indexer: indexer} -} - -// List lists all ModelAdapters in the indexer. -func (s *modelAdapterLister) List(selector labels.Selector) (ret []*v1alpha1.ModelAdapter, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.ModelAdapter)) - }) - return ret, err + return &modelAdapterLister{listers.New[*v1alpha1.ModelAdapter](indexer, v1alpha1.Resource("modeladapter"))} } // ModelAdapters returns an object that can list and get ModelAdapters. func (s *modelAdapterLister) ModelAdapters(namespace string) ModelAdapterNamespaceLister { - return modelAdapterNamespaceLister{indexer: s.indexer, namespace: namespace} + return modelAdapterNamespaceLister{listers.NewNamespaced[*v1alpha1.ModelAdapter](s.ResourceIndexer, namespace)} } // ModelAdapterNamespaceLister helps list and get ModelAdapters. @@ -73,26 +65,5 @@ type ModelAdapterNamespaceLister interface { // modelAdapterNamespaceLister implements the ModelAdapterNamespaceLister // interface. type modelAdapterNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all ModelAdapters in the indexer for a given namespace. -func (s modelAdapterNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ModelAdapter, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.ModelAdapter)) - }) - return ret, err -} - -// Get retrieves the ModelAdapter from the indexer for a given namespace and name. -func (s modelAdapterNamespaceLister) Get(name string) (*v1alpha1.ModelAdapter, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("modeladapter"), name) - } - return obj.(*v1alpha1.ModelAdapter), nil + listers.ResourceIndexer[*v1alpha1.ModelAdapter] } diff --git a/pkg/client/listers/orchestration/v1alpha1/rayclusterfleet.go b/pkg/client/listers/orchestration/v1alpha1/rayclusterfleet.go index f01d4851..07f7d3df 100644 --- a/pkg/client/listers/orchestration/v1alpha1/rayclusterfleet.go +++ b/pkg/client/listers/orchestration/v1alpha1/rayclusterfleet.go @@ -19,8 +19,8 @@ package v1alpha1 import ( v1alpha1 "github.com/vllm-project/aibrix/api/orchestration/v1alpha1" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/listers" "k8s.io/client-go/tools/cache" ) @@ -37,25 +37,17 @@ type RayClusterFleetLister interface { // rayClusterFleetLister implements the RayClusterFleetLister interface. type rayClusterFleetLister struct { - indexer cache.Indexer + listers.ResourceIndexer[*v1alpha1.RayClusterFleet] } // NewRayClusterFleetLister returns a new RayClusterFleetLister. func NewRayClusterFleetLister(indexer cache.Indexer) RayClusterFleetLister { - return &rayClusterFleetLister{indexer: indexer} -} - -// List lists all RayClusterFleets in the indexer. -func (s *rayClusterFleetLister) List(selector labels.Selector) (ret []*v1alpha1.RayClusterFleet, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.RayClusterFleet)) - }) - return ret, err + return &rayClusterFleetLister{listers.New[*v1alpha1.RayClusterFleet](indexer, v1alpha1.Resource("rayclusterfleet"))} } // RayClusterFleets returns an object that can list and get RayClusterFleets. func (s *rayClusterFleetLister) RayClusterFleets(namespace string) RayClusterFleetNamespaceLister { - return rayClusterFleetNamespaceLister{indexer: s.indexer, namespace: namespace} + return rayClusterFleetNamespaceLister{listers.NewNamespaced[*v1alpha1.RayClusterFleet](s.ResourceIndexer, namespace)} } // RayClusterFleetNamespaceLister helps list and get RayClusterFleets. @@ -73,26 +65,5 @@ type RayClusterFleetNamespaceLister interface { // rayClusterFleetNamespaceLister implements the RayClusterFleetNamespaceLister // interface. type rayClusterFleetNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all RayClusterFleets in the indexer for a given namespace. -func (s rayClusterFleetNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.RayClusterFleet, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.RayClusterFleet)) - }) - return ret, err -} - -// Get retrieves the RayClusterFleet from the indexer for a given namespace and name. -func (s rayClusterFleetNamespaceLister) Get(name string) (*v1alpha1.RayClusterFleet, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("rayclusterfleet"), name) - } - return obj.(*v1alpha1.RayClusterFleet), nil + listers.ResourceIndexer[*v1alpha1.RayClusterFleet] } diff --git a/pkg/client/listers/orchestration/v1alpha1/rayclusterreplicaset.go b/pkg/client/listers/orchestration/v1alpha1/rayclusterreplicaset.go index 3447097f..539a9fa2 100644 --- a/pkg/client/listers/orchestration/v1alpha1/rayclusterreplicaset.go +++ b/pkg/client/listers/orchestration/v1alpha1/rayclusterreplicaset.go @@ -19,8 +19,8 @@ package v1alpha1 import ( v1alpha1 "github.com/vllm-project/aibrix/api/orchestration/v1alpha1" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/listers" "k8s.io/client-go/tools/cache" ) @@ -37,25 +37,17 @@ type RayClusterReplicaSetLister interface { // rayClusterReplicaSetLister implements the RayClusterReplicaSetLister interface. type rayClusterReplicaSetLister struct { - indexer cache.Indexer + listers.ResourceIndexer[*v1alpha1.RayClusterReplicaSet] } // NewRayClusterReplicaSetLister returns a new RayClusterReplicaSetLister. func NewRayClusterReplicaSetLister(indexer cache.Indexer) RayClusterReplicaSetLister { - return &rayClusterReplicaSetLister{indexer: indexer} -} - -// List lists all RayClusterReplicaSets in the indexer. -func (s *rayClusterReplicaSetLister) List(selector labels.Selector) (ret []*v1alpha1.RayClusterReplicaSet, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.RayClusterReplicaSet)) - }) - return ret, err + return &rayClusterReplicaSetLister{listers.New[*v1alpha1.RayClusterReplicaSet](indexer, v1alpha1.Resource("rayclusterreplicaset"))} } // RayClusterReplicaSets returns an object that can list and get RayClusterReplicaSets. func (s *rayClusterReplicaSetLister) RayClusterReplicaSets(namespace string) RayClusterReplicaSetNamespaceLister { - return rayClusterReplicaSetNamespaceLister{indexer: s.indexer, namespace: namespace} + return rayClusterReplicaSetNamespaceLister{listers.NewNamespaced[*v1alpha1.RayClusterReplicaSet](s.ResourceIndexer, namespace)} } // RayClusterReplicaSetNamespaceLister helps list and get RayClusterReplicaSets. @@ -73,26 +65,5 @@ type RayClusterReplicaSetNamespaceLister interface { // rayClusterReplicaSetNamespaceLister implements the RayClusterReplicaSetNamespaceLister // interface. type rayClusterReplicaSetNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all RayClusterReplicaSets in the indexer for a given namespace. -func (s rayClusterReplicaSetNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.RayClusterReplicaSet, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.RayClusterReplicaSet)) - }) - return ret, err -} - -// Get retrieves the RayClusterReplicaSet from the indexer for a given namespace and name. -func (s rayClusterReplicaSetNamespaceLister) Get(name string) (*v1alpha1.RayClusterReplicaSet, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("rayclusterreplicaset"), name) - } - return obj.(*v1alpha1.RayClusterReplicaSet), nil + listers.ResourceIndexer[*v1alpha1.RayClusterReplicaSet] } diff --git a/pkg/controller/podautoscaler/podautoscaler_controller.go b/pkg/controller/podautoscaler/podautoscaler_controller.go index 2e455a48..2c1e24d7 100644 --- a/pkg/controller/podautoscaler/podautoscaler_controller.go +++ b/pkg/controller/podautoscaler/podautoscaler_controller.go @@ -114,16 +114,14 @@ func filterHPAObject(ctx context.Context, object client.Object) []reconcile.Requ func add(mgr manager.Manager, r reconcile.Reconciler) error { // Build raw source for periodical requeue events from event channel reconciler := r.(*PodAutoscalerReconciler) - src := &source.Channel{ - Source: reconciler.eventCh, - } + src := source.Channel(reconciler.eventCh, &handler.EnqueueRequestForObject{}) // Create a new controller managed by AIBrix manager, watching for changes to PodAutoscaler objects // and HorizontalPodAutoscaler objects. err := ctrl.NewControllerManagedBy(mgr). For(&autoscalingv1alpha1.PodAutoscaler{}). Watches(&autoscalingv2.HorizontalPodAutoscaler{}, handler.EnqueueRequestsFromMapFunc(filterHPAObject)). - WatchesRawSource(src, &handler.EnqueueRequestForObject{}). + WatchesRawSource(src). Complete(r) klog.InfoS("Added AIBrix pod-autoscaler-controller successfully") diff --git a/pkg/plugins/gateway/algorithms/prefix_cache_and_load.go b/pkg/plugins/gateway/algorithms/prefix_cache_and_load.go index 76042d57..847d191d 100644 --- a/pkg/plugins/gateway/algorithms/prefix_cache_and_load.go +++ b/pkg/plugins/gateway/algorithms/prefix_cache_and_load.go @@ -222,7 +222,7 @@ func (h *SlidingWindowHistogram) getPrefillCost(node *prefixcacheindexer.TreeNod attnQuad = calculateAttnQuadV100(numTokens, nil) } prefillTime := (baseTime + attnQuad) / 0.9 - numPods := len(node.ModelToPods) // You might need to adjust this based on your actual GPU allocation tracking + numPods := node.GetModelToPodCount() // You might need to adjust this based on your actual GPU allocation tracking klog.Infof("numTokens: %d, contextLength: %d, targetGPU: %s", numTokens, contextLength, targetGPU) klog.Infof("prefillTime: %.2f = (Base time(%.2f) + attnQuad(%.2f)) / 0.9", prefillTime, baseTime, attnQuad) totalPrefillCost := missRate * float64(h.nodeToCount[node]) * prefillTime / float64(numPods) @@ -298,22 +298,18 @@ func (h *SlidingWindowHistogram) removeEvictedNodes(nodes []*prefixcacheindexer. func (h *SlidingWindowHistogram) removeOldEntries(currentTime time.Time) { h.mu.Lock() defer h.mu.Unlock() - windowStart := currentTime.Add(-h.windowDuration) newTimestamps := make([]histogramEntry, 0) - for _, entry := range h.timestamps { if entry.timestamp.After(windowStart) { newTimestamps = append(newTimestamps, entry) } else { node := entry.node leafNode := entry.leafNode - h.histogram[node] -= leafNode.ContextLength() h.nodeToCount[node]-- h.hitTokens[node] -= leafNode.ContextLength() - leafNode.NumTokens() h.promptTokens[node] -= leafNode.ContextLength() - if h.histogram[node] <= 0 { delete(h.histogram, node) delete(h.nodeToCount, node) @@ -368,7 +364,7 @@ func (h *SlidingWindowHistogram) getCurrentAllocationCostPerPod() map[string]flo costs := make(map[string]float64) for node := range h.histogram { // Iterate through all models and their pods for this node - for _, modelPods := range node.ModelToPods { + for _, modelPods := range node.GetModelToPods() { for podName := range modelPods { costs[podName] += h.getNodeCost(node, podName) } @@ -387,21 +383,13 @@ func (p *prefixCacheAndLoadRouter) updatePodSet(readyPods []*v1.Pod) { // Update cache structures for _, node := range allNodes { // 1. Update ModelToPods - for model, podMap := range node.ModelToPods { - for podName := range podMap { - if !currentPodSet[podName] { - delete(podMap, podName) - podsChanged = true - } - } - if len(podMap) == 0 { - delete(node.ModelToPods, model) - } + if node.RemovePodsNotInSet(currentPodSet) { + podsChanged = true } // 2. Update node's pod-specific data structures - node.EvictedPods = make(map[int]bool) // Reset as pod IDs might change - node.CachedPods = make(map[int]bool) // Reset as pod IDs might change - node.RefCounter = make([]int, len(currentPodSet)) // Resize for new pod count + node.ResetEvictedPods() // Reset as pod IDs might change + node.ResetCachedPods() // Reset as pod IDs might change + node.ResetRefCounter(len(currentPodSet)) // Resize for new pod count } // Update router and histogram if pods changed @@ -440,7 +428,10 @@ func (p *prefixCacheAndLoadRouter) updatePodSet(readyPods []*v1.Pod) { // Filter timestamps entries for nodes that still have valid pods newTimestamps := make([]histogramEntry, 0) for _, entry := range h.timestamps { - if hasValidPods(entry.node, currentPodSet) { + if entry.node == nil { + continue + } + if entry.node.HasValidPods(currentPodSet) { newTimestamps = append(newTimestamps, entry) } } @@ -448,18 +439,6 @@ func (p *prefixCacheAndLoadRouter) updatePodSet(readyPods []*v1.Pod) { } } -// Helper function to check if a node has any valid pods -func hasValidPods(node *prefixcacheindexer.TreeNode, currentPodSet map[string]bool) bool { - for _, podMap := range node.ModelToPods { - for podName := range podMap { - if currentPodSet[podName] { - return true - } - } - } - return false -} - func (p *prefixCacheAndLoadRouter) Route(ctx context.Context, pods map[string]*v1.Pod, model, message string) (string, error) { readyPods := utils.FilterReadyPods(pods) if len(readyPods) == 0 { @@ -489,7 +468,7 @@ func (p *prefixCacheAndLoadRouter) Route(ctx context.Context, pods map[string]*v node, matchedTokens, _ := p.cache.AddPrefix(tokens, model, "") var matchedPods []*v1.Pod var matchedPodsNames []string - if modelPods, ok := node.ModelToPods[model]; ok { + if modelPods, ok := node.GetModelToPods()[model]; ok { klog.Infof("node.ModelToPods[model]: %v", modelPods) for podName := range modelPods { for _, pod := range readyPods { @@ -514,7 +493,7 @@ func (p *prefixCacheAndLoadRouter) Route(ctx context.Context, pods map[string]*v currentNode := node for currentNode != nil { - if modelPods, ok := currentNode.ModelToPods[model]; ok { + if modelPods, ok := currentNode.GetModelToPods()[model]; ok { var nodePods []*v1.Pod for podName := range modelPods { for _, pod := range readyPods { @@ -586,13 +565,7 @@ func (p *prefixCacheAndLoadRouter) Route(ctx context.Context, pods map[string]*v // Update pod mapping in ALL nodes from matched node to root currentNode := node for currentNode != nil { - if modelPods, ok := currentNode.ModelToPods[model]; !ok { - currentNode.ModelToPods[model] = map[string]time.Time{ - targetPod.Name: time.Now(), - } - } else { - modelPods[targetPod.Name] = time.Now() - } + currentNode.AddOrUpdatePodForModel(model, targetPod.Name, time.Now()) currentNode = currentNode.GetParent() } @@ -609,7 +582,7 @@ func (h *SlidingWindowHistogram) getPodLoad(pod *v1.Pod) int { defer h.mu.RUnlock() load := 0 for node, count := range h.nodeToCount { - for _, podMap := range node.ModelToPods { + for _, podMap := range node.GetModelToPods() { if _, exists := podMap[pod.Name]; exists { load += count break // Found this pod in this node, no need to check other models diff --git a/pkg/plugins/gateway/prefixcacheindexer/hash.go b/pkg/plugins/gateway/prefixcacheindexer/hash.go index cbac85e4..18b33216 100644 --- a/pkg/plugins/gateway/prefixcacheindexer/hash.go +++ b/pkg/plugins/gateway/prefixcacheindexer/hash.go @@ -19,11 +19,12 @@ package prefixcacheindexer import ( "bytes" "encoding/binary" + "math/rand" "strconv" "sync" "time" - "github.com/cespare/xxhash" + "github.com/cespare/xxhash/v2" "github.com/vllm-project/aibrix/pkg/utils" v1 "k8s.io/api/core/v1" "k8s.io/klog/v2" @@ -90,6 +91,8 @@ func getPrefixCacheEvictionDuration() time.Duration { type PrefixHashTable struct { mu sync.RWMutex blocks map[uint64]Block + hash *xxhash.Digest + seed uint64 } type Block struct { @@ -98,8 +101,12 @@ type Block struct { } func NewPrefixHashTable() PrefixCacheIndexer { + r := rand.New(rand.NewSource(time.Now().Unix())) + seed := r.Uint64() instance := &PrefixHashTable{ blocks: map[uint64]Block{}, + hash: xxhash.NewWithSeed(seed), + seed: seed, } ticker := time.NewTicker(prefixCacheEvictionInterval) @@ -128,7 +135,9 @@ func (c *PrefixHashTable) MatchPrefix(tokens []int, model string, pods []*v1.Pod } chunk := tokens[i:end] - prefixHash := xxhash.Sum64(IntArrayToByteArray(chunk)) + _, _ = c.hash.Write(IntArrayToByteArray(chunk)) + prefixHash := c.hash.Sum64() + c.hash.ResetWithSeed(c.seed) block, ok = c.blocks[prefixHash] if !ok || len(block.modelToPods[model]) == 0 { lastTokenMatchIndex = i @@ -166,7 +175,9 @@ func (c *PrefixHashTable) AddPrefix(unMatchedTokens []int, model, pod string) { } chunk := unMatchedTokens[i:end] - prefixHash := xxhash.Sum64(IntArrayToByteArray(chunk)) + _, _ = c.hash.Write(IntArrayToByteArray(chunk)) + prefixHash := c.hash.Sum64() + c.hash.ResetWithSeed(c.seed) block, ok := c.blocks[prefixHash] if !ok { block = Block{ diff --git a/pkg/plugins/gateway/prefixcacheindexer/hash_test.go b/pkg/plugins/gateway/prefixcacheindexer/hash_test.go index 64cbe16f..e9f2f0bd 100644 --- a/pkg/plugins/gateway/prefixcacheindexer/hash_test.go +++ b/pkg/plugins/gateway/prefixcacheindexer/hash_test.go @@ -18,9 +18,11 @@ package prefixcacheindexer import ( "fmt" + "math/rand" "testing" "time" + "github.com/cespare/xxhash/v2" "github.com/stretchr/testify/assert" "github.com/vllm-project/aibrix/pkg/utils" v1 "k8s.io/api/core/v1" @@ -28,8 +30,12 @@ import ( ) func Test_PrefixHashTableE2E(t *testing.T) { + r := rand.New(rand.NewSource(time.Now().Unix())) + seed := r.Uint64() cache := PrefixHashTable{ blocks: map[uint64]Block{}, + hash: xxhash.NewWithSeed(seed), + seed: seed, } pods := []*v1.Pod{ {ObjectMeta: metav1.ObjectMeta{Name: "p1"}}, @@ -64,6 +70,8 @@ func Test_PrefixHashTableE2E(t *testing.T) { } func Test_MatchPrefix(t *testing.T) { + r := rand.New(rand.NewSource(time.Now().Unix())) + seed := r.Uint64() tests := []*struct { name string inputText string @@ -79,6 +87,8 @@ func Test_MatchPrefix(t *testing.T) { inputText: "Hello World! What a Good Day! 你好世界!多么美好的一天啊!", cache: PrefixHashTable{ blocks: map[uint64]Block{}, + hash: xxhash.NewWithSeed(seed), + seed: seed, }, model: "m1", pods: []*v1.Pod{ @@ -103,6 +113,8 @@ func Test_MatchPrefix(t *testing.T) { lastAccessTime: time.Now(), }, }, + hash: xxhash.NewWithSeed(0), + seed: 0, }, model: "m1", pods: []*v1.Pod{ diff --git a/pkg/plugins/gateway/prefixcacheindexer/tree.go b/pkg/plugins/gateway/prefixcacheindexer/tree.go index 428dd1d3..2fc8ba5d 100644 --- a/pkg/plugins/gateway/prefixcacheindexer/tree.go +++ b/pkg/plugins/gateway/prefixcacheindexer/tree.go @@ -32,20 +32,60 @@ const ( ) type TreeNode struct { + mu sync.RWMutex // Add mutex for thread safety id int children map[int]*TreeNode parent *TreeNode value []int key []int - RefCounter []int + refCounter []int load int lastAccess time.Time - EvictedPods map[int]bool - CachedPods map[int]bool + evictedPods map[int]bool + cachedPods map[int]bool isLeaf bool contextLength int // total length from root to this node depth int - ModelToPods map[string]map[string]time.Time // model -> {podName -> lastAccessTime} + modelToPods map[string]map[string]time.Time // model -> {podName -> lastAccessTime} +} + +func (n *TreeNode) GetModelToPods() map[string]map[string]time.Time { + n.mu.RLock() + defer n.mu.RUnlock() + return n.modelToPods +} + +func (n *TreeNode) InitAndUpdateModelPod(model string, podName string, timestamp time.Time) { + n.mu.Lock() + defer n.mu.Unlock() + + if n.modelToPods == nil { + n.modelToPods = make(map[string]map[string]time.Time) + } + if n.modelToPods[model] == nil { + n.modelToPods[model] = make(map[string]time.Time) + } + n.modelToPods[model][podName] = timestamp +} + +func (n *TreeNode) GetRefCounter() []int { + return n.refCounter +} + +func (n *TreeNode) GetLoad() int { + return n.load +} + +func (n *TreeNode) GetLastAccess() time.Time { + return n.lastAccess +} + +func (n *TreeNode) GetEvictedPods() map[int]bool { + return n.evictedPods +} + +func (n *TreeNode) GetCachedPods() map[int]bool { + return n.cachedPods } func (n *TreeNode) GetParent() *TreeNode { @@ -72,6 +112,113 @@ func (n *TreeNode) GetDepth() int { return n.depth } +func (n *TreeNode) GetID() int { + return n.id +} + +func (n *TreeNode) GetChildren() map[int]*TreeNode { + return n.children +} + +func (n *TreeNode) ResetEvictedPods() { + n.evictedPods = make(map[int]bool) +} + +func (n *TreeNode) ResetCachedPods() { + n.cachedPods = make(map[int]bool) +} + +func (n *TreeNode) ResetRefCounter(numPods int) { + n.refCounter = make([]int, numPods) +} + +func (n *TreeNode) RemovePodsNotInCurrentPodSet(currentPodSet map[string]bool) bool { + n.mu.Lock() + defer n.mu.Unlock() + podsChanged := false + for model, podMap := range n.modelToPods { + for podName := range podMap { + if !currentPodSet[podName] { + delete(podMap, podName) + podsChanged = true + } + } + if len(podMap) == 0 { + delete(n.modelToPods, model) + } + } + return podsChanged +} + +func (n *TreeNode) HasPodForModel(model, podName string) bool { + n.mu.RLock() + defer n.mu.RUnlock() + pods, ok := n.modelToPods[model] + if !ok { + return false + } + _, exists := pods[podName] + return exists +} + +func (n *TreeNode) HasValidPods(currentPodSet map[string]bool) bool { + n.mu.RLock() + defer n.mu.RUnlock() + for _, podMap := range n.modelToPods { + for podName := range podMap { + if currentPodSet[podName] { + return true + } + } + } + return false +} + +func (n *TreeNode) GetModelToPodCount() int { + n.mu.RLock() + defer n.mu.RUnlock() + return len(n.modelToPods) +} + +func (n *TreeNode) GetPodsForModel(model string) map[string]time.Time { + n.mu.RLock() + defer n.mu.RUnlock() + if _, exists := n.modelToPods[model]; exists { + return n.modelToPods[model] // Still returns direct reference but smaller scope + } + return nil +} + +func (n *TreeNode) AddOrUpdatePodForModel(model string, podName string, timestamp time.Time) { + n.mu.Lock() + defer n.mu.Unlock() + if n.modelToPods == nil { + n.modelToPods = make(map[string]map[string]time.Time) + } + if _, exists := n.modelToPods[model]; !exists { + n.modelToPods[model] = make(map[string]time.Time) + } + n.modelToPods[model][podName] = timestamp +} + +func (n *TreeNode) RemovePodsNotInSet(currentPodSet map[string]bool) bool { + n.mu.Lock() + defer n.mu.Unlock() + podsChanged := false + for model, podMap := range n.modelToPods { + for podName := range podMap { + if !currentPodSet[podName] { + delete(podMap, podName) + podsChanged = true + } + } + if len(podMap) == 0 { + delete(n.modelToPods, model) + } + } + return podsChanged +} + func (c *LPRadixCache) NewTreeNode(numPods int, parent *TreeNode, key []int, value []int) *TreeNode { // Create the node with initialized maps and slices node := &TreeNode{ @@ -80,12 +227,12 @@ func (c *LPRadixCache) NewTreeNode(numPods int, parent *TreeNode, key []int, val parent: parent, key: make([]int, len(key)), // Allocate space for key value: make([]int, len(value)), // Allocate space for value (using len(value), not len(key)) - RefCounter: make([]int, numPods), + refCounter: make([]int, numPods), load: 1, lastAccess: time.Now(), - EvictedPods: make(map[int]bool), - CachedPods: make(map[int]bool), - ModelToPods: make(map[string]map[string]time.Time), + evictedPods: make(map[int]bool), + cachedPods: make(map[int]bool), + modelToPods: make(map[string]map[string]time.Time), // Pods: make(map[string]time.Time), depth: 0, contextLength: 0, @@ -125,8 +272,10 @@ func (c *LPRadixCache) GetAllNodes() map[int]*TreeNode { } func (c *LPRadixCache) GetAllPodsInNode(node *TreeNode) []string { - all_pods_in_node := make([]string, 0, len(node.ModelToPods)) - for _, pods := range node.ModelToPods { + node.mu.RLock() + defer node.mu.RUnlock() + all_pods_in_node := make([]string, 0) + for _, pods := range node.modelToPods { for podName := range pods { all_pods_in_node = append(all_pods_in_node, podName) } @@ -180,7 +329,7 @@ type LPRadixCache struct { mu sync.RWMutex rootNode *TreeNode numPods int - // allocatedSize []int + // allocatedSize []int // not being used. if it is not going to be used, it will be removed permanently. allNodes map[int]*TreeNode nextNodeID int startTime time.Time @@ -189,7 +338,7 @@ type LPRadixCache struct { func NewLPRadixCache(numPods int) *LPRadixCache { cache := &LPRadixCache{ numPods: numPods, - // allocatedSize: make([]int, numPods), + // allocatedSize: make([]int, numPods), // not being used. if it is not going to be used, it will be removed permanently. allNodes: make(map[int]*TreeNode), nextNodeID: 0, startTime: time.Now(), @@ -200,8 +349,8 @@ func NewLPRadixCache(numPods int) *LPRadixCache { func (c *LPRadixCache) reset() { root := c.NewTreeNode(c.numPods, nil, []int{}, []int{}) - for i := range root.RefCounter { - root.RefCounter[i] = 1 + for i := range root.refCounter { + root.refCounter[i] = 1 } c.rootNode = root c.allNodes = make(map[int]*TreeNode) @@ -229,8 +378,7 @@ func (c *LPRadixCache) GetNode(tokens []int) *TreeNode { } // Implementation of PrefixCacheIndexer interface -// Not being used. Everything is being done in AddPrefix -// Fix for MatchPrefix method in tree.go +// NOTE: It is currently Not being used. Everything is being done in AddPrefix interface. func (c *LPRadixCache) MatchPrefix(inputTokens []int, model string, pods []*v1.Pod) ([]int, []int, []*v1.Pod) { c.mu.RLock() defer c.mu.RUnlock() @@ -244,7 +392,7 @@ func (c *LPRadixCache) MatchPrefix(inputTokens []int, model string, pods []*v1.P // Find matching pods var matchedPods []*v1.Pod - if modelPods, ok := node.ModelToPods[model]; ok { + if modelPods, ok := node.modelToPods[model]; ok { for _, pod := range pods { if _, ok := modelPods[pod.Name]; ok { if matchedPods == nil { @@ -257,7 +405,7 @@ func (c *LPRadixCache) MatchPrefix(inputTokens []int, model string, pods []*v1.P } klog.Infof("MatchPrefix - node(%d) key: %v, matched tokens: %v, model pods: %v", - node.id, node.key, matchedTokens, node.ModelToPods) + node.id, node.key, matchedTokens, node.modelToPods) return matchedTokens, unmatchedTokens, matchedPods } @@ -291,35 +439,19 @@ func (c *LPRadixCache) matchPrefixHelper(node *TreeNode, tokens []int) (*TreeNod return node, nil } -func (c *LPRadixCache) AddPrefix(tokens []int, model, podName string) (*TreeNode, []int, []int) { +func (c *LPRadixCache) AddPrefix(tokens []int, model string, podName string) (*TreeNode, []int, []int) { c.mu.Lock() defer c.mu.Unlock() // Do insertion first node, matchedTokens, unmatchedTokens := c.insertHelper(c.rootNode, tokens, tokens) if node != nil { - if node.ModelToPods == nil { - node.ModelToPods = make(map[string]map[string]time.Time) - } - if node.ModelToPods[model] == nil { - node.ModelToPods[model] = make(map[string]time.Time) - } - node.ModelToPods[model][podName] = time.Now() + node.InitAndUpdateModelPod(model, podName, time.Now()) current := node for current.parent != nil { - if current.parent.ModelToPods == nil { - current.parent.ModelToPods = make(map[string]map[string]time.Time) - } - if current.parent.ModelToPods[model] == nil { - current.parent.ModelToPods[model] = make(map[string]time.Time) - } - current.parent.ModelToPods[model][podName] = time.Now() + current.parent.InitAndUpdateModelPod(model, podName, time.Now()) current = current.parent } - if _, ok := node.ModelToPods[model]; !ok { - node.ModelToPods[model] = make(map[string]time.Time) - } - node.ModelToPods[model][podName] = time.Now() klog.Infof("Updated mapping for model %s, pod %s in node(%d) with key %v", model, podName, node.id, node.key) } @@ -392,7 +524,6 @@ func (c *LPRadixCache) doesExceededTTL(node *TreeNode, now time.Time) bool { func (c *LPRadixCache) Evict(now time.Time) []*TreeNode { c.mu.Lock() defer c.mu.Unlock() - var nodesToEvict []*TreeNode for _, node := range c.allNodes { if node != c.rootNode { @@ -445,14 +576,14 @@ func (c *LPRadixCache) evictNode(node *TreeNode) { current := node for parent := node.parent; parent != nil; parent = parent.parent { // Remove this node's pod mappings from parent - for model, pods := range current.ModelToPods { - if parentPods, ok := parent.ModelToPods[model]; ok { + for model, pods := range current.modelToPods { + if parentPods, ok := parent.modelToPods[model]; ok { for podName := range pods { delete(parentPods, podName) } // Remove model mapping if no pods left if len(parentPods) == 0 { - delete(parent.ModelToPods, model) + delete(parent.modelToPods, model) } } } @@ -470,12 +601,12 @@ func (c *LPRadixCache) evictNode(node *TreeNode) { // Clean up the node's references node.parent = nil node.children = nil - node.ModelToPods = nil - node.EvictedPods = nil - node.CachedPods = nil + node.modelToPods = nil + node.evictedPods = nil + node.cachedPods = nil node.value = nil node.key = nil - node.RefCounter = nil + node.refCounter = nil } func (c *LPRadixCache) splitNode(key []int, child *TreeNode, splitLen int) *TreeNode { @@ -505,30 +636,30 @@ func (c *LPRadixCache) splitNode(key []int, child *TreeNode, splitLen int) *Tree // Copy metadata newNode.load = child.load - copy(newNode.RefCounter, child.RefCounter) + copy(newNode.refCounter, child.refCounter) // Copy pod mappings - for k, v := range child.CachedPods { - newNode.CachedPods[k] = v + for k, v := range child.cachedPods { + newNode.cachedPods[k] = v } - for k, v := range child.EvictedPods { - newNode.EvictedPods[k] = v + for k, v := range child.evictedPods { + newNode.evictedPods[k] = v } // Copy ModelToPods mapping to both nodes - newNode.ModelToPods = make(map[string]map[string]time.Time) - for model, pods := range child.ModelToPods { + newNode.modelToPods = make(map[string]map[string]time.Time) + for model, pods := range child.modelToPods { // Copy to new node (prefix node) - newNode.ModelToPods[model] = make(map[string]time.Time) + newNode.modelToPods[model] = make(map[string]time.Time) for podName, lastAccess := range pods { - newNode.ModelToPods[model][podName] = lastAccess + newNode.modelToPods[model][podName] = lastAccess } } - klog.Infof("Split complete - New node(%d) key: %v, ModelToPods: %v", - newNode.id, newNode.key, newNode.ModelToPods) - klog.Infof("Split complete - Child node(%d) key: %v, ModelToPods: %v", - child.id, child.key, child.ModelToPods) + klog.Infof("Split complete - New node(%d) key: %v, modelToPods: %v", + newNode.id, newNode.key, newNode.modelToPods) + klog.Infof("Split complete - Child node(%d) key: %v, modelToPods: %v", + child.id, child.key, child.modelToPods) c.allNodes[newNode.id] = newNode return newNode diff --git a/pkg/utils/util_test.go b/pkg/utils/util_test.go index 6fde8ac8..8bb7ab51 100644 --- a/pkg/utils/util_test.go +++ b/pkg/utils/util_test.go @@ -29,8 +29,12 @@ func TestTokenizeInputText(t *testing.T) { tokens, err := TokenizeInputText(inputStr) assert.Equal(t, nil, err) + outputStr, err := DetokenizeText(tokens) + assert.NoError(t, err) + assert.Equal(t, inputStr, outputStr) + tiktoken.SetBpeLoader(tiktoken_loader.NewOfflineLoader()) tke, _ := tiktoken.GetEncoding(encoding) - outputStr := tke.Decode(tokens) + outputStr = tke.Decode(tokens) assert.Equal(t, inputStr, outputStr) } diff --git a/pkg/webhook/modeladapter_webhook.go b/pkg/webhook/modeladapter_webhook.go new file mode 100644 index 00000000..97e74da4 --- /dev/null +++ b/pkg/webhook/modeladapter_webhook.go @@ -0,0 +1,79 @@ +/* +Copyright 2025 The Aibrix Team. + +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 webhook + +import ( + "context" + "fmt" + "net/url" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + modelapi "github.com/vllm-project/aibrix/api/model/v1alpha1" +) + +type ModelAdapterWebhook struct{} + +// SetupBackendRuntimeWebhook will setup the manager to manage the webhooks +func SetupBackendRuntimeWebhook(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(&modelapi.ModelAdapter{}). + WithDefaulter(&ModelAdapterWebhook{}). + WithValidator(&ModelAdapterWebhook{}). + Complete() +} + +//+kubebuilder:webhook:path=/mutate-model-aibrix-ai-v1alpha1-modeladapter,mutating=true,failurePolicy=fail,sideEffects=None,groups=model.aibrix.ai,resources=modeladapters,verbs=create;update,versions=v1alpha1,name=mmodeladapter.kb.io,admissionReviewVersions=v1 + +var _ webhook.CustomDefaulter = &ModelAdapterWebhook{} + +// Default implements webhook.Defaulter so a webhook will be registered for the type +func (w *ModelAdapterWebhook) Default(ctx context.Context, obj runtime.Object) error { + return nil +} + +//+kubebuilder:webhook:path=/validate-model-aibrix-ai-v1alpha1-modeladapter,mutating=false,failurePolicy=fail,sideEffects=None,groups=model.aibrix.ai,resources=modeladapters,verbs=create;update,versions=v1alpha1,name=vmodeladapter.kb.io,admissionReviewVersions=v1 + +var _ webhook.CustomValidator = &ModelAdapterWebhook{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (w *ModelAdapterWebhook) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { + var allErrs field.ErrorList + specPath := field.NewPath("spec") + + adapter := obj.(*modelapi.ModelAdapter) + + if _, err := url.ParseRequestURI(adapter.Spec.ArtifactURL); err != nil { + allErrs = append(allErrs, field.Invalid(specPath.Child("artifactURL"), adapter.Spec.ArtifactURL, fmt.Sprintf("artifactURL is invalid: %v", err))) + } + + return nil, allErrs.ToAggregate() +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (w *ModelAdapterWebhook) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + return nil, nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (w *ModelAdapterWebhook) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { + return nil, nil +} diff --git a/test/integration/webhook/modeladapter_test.go b/test/integration/webhook/modeladapter_test.go new file mode 100644 index 00000000..7e99abdc --- /dev/null +++ b/test/integration/webhook/modeladapter_test.go @@ -0,0 +1,80 @@ +/* +Copyright 2025 The Aibrix Team. + +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 webhook + +import ( + "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + modelapi "github.com/vllm-project/aibrix/api/model/v1alpha1" +) + +var _ = ginkgo.Describe("modelAdapter default and validation", func() { + var ns *corev1.Namespace + + ginkgo.BeforeEach(func() { + // Create test namespace before each test. + ns = &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "test-ns-", + }, + } + gomega.Expect(k8sClient.Create(ctx, ns)).To(gomega.Succeed()) + }) + + ginkgo.AfterEach(func() { + gomega.Expect(k8sClient.Delete(ctx, ns)).To(gomega.Succeed()) + var adapters modelapi.ModelAdapterList + gomega.Expect(k8sClient.List(ctx, &adapters)).To(gomega.Succeed()) + + for _, item := range adapters.Items { + gomega.Expect(k8sClient.Delete(ctx, &item)).To(gomega.Succeed()) + } + }) + + type testValidatingCase struct { + adapter func() *modelapi.ModelAdapter + failed bool + } + ginkgo.DescribeTable("test validating", + func(tc *testValidatingCase) { + if tc.failed { + gomega.Expect(k8sClient.Create(ctx, tc.adapter())).Should(gomega.HaveOccurred()) + } else { + gomega.Expect(k8sClient.Create(ctx, tc.adapter())).To(gomega.Succeed()) + } + }, + ginkgo.Entry("adapter creation with invalid artifactURL should be failed", &testValidatingCase{ + adapter: func() *modelapi.ModelAdapter { + adapter := modelapi.ModelAdapter{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-adapter", + Namespace: ns.Name, + }, + Spec: modelapi.ModelAdapterSpec{ + ArtifactURL: "aabbcc", + PodSelector: &metav1.LabelSelector{}, + }, + } + return &adapter + }, + failed: true, + }), + ) +}) diff --git a/test/integration/webhook/suit_test.go b/test/integration/webhook/suit_test.go new file mode 100644 index 00000000..96ad24e9 --- /dev/null +++ b/test/integration/webhook/suit_test.go @@ -0,0 +1,157 @@ +/* +Copyright 2025 The Aibrix Team. + +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 webhook + +import ( + "context" + "crypto/tls" + "fmt" + "net" + "path/filepath" + "runtime" + "testing" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + //+kubebuilder:scaffold:imports + + admissionv1 "k8s.io/api/admission/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + autoscalingapi "github.com/vllm-project/aibrix/api/autoscaling/v1alpha1" + modelapi "github.com/vllm-project/aibrix/api/model/v1alpha1" + orcheapi "github.com/vllm-project/aibrix/api/orchestration/v1alpha1" + apiwebhook "github.com/vllm-project/aibrix/pkg/webhook" +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment +var ctx context.Context +var cancel context.CancelFunc + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "Webhook Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + ctx, cancel = context.WithCancel(context.TODO()) + + By("bootstrapping test environment") + + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: true, + + // The BinaryAssetsDirectory is only required if you want to run the tests directly + // without call the makefile target test. If not informed it will look for the + // default path defined in controller-runtime which is /usr/local/kubebuilder/. + // Note that you must have the required binaries setup under the bin directory to perform + // the tests directly. When we run make test it will be setup and used automatically. + BinaryAssetsDirectory: filepath.Join("..", "..", "..", "bin", "k8s", + fmt.Sprintf("1.30.0-%s-%s", runtime.GOOS, runtime.GOARCH)), + + WebhookInstallOptions: envtest.WebhookInstallOptions{ + Paths: []string{filepath.Join("..", "..", "..", "config", "webhook")}, + }, + } + + var err error + // cfg is defined in this file globally. + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = modelapi.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + err = orcheapi.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + err = autoscalingapi.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + err = admissionv1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + err = corev1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + + // start webhook server using Manager + webhookInstallOptions := &testEnv.WebhookInstallOptions + mgr, err := ctrl.NewManager(cfg, ctrl.Options{ + Scheme: scheme.Scheme, + WebhookServer: webhook.NewServer(webhook.Options{ + Host: webhookInstallOptions.LocalServingHost, + Port: webhookInstallOptions.LocalServingPort, + CertDir: webhookInstallOptions.LocalServingCertDir, + }), + LeaderElection: false, + Metrics: metricsserver.Options{BindAddress: "0"}, + }) + Expect(err).NotTo(HaveOccurred()) + + err = apiwebhook.SetupBackendRuntimeWebhook(mgr) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:webhook + + go func() { + defer GinkgoRecover() + err = mgr.Start(ctx) + Expect(err).NotTo(HaveOccurred()) + }() + + // wait for the webhook server to get ready + dialer := &net.Dialer{Timeout: time.Second} + addrPort := fmt.Sprintf("%s:%d", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort) + Eventually(func() error { + conn, err := tls.DialWithDialer(dialer, "tcp", addrPort, &tls.Config{InsecureSkipVerify: true}) + if err != nil { + return err + } + return conn.Close() + }).Should(Succeed()) + +}) + +var _ = AfterSuite(func() { + cancel() + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +})