diff --git a/.github/workflows/smoke.yaml b/.github/workflows/smoke.yaml index 3f7c10e41..e434725c7 100644 --- a/.github/workflows/smoke.yaml +++ b/.github/workflows/smoke.yaml @@ -42,21 +42,20 @@ jobs: curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash sudo mv kustomize /usr/local/bin/ - - name: Apply CRDs + - name: Apply external CRDs run: | kubectl apply -f tests/crds/monitoring.coreos.com_servicemonitors.yaml kubectl apply -f tests/crds/route_crd.yaml kubectl apply -f tests/crds/serving.kserve.io_inferenceservices.yaml - kustomize build config/crd | kubectl apply -f - - name: Update params.env file run: | sed -i 's|trustyaiOperatorImage=quay.io/trustyai/trustyai-service-operator:latest|trustyaiOperatorImage=smoke/operator:pr-${{ github.event.pull_request.number || env.PR_NUMBER }}|' config/base/params.env - - name: Deploy the operator with kustomize + - name: Deploy the operator with testing overlay run: | kubectl create namespace system - kustomize build config/base | kubectl apply -n system -f - + kustomize build config/overlays/testing | kubectl apply -n system -f - - name: Run smoke tests run: ./tests/smoke/test_smoke.sh diff --git a/Makefile b/Makefile index c2ec50c11..3c6d34c56 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,28 @@ help: ## Display this help. .PHONY: manifests manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. - $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases + $(CONTROLLER_GEN) rbac:roleName=manager-role,headerFile="hack/boilerplate.yaml.txt" crd:headerFile="hack/boilerplate.yaml.txt" webhook:headerFile="hack/boilerplate.yaml.txt" paths="./..." output:crd:artifacts:config=config/crd/bases + @$(MAKE) components-generate + +.PHONY: components-generate +components-generate: ## Generate component kustomizations from controller-gen output + @echo "Generating Kustomize components..." + @./hack/generate-components.sh + +.PHONY: components-validate +components-validate: kustomize ## Validate all components build correctly + @./hack/validate-components.sh + +.PHONY: list-overlays +list-overlays: ## List available overlays + @echo "Available overlays:" + @echo " base - Core operator only (no controllers)" + @for overlay in config/overlays/*; do \ + if [ -d "$$overlay" ]; then \ + name=$$(basename $$overlay); \ + echo " $$name"; \ + fi \ + done .PHONY: generate generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. @@ -187,7 +208,7 @@ CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen ENVTEST ?= $(LOCALBIN)/setup-envtest ## Tool Versions -KUSTOMIZE_VERSION ?= v3.8.7 +KUSTOMIZE_VERSION ?= v5.7.0 CONTROLLER_TOOLS_VERSION ?= v0.20.0 KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" @@ -278,10 +299,35 @@ catalog-push: ## Push a catalog image. # Generate the full set of manifests to deploy the TrustyAI operator, with a customizable deployment namespace and operator image OPERATOR_IMAGE ?= quay.io/trustyai/trustyai-service-operator:latest .PHONY: manifest-gen -manifest-gen: kustomize - @echo "Usage: make manifest-gen NAMESPACE= OPERATOR_IMAGE=" - @echo "Example: make manifest-gen NAMESPACE=my-namespace OPERATOR_IMAGE=quay.io/myorg/trustyai-service-operator:latest" - mkdir -p release - @if [ -z "$(NAMESPACE)" ]; then echo "Error: NAMESPACE argument is required"; exit 1; fi - $(KUSTOMIZE) build config/base | sed "s|namespace: system|namespace: $(NAMESPACE)|g" | sed "s|quay.io/trustyai/trustyai-service-operator:latest|$(OPERATOR_IMAGE)|g" > release/trustyai_bundle.yaml - @echo "Release manifest generated at release/trustyai_bundle.yaml with namespace '$(NAMESPACE)' and operator image '$(OPERATOR_IMAGE)'" \ No newline at end of file +manifest-gen: kustomize ## Generate deployment manifests. Usage: make manifest-gen NAMESPACE= [OVERLAY=] [OPERATOR_IMAGE=] + @if [ -z "$(NAMESPACE)" ]; then \ + echo "Error: NAMESPACE argument is required"; \ + echo ""; \ + echo "Usage: make manifest-gen NAMESPACE= [OVERLAY=] [OPERATOR_IMAGE=]"; \ + echo "Example: make manifest-gen NAMESPACE=my-namespace OVERLAY=odh"; \ + echo ""; \ + echo "Available overlays (use 'make list-overlays' for descriptions):"; \ + echo " base (default)"; \ + ls -1 config/overlays/ 2>/dev/null | sed 's/^/ /'; \ + exit 1; \ + fi + @if [ ! -z "$(OVERLAY)" ] && [ "$(OVERLAY)" != "base" ] && [ ! -d "config/overlays/$(OVERLAY)" ]; then \ + echo "Error: Overlay '$(OVERLAY)' not found"; \ + echo "Available overlays:"; \ + echo " base"; \ + ls -1 config/overlays/ 2>/dev/null | sed 's/^/ /' || echo " (no overlays found)"; \ + exit 1; \ + fi + @mkdir -p release + @if [ -z "$(OVERLAY)" ]; then \ + echo "Building from config/overlays/testing..."; \ + $(KUSTOMIZE) build config/overlays/testing | sed "s|namespace: system|namespace: $(NAMESPACE)|g" | sed "s|quay.io/trustyai/trustyai-service-operator:latest|$(OPERATOR_IMAGE)|g" > release/trustyai_bundle.yaml; \ + echo "✓ Release manifest generated at release/trustyai_bundle.yaml"; \ + else \ + echo "Building from config/overlays/$(OVERLAY)..."; \ + $(KUSTOMIZE) build config/overlays/$(OVERLAY) | sed "s|namespace: system|namespace: $(NAMESPACE)|g" | sed "s|quay.io/trustyai/trustyai-service-operator:latest|$(OPERATOR_IMAGE)|g" > release/trustyai_$(OVERLAY)_bundle.yaml; \ + echo "✓ Release manifest generated at release/trustyai_$(OVERLAY)_bundle.yaml"; \ + fi + @echo " Namespace: $(NAMESPACE)" + @echo " Overlay: $(OVERLAY)" + @echo " Image: $(OPERATOR_IMAGE)" diff --git a/api/evalhub/v1alpha1/zz_generated.deepcopy.go b/api/evalhub/v1alpha1/zz_generated.deepcopy.go index d033edb3c..f17027f6c 100644 --- a/api/evalhub/v1alpha1/zz_generated.deepcopy.go +++ b/api/evalhub/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated /* -Copyright 2023. +Copyright 2026. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/api/gorch/v1alpha1/zz_generated.deepcopy.go b/api/gorch/v1alpha1/zz_generated.deepcopy.go index 426719d27..5df46f36a 100644 --- a/api/gorch/v1alpha1/zz_generated.deepcopy.go +++ b/api/gorch/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated /* -Copyright 2023. +Copyright 2026. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/api/lmes/v1alpha1/zz_generated.deepcopy.go b/api/lmes/v1alpha1/zz_generated.deepcopy.go index 80abaa1d9..de8a4ffa6 100644 --- a/api/lmes/v1alpha1/zz_generated.deepcopy.go +++ b/api/lmes/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated /* -Copyright 2023. +Copyright 2026. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/api/nemo_guardrails/v1alpha1/zz_generated.deepcopy.go b/api/nemo_guardrails/v1alpha1/zz_generated.deepcopy.go index b09f8badb..174624e6c 100644 --- a/api/nemo_guardrails/v1alpha1/zz_generated.deepcopy.go +++ b/api/nemo_guardrails/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated /* -Copyright 2023. +Copyright 2026. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/api/tas/v1/zz_generated.deepcopy.go b/api/tas/v1/zz_generated.deepcopy.go index 4b1e793ac..c0c68d62b 100644 --- a/api/tas/v1/zz_generated.deepcopy.go +++ b/api/tas/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated /* -Copyright 2023. +Copyright 2026. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/api/tas/v1alpha1/zz_generated.deepcopy.go b/api/tas/v1alpha1/zz_generated.deepcopy.go index 2c7b65d0a..af4319eb4 100644 --- a/api/tas/v1alpha1/zz_generated.deepcopy.go +++ b/api/tas/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated /* -Copyright 2023. +Copyright 2026. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/config/base/kustomization.yaml b/config/base/kustomization.yaml index db0f8179e..2ba74f199 100644 --- a/config/base/kustomization.yaml +++ b/config/base/kustomization.yaml @@ -1,16 +1,10 @@ --- -namePrefix: trustyai-service-operator- - resources: - - ../crd - - ../rbac - ../manager + - ../rbac-base - ../prometheus - ../configmaps -commonLabels: - app.kubernetes.io/part-of: trustyai - configMapGenerator: - env: params.env name: config diff --git a/config/crd/bases/trustyai.opendatahub.io_evalhubs.yaml b/config/components/evalhub/crd/trustyai.opendatahub.io_evalhubs.yaml similarity index 99% rename from config/crd/bases/trustyai.opendatahub.io_evalhubs.yaml rename to config/components/evalhub/crd/trustyai.opendatahub.io_evalhubs.yaml index 8705120c7..3a2ff0169 100644 --- a/config/crd/bases/trustyai.opendatahub.io_evalhubs.yaml +++ b/config/components/evalhub/crd/trustyai.opendatahub.io_evalhubs.yaml @@ -1,3 +1,4 @@ +# YAML generated by controller-gen. DO NOT EDIT. --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/config/components/evalhub/kustomization.yaml b/config/components/evalhub/kustomization.yaml new file mode 100644 index 000000000..f82d7f49f --- /dev/null +++ b/config/components/evalhub/kustomization.yaml @@ -0,0 +1,17 @@ +--- +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +resources: + - crd/trustyai.opendatahub.io_evalhubs.yaml + - rbac/evalhub_auth_reviewer_role.yaml + - rbac/evalhub_job_config_binding.yaml + - rbac/evalhub_job_config_role.yaml + - rbac/evalhub_jobs_writer_binding.yaml + - rbac/evalhub_jobs_writer_role.yaml + - rbac/evalhub_mlflow_access_binding.yaml + - rbac/evalhub_mlflow_access_role.yaml + - rbac/evalhub_mlflow_jobs_binding.yaml + - rbac/evalhub_mlflow_jobs_role.yaml + - rbac/manager-rbac.yaml + - rbac/manager-rolebinding.yaml diff --git a/config/rbac/evalhub/evalhub_auth_reviewer_role.yaml b/config/components/evalhub/rbac/evalhub_auth_reviewer_role.yaml similarity index 100% rename from config/rbac/evalhub/evalhub_auth_reviewer_role.yaml rename to config/components/evalhub/rbac/evalhub_auth_reviewer_role.yaml diff --git a/config/rbac/evalhub/evalhub_job_config_binding.yaml b/config/components/evalhub/rbac/evalhub_job_config_binding.yaml similarity index 100% rename from config/rbac/evalhub/evalhub_job_config_binding.yaml rename to config/components/evalhub/rbac/evalhub_job_config_binding.yaml diff --git a/config/rbac/evalhub/evalhub_job_config_role.yaml b/config/components/evalhub/rbac/evalhub_job_config_role.yaml similarity index 100% rename from config/rbac/evalhub/evalhub_job_config_role.yaml rename to config/components/evalhub/rbac/evalhub_job_config_role.yaml diff --git a/config/rbac/evalhub/evalhub_jobs_writer_binding.yaml b/config/components/evalhub/rbac/evalhub_jobs_writer_binding.yaml similarity index 100% rename from config/rbac/evalhub/evalhub_jobs_writer_binding.yaml rename to config/components/evalhub/rbac/evalhub_jobs_writer_binding.yaml diff --git a/config/rbac/evalhub/evalhub_jobs_writer_role.yaml b/config/components/evalhub/rbac/evalhub_jobs_writer_role.yaml similarity index 100% rename from config/rbac/evalhub/evalhub_jobs_writer_role.yaml rename to config/components/evalhub/rbac/evalhub_jobs_writer_role.yaml diff --git a/config/rbac/evalhub/evalhub_mlflow_access_binding.yaml b/config/components/evalhub/rbac/evalhub_mlflow_access_binding.yaml similarity index 100% rename from config/rbac/evalhub/evalhub_mlflow_access_binding.yaml rename to config/components/evalhub/rbac/evalhub_mlflow_access_binding.yaml diff --git a/config/rbac/evalhub/evalhub_mlflow_access_role.yaml b/config/components/evalhub/rbac/evalhub_mlflow_access_role.yaml similarity index 100% rename from config/rbac/evalhub/evalhub_mlflow_access_role.yaml rename to config/components/evalhub/rbac/evalhub_mlflow_access_role.yaml diff --git a/config/rbac/evalhub/evalhub_mlflow_jobs_binding.yaml b/config/components/evalhub/rbac/evalhub_mlflow_jobs_binding.yaml similarity index 100% rename from config/rbac/evalhub/evalhub_mlflow_jobs_binding.yaml rename to config/components/evalhub/rbac/evalhub_mlflow_jobs_binding.yaml diff --git a/config/rbac/evalhub/evalhub_mlflow_jobs_role.yaml b/config/components/evalhub/rbac/evalhub_mlflow_jobs_role.yaml similarity index 100% rename from config/rbac/evalhub/evalhub_mlflow_jobs_role.yaml rename to config/components/evalhub/rbac/evalhub_mlflow_jobs_role.yaml diff --git a/config/components/evalhub/rbac/manager-rbac.yaml b/config/components/evalhub/rbac/manager-rbac.yaml new file mode 100644 index 000000000..149b27129 --- /dev/null +++ b/config/components/evalhub/rbac/manager-rbac.yaml @@ -0,0 +1,149 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: evalhub-manager-role +rules: +- apiGroups: + - trustyai.opendatahub.io + resources: + - evalhubs + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - trustyai.opendatahub.io + resources: + - evalhubs/proxy + verbs: + - get + - create +- apiGroups: + - trustyai.opendatahub.io + resources: + - evalhubs/status + verbs: + - get + - update + - patch +- apiGroups: + - trustyai.opendatahub.io + resources: + - evalhubs/finalizers + verbs: + - update +- apiGroups: + - apps + resources: + - deployments + verbs: + - list + - watch + - get + - create + - update + - patch + - delete +- apiGroups: + - apps + resources: + - deployments/status + verbs: + - get + - update + - patch +- apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - list + - watch + - get + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - update +- apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - rbac.authorization.k8s.io + resources: + - rolebindings + verbs: + - get + - list + - watch + - create + - update + - patch + - delete diff --git a/config/rbac/role_binding.yaml b/config/components/evalhub/rbac/manager-rolebinding.yaml similarity index 73% rename from config/rbac/role_binding.yaml rename to config/components/evalhub/rbac/manager-rolebinding.yaml index bf595d684..15c48f485 100644 --- a/config/rbac/role_binding.yaml +++ b/config/components/evalhub/rbac/manager-rolebinding.yaml @@ -1,18 +1,18 @@ +--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/name: clusterrolebinding - app.kubernetes.io/instance: manager-rolebinding + app.kubernetes.io/instance: evalhub-manager-rolebinding app.kubernetes.io/component: rbac app.kubernetes.io/created-by: trustyai-service-operator - app.kubernetes.io/part-of: trustyai-service-operator app.kubernetes.io/managed-by: kustomize - name: manager-rolebinding + name: evalhub-manager-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: manager-role + name: trustyai-service-operator-evalhub-manager-role subjects: - kind: ServiceAccount name: controller-manager diff --git a/config/crd/bases/trustyai.opendatahub.io_guardrailsorchestrators.yaml b/config/components/gorch/crd/trustyai.opendatahub.io_guardrailsorchestrators.yaml similarity index 99% rename from config/crd/bases/trustyai.opendatahub.io_guardrailsorchestrators.yaml rename to config/components/gorch/crd/trustyai.opendatahub.io_guardrailsorchestrators.yaml index f5ff8320e..bcf8cbea7 100644 --- a/config/crd/bases/trustyai.opendatahub.io_guardrailsorchestrators.yaml +++ b/config/components/gorch/crd/trustyai.opendatahub.io_guardrailsorchestrators.yaml @@ -1,3 +1,4 @@ +# YAML generated by controller-gen. DO NOT EDIT. --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/config/components/gorch/kustomization.yaml b/config/components/gorch/kustomization.yaml new file mode 100644 index 000000000..56052f830 --- /dev/null +++ b/config/components/gorch/kustomization.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +resources: + - crd/trustyai.opendatahub.io_guardrailsorchestrators.yaml + - rbac/manager-rbac.yaml + - rbac/manager-rolebinding.yaml diff --git a/config/components/gorch/rbac/manager-rbac.yaml b/config/components/gorch/rbac/manager-rbac.yaml new file mode 100644 index 000000000..e1d47a7fd --- /dev/null +++ b/config/components/gorch/rbac/manager-rbac.yaml @@ -0,0 +1,152 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: gorch-manager-role +rules: +- apiGroups: + - trustyai.opendatahub.io + resources: + - guardrailsorchestrators + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - trustyai.opendatahub.io + resources: + - guardrailsorchestrators/status + verbs: + - get + - update + - patch +- apiGroups: + - trustyai.opendatahub.io + resources: + - guardrailsorchestrators/finalizers + verbs: + - update +- apiGroups: + - serving.kserve.io + resources: + - servingruntimes + verbs: + - get + - list + - watch +- apiGroups: + - serving.kserve.io + resources: + - inferenceservices + verbs: + - get + - list +- apiGroups: + - apps + resources: + - deployments + verbs: + - list + - watch + - get + - create + - update + - patch + - delete +- apiGroups: + - apps + resources: + - deployments/status + verbs: + - get + - update + - patch +- apiGroups: + - apps + resources: + - deployments/finalizers + verbs: + - update +- apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - update +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - list + - watch + - get + - create + - update + - patch + - delete diff --git a/config/components/gorch/rbac/manager-rolebinding.yaml b/config/components/gorch/rbac/manager-rolebinding.yaml new file mode 100644 index 000000000..d9375feaf --- /dev/null +++ b/config/components/gorch/rbac/manager-rolebinding.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: gorch-manager-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: trustyai-service-operator + app.kubernetes.io/managed-by: kustomize + name: gorch-manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: trustyai-service-operator-gorch-manager-role +subjects: + - kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/config/components/job-mgr/kustomization.yaml b/config/components/job-mgr/kustomization.yaml new file mode 100644 index 000000000..7da9553f9 --- /dev/null +++ b/config/components/job-mgr/kustomization.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +resources: + - rbac/manager-rbac.yaml + - rbac/manager-rolebinding.yaml diff --git a/config/components/job-mgr/rbac/manager-rbac.yaml b/config/components/job-mgr/rbac/manager-rbac.yaml new file mode 100644 index 000000000..8e8a9046d --- /dev/null +++ b/config/components/job-mgr/rbac/manager-rbac.yaml @@ -0,0 +1,65 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: job-mgr-manager-role +rules: +- apiGroups: + - scheduling.k8s.io + resources: + - priorityclasses + verbs: + - list + - get + - watch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - watch + - update + - patch +- apiGroups: + - kueue.x-k8s.io + resources: + - workloads + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - kueue.x-k8s.io + resources: + - workloads/status + verbs: + - get + - update + - patch +- apiGroups: + - kueue.x-k8s.io + resources: + - workloads/finalizers + verbs: + - update +- apiGroups: + - kueue.x-k8s.io + resources: + - resourceflavors + verbs: + - get + - list + - watch +- apiGroups: + - kueue.x-k8s.io + resources: + - workloadpriorityclasses + verbs: + - get + - list + - watch diff --git a/config/components/job-mgr/rbac/manager-rolebinding.yaml b/config/components/job-mgr/rbac/manager-rolebinding.yaml new file mode 100644 index 000000000..95bffb1dc --- /dev/null +++ b/config/components/job-mgr/rbac/manager-rolebinding.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: job-mgr-manager-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: trustyai-service-operator + app.kubernetes.io/managed-by: kustomize + name: job-mgr-manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: trustyai-service-operator-job-mgr-manager-role +subjects: + - kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/config/components/lmes/configmaps/lmeval-tasks.yaml b/config/components/lmes/configmaps/lmeval-tasks.yaml new file mode 100644 index 000000000..df5816009 --- /dev/null +++ b/config/components/lmes/configmaps/lmeval-tasks.yaml @@ -0,0 +1,148 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: lmeval-tasks +data: + tier1: | + [ + { + "task": "gsm8k", + "description": "A benchmark of grade school math problems aimed at evaluating reasoning capabilities." + }, + { + "task": "rte", + "description": "" + }, + { + "task": "arc_easy", + "description": "" + }, + { + "task": "bbh", + "description": "Tasks focused on deep semantic understanding through hypothesization and reasoning." + }, + { + "task": "hellaswag", + "description": "Tasks to predict the ending of stories or scenarios, testing comprehension and creativity." + }, + { + "task": "winogrande", + "description": "A large-scale dataset for coreference resolution, inspired by the Winograd Schema Challenge." + }, + { + "task": "mmlu_anatomy", + "description": "" + }, + { + "task": "cb", + "description": "" + }, + { + "task": "openbookqa", + "description": "Open-book question answering tasks that require external knowledge and reasoning." + }, + { + "task": "commonsense_qa", + "description": "CommonsenseQA, a multiple-choice QA dataset for measuring commonsense knowledge." + }, + { + "task": "lambada_openai", + "description": "" + }, + { + "task": "lambada_standard", + "description": "" + }, + { + "task": "humaneval", + "description": "Code generation task that measures functional correctness for synthesizing programs from docstrings." + }, + { + "task": "wsc273", + "description": "The Winograd Schema Challenge, a test of commonsense reasoning and coreference resolution." + }, + { + "task": "mmlu_pro_law", + "description": "" + }, + { + "task": "gpqa_main_n_shot", + "description": "" + }, + { + "task": "xnli_tr", + "description": "" + }, + { + "task": "mbpp", + "description": "A benchmark designed to measure the ability to synthesize short Python programs from natural language descriptions." + }, + { + "task": "truthfulqa_mc2", + "description": "" + }, + { + "task": "wikitext", + "description": "Tasks based on text from Wikipedia articles to assess language modeling and generation." + }, + { + "task": "minerva_math_precalc", + "description": "" + }, + { + "task": "piqa", + "description": "Physical Interaction Question Answering tasks to test physical commonsense reasoning." + }, + { + "task": "leaderboard_math_algebra_hard", + "description": "" + }, + { + "task": "triviaqa", + "description": "A large-scale dataset for trivia question answering to test general knowledge." + }, + { + "task": "xwinograd_zh", + "description": "" + }, + { + "task": "social_iqa", + "description": "" + }, + { + "task": "ifeval", + "description": "Interactive fiction evaluation tasks for narrative understanding and reasoning." + }, + { + "task": "sciq", + "description": "Science Question Answering tasks to assess understanding of scientific concepts." + }, + { + "task": "wmdp_bio", + "description": "" + }, + { + "task": "ceval-valid_law", + "description": "" + }, + { + "task": "kmmlu_direct_law", + "description": "" + }, + { + "task": "belebele_ckb_Arab", + "description": "" + }, + { + "task": "xlsum_es", + "description": "" + }, + { + "task": "bbh_fewshot_snarks", + "description": "" + }, + { + "task": "mmlu_pro_plus_law", + "description": "" + } + ] diff --git a/config/crd/bases/trustyai.opendatahub.io_lmevaljobs.yaml b/config/components/lmes/crd/trustyai.opendatahub.io_lmevaljobs.yaml similarity index 99% rename from config/crd/bases/trustyai.opendatahub.io_lmevaljobs.yaml rename to config/components/lmes/crd/trustyai.opendatahub.io_lmevaljobs.yaml index 8a91dd558..266dd12d0 100644 --- a/config/crd/bases/trustyai.opendatahub.io_lmevaljobs.yaml +++ b/config/components/lmes/crd/trustyai.opendatahub.io_lmevaljobs.yaml @@ -1,3 +1,4 @@ +# YAML generated by controller-gen. DO NOT EDIT. --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/config/components/lmes/kustomization.yaml b/config/components/lmes/kustomization.yaml new file mode 100644 index 000000000..87fe3473b --- /dev/null +++ b/config/components/lmes/kustomization.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +resources: + - crd/trustyai.opendatahub.io_lmevaljobs.yaml + - rbac/default_lmeval_user_rolebinding.yaml + - rbac/manager-rbac.yaml + - rbac/manager-rolebinding.yaml + - rbac/non_admin_lmeval_role.yaml + - configmaps/lmeval-tasks.yaml diff --git a/config/rbac/default_lmeval_user_rolebinding.yaml b/config/components/lmes/rbac/default_lmeval_user_rolebinding.yaml similarity index 100% rename from config/rbac/default_lmeval_user_rolebinding.yaml rename to config/components/lmes/rbac/default_lmeval_user_rolebinding.yaml diff --git a/config/components/lmes/rbac/manager-rbac.yaml b/config/components/lmes/rbac/manager-rbac.yaml new file mode 100644 index 000000000..f21dddeba --- /dev/null +++ b/config/components/lmes/rbac/manager-rbac.yaml @@ -0,0 +1,88 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: lmes-manager-role +rules: +- apiGroups: + - trustyai.opendatahub.io + resources: + - lmevaljobs + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - trustyai.opendatahub.io + resources: + - lmevaljobs/status + verbs: + - get + - update + - patch +- apiGroups: + - trustyai.opendatahub.io + resources: + - lmevaljobs/finalizers + verbs: + - update +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + - create + - delete +- apiGroups: + - "" + resources: + - pods/exec + verbs: + - get + - list + - watch + - create + - delete +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - watch + - list +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - watch + - list +- apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - list + - get + - watch +- apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - list + - get + - watch + - create + - update + - patch + - delete diff --git a/config/components/lmes/rbac/manager-rolebinding.yaml b/config/components/lmes/rbac/manager-rolebinding.yaml new file mode 100644 index 000000000..8e6a54771 --- /dev/null +++ b/config/components/lmes/rbac/manager-rolebinding.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: lmes-manager-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: trustyai-service-operator + app.kubernetes.io/managed-by: kustomize + name: lmes-manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: trustyai-service-operator-lmes-manager-role +subjects: + - kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/config/rbac/non_admin_lmeval_role.yaml b/config/components/lmes/rbac/non_admin_lmeval_role.yaml similarity index 100% rename from config/rbac/non_admin_lmeval_role.yaml rename to config/components/lmes/rbac/non_admin_lmeval_role.yaml diff --git a/config/crd/bases/trustyai.opendatahub.io_nemoguardrails.yaml b/config/components/nemo-guardrails/crd/trustyai.opendatahub.io_nemoguardrails.yaml similarity index 99% rename from config/crd/bases/trustyai.opendatahub.io_nemoguardrails.yaml rename to config/components/nemo-guardrails/crd/trustyai.opendatahub.io_nemoguardrails.yaml index eef7cb96e..df5d0a1fa 100644 --- a/config/crd/bases/trustyai.opendatahub.io_nemoguardrails.yaml +++ b/config/components/nemo-guardrails/crd/trustyai.opendatahub.io_nemoguardrails.yaml @@ -1,3 +1,4 @@ +# YAML generated by controller-gen. DO NOT EDIT. --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/config/components/nemo-guardrails/kustomization.yaml b/config/components/nemo-guardrails/kustomization.yaml new file mode 100644 index 000000000..0c7d8607c --- /dev/null +++ b/config/components/nemo-guardrails/kustomization.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +resources: + - crd/trustyai.opendatahub.io_nemoguardrails.yaml + - rbac/manager-rbac.yaml + - rbac/manager-rolebinding.yaml + - rbac/nemoguardrail_editor_role.yaml + - rbac/nemoguardrail_viewer_role.yaml diff --git a/config/components/nemo-guardrails/rbac/manager-rbac.yaml b/config/components/nemo-guardrails/rbac/manager-rbac.yaml new file mode 100644 index 000000000..a38b153a5 --- /dev/null +++ b/config/components/nemo-guardrails/rbac/manager-rbac.yaml @@ -0,0 +1,118 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: nemo-guardrails-manager-role +rules: +- apiGroups: + - trustyai.opendatahub.io + resources: + - nemoguardrails + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - trustyai.opendatahub.io + resources: + - nemoguardrails/status + verbs: + - get + - update + - patch +- apiGroups: + - trustyai.opendatahub.io + resources: + - nemoguardrails/finalizers + verbs: + - update +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - apps + resources: + - deployments + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - apps + resources: + - deployments/status + verbs: + - get + - update + - patch +- apiGroups: + - apps + resources: + - deployments/finalizers + verbs: + - update diff --git a/config/components/nemo-guardrails/rbac/manager-rolebinding.yaml b/config/components/nemo-guardrails/rbac/manager-rolebinding.yaml new file mode 100644 index 000000000..c39b8fe0a --- /dev/null +++ b/config/components/nemo-guardrails/rbac/manager-rolebinding.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: nemo-guardrails-manager-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: trustyai-service-operator + app.kubernetes.io/managed-by: kustomize + name: nemo-guardrails-manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: trustyai-service-operator-nemo-guardrails-manager-role +subjects: + - kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/config/rbac/nemoguardrail_editor_role.yaml b/config/components/nemo-guardrails/rbac/nemoguardrail_editor_role.yaml similarity index 100% rename from config/rbac/nemoguardrail_editor_role.yaml rename to config/components/nemo-guardrails/rbac/nemoguardrail_editor_role.yaml diff --git a/config/rbac/nemoguardrail_viewer_role.yaml b/config/components/nemo-guardrails/rbac/nemoguardrail_viewer_role.yaml similarity index 100% rename from config/rbac/nemoguardrail_viewer_role.yaml rename to config/components/nemo-guardrails/rbac/nemoguardrail_viewer_role.yaml diff --git a/config/crd/bases/trustyai.opendatahub.io_trustyaiservices.yaml b/config/components/tas/crd/trustyai.opendatahub.io_trustyaiservices.yaml similarity index 99% rename from config/crd/bases/trustyai.opendatahub.io_trustyaiservices.yaml rename to config/components/tas/crd/trustyai.opendatahub.io_trustyaiservices.yaml index ea094a6d1..2ffd19a1c 100644 --- a/config/crd/bases/trustyai.opendatahub.io_trustyaiservices.yaml +++ b/config/components/tas/crd/trustyai.opendatahub.io_trustyaiservices.yaml @@ -1,3 +1,4 @@ +# YAML generated by controller-gen. DO NOT EDIT. --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/config/components/tas/kustomization.yaml b/config/components/tas/kustomization.yaml new file mode 100644 index 000000000..0af127405 --- /dev/null +++ b/config/components/tas/kustomization.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +resources: + - crd/trustyai.opendatahub.io_trustyaiservices.yaml + - rbac/manager-rbac.yaml + - rbac/manager-rolebinding.yaml + - rbac/trustyaiservice_editor_role.yaml + - rbac/trustyaiservice_viewer_role.yaml diff --git a/config/rbac/role.yaml b/config/components/tas/rbac/manager-rbac.yaml similarity index 76% rename from config/rbac/role.yaml rename to config/components/tas/rbac/manager-rbac.yaml index a47605eda..2d14cc7c1 100644 --- a/config/rbac/role.yaml +++ b/config/components/tas/rbac/manager-rbac.yaml @@ -2,72 +2,54 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: manager-role + name: tas-manager-role rules: - apiGroups: - - "" + - trustyai.opendatahub.io resources: - - configmaps - - persistentvolumeclaims - - pods - - secrets - - serviceaccounts - - services + - trustyaiservices verbs: - - create - - delete - get - list - - patch - - update - watch -- apiGroups: - - "" - resources: - - events - verbs: - create - - patch - update - - watch + - patch + - delete - apiGroups: - - "" + - trustyai.opendatahub.io resources: - - persistentvolumes + - trustyaiservices/status verbs: - get - - list - - watch + - update + - patch - apiGroups: - - "" + - trustyai.opendatahub.io resources: - - pods/exec + - trustyaiservices/finalizers verbs: - - create - - delete - - get - - list - - watch + - update - apiGroups: - - apiextensions.k8s.io + - apps resources: - - customresourcedefinitions + - deployments verbs: - - get - list - watch + - get + - create + - update + - patch + - delete - apiGroups: - apps resources: - - deployments + - deployments/status verbs: - - create - - delete - get - - list - - patch - update - - watch + - patch - apiGroups: - apps resources: @@ -75,192 +57,181 @@ rules: verbs: - update - apiGroups: - - apps + - monitoring.coreos.com resources: - - deployments/status + - servicemonitors verbs: - - get - - patch - - update + - list + - watch + - create - apiGroups: - - coordination.k8s.io + - "" resources: - - leases + - services verbs: - - create - get + - list + - watch + - create - update + - patch + - delete - apiGroups: - - kueue.x-k8s.io + - "" resources: - - resourceflavors - - workloadpriorityclasses + - pods verbs: - get - list - watch + - create + - update + - patch + - delete - apiGroups: - - kueue.x-k8s.io + - "" resources: - - workloads + - configmaps verbs: - - create - - delete - get - list - - patch - - update - watch -- apiGroups: - - kueue.x-k8s.io - resources: - - workloads/finalizers - verbs: + - create - update + - patch + - delete - apiGroups: - - kueue.x-k8s.io + - "" resources: - - workloads/status + - persistentvolumes verbs: + - list - get - - patch - - update + - watch - apiGroups: - - monitoring.coreos.com + - "" resources: - - servicemonitors + - persistentvolumeclaims verbs: - - create - list + - get - watch + - create + - update + - patch + - delete - apiGroups: - - networking.istio.io + - route.openshift.io resources: - - destinationrules - - virtualservices + - routes verbs: - - create - - delete - - get - list - - patch - - update - watch + - get + - create + - update + - patch + - delete - apiGroups: - - rbac.authorization.k8s.io + - serving.kserve.io resources: - - clusterrolebindings + - inferenceservices verbs: - - create - - delete - - get - list - - update - watch + - get + - update + - patch - apiGroups: - - rbac.authorization.k8s.io + - serving.kserve.io resources: - - rolebindings - - roles + - inferenceservices/finalizers verbs: - - create - - delete - - get - list - - patch - - update - watch + - get + - update + - patch + - delete - apiGroups: - - route.openshift.io + - "" resources: - - routes + - events verbs: - create - - delete - - get - - list - patch - update - - watch - apiGroups: - - scheduling.k8s.io + - "" resources: - - priorityclasses + - secrets verbs: - get - list - watch + - create + - update + - patch + - delete - apiGroups: - - serving.kserve.io + - "" resources: - - inferenceservices + - serviceaccounts verbs: - get - list - - patch - - update - watch + - create + - update + - delete - apiGroups: - - serving.kserve.io + - rbac.authorization.k8s.io resources: - - inferenceservices/finalizers + - clusterrolebindings verbs: - - delete - get - list - - patch - - update - watch + - create + - update + - delete - apiGroups: - - serving.kserve.io + - coordination.k8s.io resources: - - servingruntimes + - leases verbs: - get - - list - - watch + - create + - update - apiGroups: - - trustyai.opendatahub.io + - networking.istio.io resources: - - evalhubs - - guardrailsorchestrators - - lmevaljobs - - nemoguardrails - - trustyaiservices + - destinationrules verbs: - create - - delete - - get - list - - patch - - update - watch -- apiGroups: - - trustyai.opendatahub.io - resources: - - evalhubs/finalizers - - guardrailsorchestrators/finalizers - - lmevaljobs/finalizers - - nemoguardrails/finalizers - - trustyaiservices/finalizers - verbs: + - get - update + - patch + - delete - apiGroups: - - trustyai.opendatahub.io + - networking.istio.io resources: - - evalhubs/proxy + - virtualservices verbs: - create + - list + - watch - get + - update + - patch + - delete - apiGroups: - - trustyai.opendatahub.io + - apiextensions.k8s.io resources: - - evalhubs/status - - guardrailsorchestrators/status - - lmevaljobs/status - - nemoguardrails/status - - trustyaiservices/status + - customresourcedefinitions verbs: + - list + - watch - get - - patch - - update diff --git a/config/components/tas/rbac/manager-rolebinding.yaml b/config/components/tas/rbac/manager-rolebinding.yaml new file mode 100644 index 000000000..28d884253 --- /dev/null +++ b/config/components/tas/rbac/manager-rolebinding.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: tas-manager-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: trustyai-service-operator + app.kubernetes.io/managed-by: kustomize + name: tas-manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: trustyai-service-operator-tas-manager-role +subjects: + - kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/config/rbac/trustyaiservice_editor_role.yaml b/config/components/tas/rbac/trustyaiservice_editor_role.yaml similarity index 100% rename from config/rbac/trustyaiservice_editor_role.yaml rename to config/components/tas/rbac/trustyaiservice_editor_role.yaml diff --git a/config/rbac/trustyaiservice_viewer_role.yaml b/config/components/tas/rbac/trustyaiservice_viewer_role.yaml similarity index 100% rename from config/rbac/trustyaiservice_viewer_role.yaml rename to config/components/tas/rbac/trustyaiservice_viewer_role.yaml diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 9b0911921..db69c8fea 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -1,3 +1,7 @@ +# DEPRECATED: This wrapper is maintained for backwards compatibility +# New overlays should use components instead which include CRDs +# See config/components/ for modular controller-specific CRDs + resources: - bases/trustyai.opendatahub.io_trustyaiservices.yaml - bases/trustyai.opendatahub.io_lmevaljobs.yaml diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index e2fa6be40..31cda7a1e 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -32,8 +32,7 @@ spec: - /manager args: - --leader-elect - - --enable-services - - "TAS,LMES,GORCH,NEMO_GUARDRAILS,EVALHUB" + # --enable-services will be set by overlays based on which components are included image: $(trustyaiOperatorImage) name: manager securityContext: diff --git a/config/overlays/lmes/kustomization.yaml b/config/overlays/lmes/kustomization.yaml index 216c929fa..54b981b79 100644 --- a/config/overlays/lmes/kustomization.yaml +++ b/config/overlays/lmes/kustomization.yaml @@ -4,5 +4,24 @@ kind: Kustomization resources: - ../../base -patchesStrategicMerge: - - lmes-only-patch.yaml +components: + - ../../components/lmes + +labels: + - includeSelectors: true + pairs: + app.kubernetes.io/part-of: trustyai + +namePrefix: trustyai-service-operator- + +patches: + - target: + kind: Deployment + name: controller-manager + patch: |- + - op: add + path: /spec/template/spec/containers/0/args/- + value: "--enable-services" + - op: add + path: /spec/template/spec/containers/0/args/- + value: "LMES" diff --git a/config/overlays/mcp-guardrails/kustomization.yaml b/config/overlays/mcp-guardrails/kustomization.yaml new file mode 100644 index 000000000..e3efc8e89 --- /dev/null +++ b/config/overlays/mcp-guardrails/kustomization.yaml @@ -0,0 +1,36 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +# NeMo Guardrails Only Overlay +# Deploys only the NeMo Guardrails controller + +resources: + - ../../base + +components: + - ../../components/nemo-guardrails + +labels: + - includeSelectors: true + pairs: + app.kubernetes.io/part-of: trustyai + +namePrefix: trustyai-service-operator- + +patches: + - target: + kind: Deployment + name: controller-manager + patch: |- + - op: add + path: /spec/template/spec/containers/0/args/- + value: "--enable-services" + - op: add + path: /spec/template/spec/containers/0/args/- + value: "NEMO_GUARDRAILS" + +configMapGenerator: + - env: params.env + behavior: merge + name: config diff --git a/config/overlays/mcp-guardrails/params.env b/config/overlays/mcp-guardrails/params.env new file mode 100644 index 000000000..97862fdee --- /dev/null +++ b/config/overlays/mcp-guardrails/params.env @@ -0,0 +1,4 @@ +trustyaiServiceImage=quay.io/opendatahub/trustyai-service:latest +trustyaiOperatorImage=quay.io/opendatahub/trustyai-service-operator:latest +kube-rbac-proxy=quay.io/openshift/origin-kube-rbac-proxy:4.19 +nemo-guardrails-image=quay.io/trustyai/nemo-guardrails-server:latest diff --git a/config/overlays/odh-kueue/kustomization.yaml b/config/overlays/odh-kueue/kustomization.yaml index 28837c2c9..6da32fff1 100644 --- a/config/overlays/odh-kueue/kustomization.yaml +++ b/config/overlays/odh-kueue/kustomization.yaml @@ -4,8 +4,29 @@ kind: Kustomization resources: - ../../base -patchesStrategicMerge: - - patch.yaml +components: + - ../../components/tas + - ../../components/lmes + - ../../components/job-mgr + +labels: + - includeSelectors: true + pairs: + app.kubernetes.io/part-of: trustyai + +namePrefix: trustyai-service-operator- + +patches: + - target: + kind: Deployment + name: controller-manager + patch: |- + - op: add + path: /spec/template/spec/containers/0/args/- + value: "--enable-services" + - op: add + path: /spec/template/spec/containers/0/args/- + value: "TAS,LMES,JOB_MGR" configMapGenerator: - env: params.env diff --git a/config/overlays/odh/kustomization.yaml b/config/overlays/odh/kustomization.yaml index d4b4a2a96..61f1fe2c7 100644 --- a/config/overlays/odh/kustomization.yaml +++ b/config/overlays/odh/kustomization.yaml @@ -3,6 +3,33 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base + +components: + - ../../components/tas + - ../../components/evalhub + - ../../components/lmes + - ../../components/gorch + - ../../components/nemo-guardrails + +labels: + - includeSelectors: true + pairs: + app.kubernetes.io/part-of: trustyai + +namePrefix: trustyai-service-operator- + +patches: + - target: + kind: Deployment + name: controller-manager + patch: |- + - op: add + path: /spec/template/spec/containers/0/args/- + value: "--enable-services" + - op: add + path: /spec/template/spec/containers/0/args/- + value: "TAS,LMES,GORCH,NEMO_GUARDRAILS,EVALHUB" + configMapGenerator: - env: params.env behavior: merge diff --git a/config/overlays/rhoai/kustomization.yaml b/config/overlays/rhoai/kustomization.yaml index d4b4a2a96..61f1fe2c7 100644 --- a/config/overlays/rhoai/kustomization.yaml +++ b/config/overlays/rhoai/kustomization.yaml @@ -3,6 +3,33 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base + +components: + - ../../components/tas + - ../../components/evalhub + - ../../components/lmes + - ../../components/gorch + - ../../components/nemo-guardrails + +labels: + - includeSelectors: true + pairs: + app.kubernetes.io/part-of: trustyai + +namePrefix: trustyai-service-operator- + +patches: + - target: + kind: Deployment + name: controller-manager + patch: |- + - op: add + path: /spec/template/spec/containers/0/args/- + value: "--enable-services" + - op: add + path: /spec/template/spec/containers/0/args/- + value: "TAS,LMES,GORCH,NEMO_GUARDRAILS,EVALHUB" + configMapGenerator: - env: params.env behavior: merge diff --git a/config/overlays/testing/kustomization.yaml b/config/overlays/testing/kustomization.yaml index 7cacd7e20..17c842640 100644 --- a/config/overlays/testing/kustomization.yaml +++ b/config/overlays/testing/kustomization.yaml @@ -1,5 +1,31 @@ resources: - ../../base +components: + - ../../components/tas + - ../../components/evalhub + - ../../components/lmes + - ../../components/gorch + - ../../components/nemo-guardrails + +labels: + - includeSelectors: true + pairs: + app.kubernetes.io/part-of: trustyai + +namePrefix: trustyai-service-operator- + +patches: + - target: + kind: Deployment + name: controller-manager + patch: |- + - op: add + path: /spec/template/spec/containers/0/args/- + value: "--enable-services" + - op: add + path: /spec/template/spec/containers/0/args/- + value: "TAS,LMES,GORCH,NEMO_GUARDRAILS,EVALHUB" + patchesStrategicMerge: - image-pull-policy.yaml diff --git a/config/rbac/auth-delegator.yml b/config/rbac-base/auth-delegator.yml similarity index 100% rename from config/rbac/auth-delegator.yml rename to config/rbac-base/auth-delegator.yml diff --git a/config/rbac/auth_proxy_client_clusterrole.yaml b/config/rbac-base/auth_proxy_client_clusterrole.yaml similarity index 100% rename from config/rbac/auth_proxy_client_clusterrole.yaml rename to config/rbac-base/auth_proxy_client_clusterrole.yaml diff --git a/config/rbac/auth_proxy_role.yaml b/config/rbac-base/auth_proxy_role.yaml similarity index 100% rename from config/rbac/auth_proxy_role.yaml rename to config/rbac-base/auth_proxy_role.yaml diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac-base/auth_proxy_role_binding.yaml similarity index 100% rename from config/rbac/auth_proxy_role_binding.yaml rename to config/rbac-base/auth_proxy_role_binding.yaml diff --git a/config/rbac/auth_proxy_service.yaml b/config/rbac-base/auth_proxy_service.yaml similarity index 100% rename from config/rbac/auth_proxy_service.yaml rename to config/rbac-base/auth_proxy_service.yaml diff --git a/config/rbac-base/kustomization.yaml b/config/rbac-base/kustomization.yaml new file mode 100644 index 000000000..928862da2 --- /dev/null +++ b/config/rbac-base/kustomization.yaml @@ -0,0 +1,9 @@ +resources: + - auth-delegator.yml + - auth_proxy_client_clusterrole.yaml + - auth_proxy_role.yaml + - auth_proxy_role_binding.yaml + - auth_proxy_service.yaml + - leader_election_role.yaml + - leader_election_role_binding.yaml + - service_account.yaml diff --git a/config/rbac/leader_election_role.yaml b/config/rbac-base/leader_election_role.yaml similarity index 100% rename from config/rbac/leader_election_role.yaml rename to config/rbac-base/leader_election_role.yaml diff --git a/config/rbac/leader_election_role_binding.yaml b/config/rbac-base/leader_election_role_binding.yaml similarity index 100% rename from config/rbac/leader_election_role_binding.yaml rename to config/rbac-base/leader_election_role_binding.yaml diff --git a/config/rbac/service_account.yaml b/config/rbac-base/service_account.yaml similarity index 100% rename from config/rbac/service_account.yaml rename to config/rbac-base/service_account.yaml diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml deleted file mode 100644 index 3dc23ef20..000000000 --- a/config/rbac/kustomization.yaml +++ /dev/null @@ -1,25 +0,0 @@ -resources: - - service_account.yaml - - role.yaml - - role_binding.yaml - - leader_election_role.yaml - - leader_election_role_binding.yaml - - auth_proxy_service.yaml - - auth_proxy_role.yaml - - auth_proxy_role_binding.yaml - - auth_proxy_client_clusterrole.yaml - - evalhub/evalhub_auth_reviewer_role.yaml - - evalhub/evalhub_job_config_binding.yaml - - evalhub/evalhub_job_config_role.yaml - - evalhub/evalhub_jobs_writer_binding.yaml - - evalhub/evalhub_jobs_writer_role.yaml - - evalhub/evalhub_mlflow_access_binding.yaml - - evalhub/evalhub_mlflow_access_role.yaml - - evalhub/evalhub_mlflow_jobs_binding.yaml - - evalhub/evalhub_mlflow_jobs_role.yaml - - nemoguardrail_editor_role.yaml - - nemoguardrail_viewer_role.yaml - - trustyaiservice_editor_role.yaml - - trustyaiservice_viewer_role.yaml - - non_admin_lmeval_role.yaml - - default_lmeval_user_rolebinding.yaml diff --git a/controllers/evalhub/rbac_manifests_test.go b/controllers/evalhub/rbac_manifests_test.go index a47870a2f..b19b2239c 100644 --- a/controllers/evalhub/rbac_manifests_test.go +++ b/controllers/evalhub/rbac_manifests_test.go @@ -21,9 +21,9 @@ func TestEvalHubJobConfigClusterRoleVerbsAreMinimalAndSufficient(t *testing.T) { } // This test file lives at trustyai-service-operator/controllers/evalhub/. - // The manifest lives under trustyai-service-operator/config/rbac/evalhub/. + // The manifest lives under trustyai-service-operator/config/components/evalhub/rbac/. moduleRoot := filepath.Clean(filepath.Join(filepath.Dir(thisFile), "..", "..")) - manifestPath := filepath.Join(moduleRoot, "config", "rbac", "evalhub", "evalhub_job_config_role.yaml") + manifestPath := filepath.Join(moduleRoot, "config", "components", "evalhub", "rbac", "evalhub_job_config_role.yaml") raw, err := os.ReadFile(manifestPath) if err != nil { diff --git a/controllers/evalhub/suite_test.go b/controllers/evalhub/suite_test.go index 459c9e860..aa870e190 100644 --- a/controllers/evalhub/suite_test.go +++ b/controllers/evalhub/suite_test.go @@ -51,7 +51,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "components", "evalhub", "crd")}, ErrorIfCRDPathMissing: true, } diff --git a/controllers/gorch/suite_test.go b/controllers/gorch/suite_test.go index 1ea41fba5..28abd5ce2 100644 --- a/controllers/gorch/suite_test.go +++ b/controllers/gorch/suite_test.go @@ -184,7 +184,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases", "trustyai.opendatahub.io_guardrailsorchestrators.yaml"), + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "components", "gorch", "crd", "trustyai.opendatahub.io_guardrailsorchestrators.yaml"), filepath.Join("..", "..", "tests", "crds"), }, ErrorIfCRDPathMissing: true, diff --git a/controllers/lmes/lmevaljob_controller_suite_test.go b/controllers/lmes/lmevaljob_controller_suite_test.go index 02d76e3ce..8d632485e 100644 --- a/controllers/lmes/lmevaljob_controller_suite_test.go +++ b/controllers/lmes/lmevaljob_controller_suite_test.go @@ -60,7 +60,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{ - filepath.Join("..", "..", "config", "crd", "bases"), + filepath.Join("..", "..", "config", "components", "lmes", "crd"), }, ErrorIfCRDPathMissing: true, } diff --git a/controllers/nemo_guardrails/suite_test.go b/controllers/nemo_guardrails/suite_test.go index f9ded1c42..1b0e06792 100644 --- a/controllers/nemo_guardrails/suite_test.go +++ b/controllers/nemo_guardrails/suite_test.go @@ -54,7 +54,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases"), + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "components", "nemo-guardrails", "crd"), filepath.Join("..", "..", "tests", "crds")}, ErrorIfCRDPathMissing: true, diff --git a/controllers/tas/suite_test.go b/controllers/tas/suite_test.go index 90b238a18..0ebe9197a 100644 --- a/controllers/tas/suite_test.go +++ b/controllers/tas/suite_test.go @@ -492,7 +492,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases"), + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "components", "tas", "crd"), filepath.Join("..", "..", "config", "prometheus"), filepath.Join("..", "..", "tests", "crds")}, ErrorIfCRDPathMissing: true, diff --git a/hack/boilerplate.go.txt b/hack/boilerplate.go.txt index 65b862271..978679816 100644 --- a/hack/boilerplate.go.txt +++ b/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright 2023. +Copyright 2026. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/hack/boilerplate.yaml.txt b/hack/boilerplate.yaml.txt new file mode 100644 index 000000000..fd2973063 --- /dev/null +++ b/hack/boilerplate.yaml.txt @@ -0,0 +1 @@ +# YAML generated by controller-gen. DO NOT EDIT. diff --git a/hack/extract-component-rbac.sh b/hack/extract-component-rbac.sh new file mode 100755 index 000000000..611fd7de0 --- /dev/null +++ b/hack/extract-component-rbac.sh @@ -0,0 +1,123 @@ +#!/usr/bin/env bash + +# Copyright 2024 The TrustyAI Authors +# SPDX-License-Identifier: Apache-2.0 + +set -euo pipefail + +# Script to extract controller-specific RBAC rules +# Takes component name, CRD pattern, and controller directories as arguments + +if [[ $# -lt 3 ]]; then + echo "Usage: $0 " + echo " controller_dirs: comma-separated list of controller directories" + exit 1 +fi + +COMPONENT_NAME="$1" +CRD_PATTERN="$2" +CONTROLLER_DIRS="$3" + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +ROLE_FILE="${PROJECT_ROOT}/config/rbac/role.yaml" + +# Temporary files +TEMP_RULES=$(mktemp) +trap "rm -f ${TEMP_RULES}" EXIT + +# Extract rules from kubebuilder markers in controller Go files +IFS=',' read -ra DIRS <<< "${CONTROLLER_DIRS}" +for controller_dir in "${DIRS[@]}"; do + dir="${PROJECT_ROOT}/${controller_dir}" + if [[ -d "${dir}" ]]; then + # Find all Go files with kubebuilder:rbac markers (with or without space) + find "${dir}" -name "*.go" -exec grep -h "// *+kubebuilder:rbac" {} \; 2>/dev/null || true + fi +done | "${SCRIPT_DIR}/kubebuilder-rbac-to-yaml.sh" > "${TEMP_RULES}" + +# If no rules were extracted from markers, extract from role.yaml +if [[ ! -s "${TEMP_RULES}" && -n "${CRD_PATTERN}" ]]; then + # For controllers without kubebuilder markers, extract comprehensive rules from role.yaml + # Include: CRD-specific rules + common controller resources + awk -v pattern="${CRD_PATTERN}" ' + BEGIN { + in_rule = 0 + rule_buffer = "" + should_include = 0 + } + + /^- apiGroups:/ { + # Output previous rule if it should be included + if (in_rule && should_include && rule_buffer != "") { + print rule_buffer + } + # Start new rule + in_rule = 1 + should_include = 0 + rule_buffer = $0 + apigroup_line = "" + next + } + + in_rule { + rule_buffer = rule_buffer "\n" $0 + + # Capture apiGroups line for analysis + if ($0 ~ /^ - /) { + if (apigroup_line == "") { + apigroup_line = $0 + } + } + + # Include if: + # 1. Contains the CRD pattern (e.g., nemoguardrails) + # 2. Is for apps apiGroup (Deployments) + # 3. Is for core "" apiGroup (Services, ConfigMaps, etc.) + # 4. Is for route.openshift.io (Routes) + # 5. Is for monitoring.coreos.com (ServiceMonitors) + # 6. Is for rbac.authorization.k8s.io (ClusterRoleBindings, RoleBindings) + if ($0 ~ pattern) { + should_include = 1 + } else if (apigroup_line ~ /apps$/) { + should_include = 1 + } else if (apigroup_line ~ /""$/) { + # Core API group - check for controller resources + if ($0 ~ /deployments/ || $0 ~ /services/ || $0 ~ /configmaps/ || + $0 ~ /secrets/ || $0 ~ /pods/) { + should_include = 1 + } + } else if (apigroup_line ~ /route\.openshift\.io/) { + should_include = 1 + } else if (apigroup_line ~ /monitoring\.coreos\.com/) { + should_include = 1 + } else if (apigroup_line ~ /rbac\.authorization\.k8s\.io/) { + should_include = 1 + } + } + + END { + # Output last rule if it should be included + if (in_rule && should_include && rule_buffer != "") { + print rule_buffer + } + } + ' "${ROLE_FILE}" > "${TEMP_RULES}" +fi + +# Output the RBAC rules as a ClusterRole +cat <" + exit 1 +fi + +COMPONENT_NAME="$1" + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +COMPONENT_DIR="${PROJECT_ROOT}/config/components/${COMPONENT_NAME}" + +# Start kustomization.yaml +cat </dev/null | sort -z) + fi +done diff --git a/hack/generate-components.sh b/hack/generate-components.sh new file mode 100755 index 000000000..b4131330b --- /dev/null +++ b/hack/generate-components.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash + +# Copyright 2024 The TrustyAI Authors +# SPDX-License-Identifier: Apache-2.0 + +set -euo pipefail + +# Script to generate Kustomize components from controller-gen output +# This script is called automatically by 'make manifests' +# Compatible with bash 3.2+ (macOS default) + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +CONFIG_DIR="${PROJECT_ROOT}/config" +CRD_BASES_DIR="${CONFIG_DIR}/crd/bases" +RBAC_DIR="${CONFIG_DIR}/rbac" +COMPONENTS_DIR="${CONFIG_DIR}/components" + +# Component list (bash 3.2 compatible) +COMPONENT_NAMES="tas evalhub lmes job-mgr gorch nemo-guardrails" + +# Function to get component details -> leave blank if the component has no CRDs +get_crd_pattern() { + case "$1" in + tas) echo "trustyaiservices" ;; + evalhub) echo "evalhubs" ;; + lmes) echo "lmevaljobs" ;; + job-mgr) echo "" ;; # JOB_MGR shares CRD with LMES + gorch) echo "guardrailsorchestrators" ;; + nemo-guardrails) echo "nemoguardrails" ;; + esac +} + +get_controller_dirs() { + case "$1" in + tas) echo "controllers/tas" ;; + evalhub) echo "controllers/evalhub" ;; + lmes) echo "controllers/lmes" ;; + job-mgr) echo "controllers/job_mgr" ;; + gorch) echo "controllers/gorch" ;; + nemo-guardrails) echo "controllers/nemo_guardrails" ;; + esac +} + + +echo "==> Generating Kustomize components from controller-gen output" + +# Ensure components directory exists +mkdir -p "${COMPONENTS_DIR}" + +# Generate each component +for component in ${COMPONENT_NAMES}; do + echo "==> Generating component: ${component}" + + # Get component details + crd_pattern=$(get_crd_pattern "${component}") + controller_dirs=$(get_controller_dirs "${component}") + + # Create component directories + component_dir="${COMPONENTS_DIR}/${component}" + mkdir -p "${component_dir}/rbac" + + # 1. Move CRD file (skip for job-mgr as it shares CRD with lmes) + # Auto-generated CRDs are moved from config/crd/bases/ to component directories + if [[ ! -z ${crd_pattern} ]]; then + echo " - Moving CRD (pattern: ${crd_pattern})" + crd_file=$(find "${CRD_BASES_DIR}" -name "*${crd_pattern}.yaml" 2>/dev/null | head -1) + if [[ -n "${crd_file}" && -f "${crd_file}" ]]; then + mv -f "${crd_file}" "${component_dir}/crd/$(basename "${crd_file}")" + echo " ✓ Moved: $(basename "${crd_file}")" + else + echo " ✗ No CRDs for pattern '${crd_pattern}'" + fi + fi + + # 2. Extract manager RBAC rules + echo " - Extracting manager RBAC" + "${SCRIPT_DIR}/extract-component-rbac.sh" \ + "${component}" \ + "${crd_pattern}" \ + "${controller_dirs}" \ + > "${component_dir}/rbac/manager-rbac.yaml" + + # 3. Generate ClusterRoleBinding for the manager role + echo " - Generating manager-rolebinding.yaml" + cat > "${component_dir}/rbac/manager-rolebinding.yaml" < "${component_dir}/kustomization.yaml" +done + + +echo "==> Removing original monolithic role.yaml" +rm -f ${CONFIG_DIR}/rbac/role.yaml + +echo "==> Component generation complete!" +echo "" +echo "Components created in: ${COMPONENTS_DIR}" +echo "Run 'make components-validate' to verify all components build correctly" diff --git a/hack/kubebuilder-rbac-to-yaml.sh b/hack/kubebuilder-rbac-to-yaml.sh new file mode 100755 index 000000000..7c9f1d5eb --- /dev/null +++ b/hack/kubebuilder-rbac-to-yaml.sh @@ -0,0 +1,105 @@ +#!/usr/bin/env bash + +# Copyright 2024 The TrustyAI Authors +# SPDX-License-Identifier: Apache-2.0 + +set -euo pipefail + +# Script to convert kubebuilder:rbac markers to YAML format +# Reads from stdin, outputs YAML to stdout +# Compatible with bash 3.2+ (macOS default) + +# Temporary file for processing +TEMP_FILE=$(mktemp) +TEMP_SEEN=$(mktemp) +trap "rm -f ${TEMP_FILE} ${TEMP_SEEN}" EXIT + +# Read all input +cat > "${TEMP_FILE}" + +# If no input, exit +if [[ ! -s "${TEMP_FILE}" ]]; then + exit 0 +fi + +# Parse kubebuilder markers and convert to YAML +# Format: //+kubebuilder:rbac:groups=foo,resources=bar,verbs=get;list + +# Process each line +while IFS= read -r line; do + # Skip non-rbac markers + if [[ ! "${line}" =~ kubebuilder:rbac ]]; then + continue + fi + + # Extract the marker content after // +kubebuilder:rbac: (with or without space) + marker="${line#*kubebuilder:rbac:}" + + # Parse key=value pairs + groups="" + resources="" + verbs="" + urls="" + + IFS=',' read -ra PAIRS <<< "${marker}" + for pair in "${PAIRS[@]}"; do + key="${pair%%=*}" + value="${pair#*=}" + + case "${key}" in + groups) groups="${value}" ;; + resources) resources="${value}" ;; + verbs) verbs="${value}" ;; + urls) urls="${value}" ;; + esac + done + + # Create a unique key for deduplication + rule_key="${groups}|${resources}|${verbs}|${urls}" + + # Check if we've seen this rule before (simple deduplication) + if grep -Fxq "${rule_key}" "${TEMP_SEEN}" 2>/dev/null; then + continue + fi + echo "${rule_key}" >> "${TEMP_SEEN}" + + # Output YAML rule + echo "- apiGroups:" + if [[ -n "${groups}" ]]; then + IFS=';' read -ra GROUP_ARRAY <<< "${groups}" + for group in "${GROUP_ARRAY[@]}"; do + # Handle empty group (core API) + if [[ "${group}" == "core" || "${group}" == '""' || -z "${group}" ]]; then + echo ' - ""' + else + echo " - ${group}" + fi + done + else + echo ' - ""' + fi + + if [[ -n "${resources}" ]]; then + echo " resources:" + IFS=';' read -ra RESOURCE_ARRAY <<< "${resources}" + for resource in "${RESOURCE_ARRAY[@]}"; do + echo " - ${resource}" + done + fi + + if [[ -n "${verbs}" ]]; then + echo " verbs:" + IFS=';' read -ra VERB_ARRAY <<< "${verbs}" + for verb in "${VERB_ARRAY[@]}"; do + echo " - ${verb}" + done + fi + + if [[ -n "${urls}" ]]; then + echo " nonResourceURLs:" + IFS=';' read -ra URL_ARRAY <<< "${urls}" + for url in "${URL_ARRAY[@]}"; do + echo " - ${url}" + done + fi +done < "${TEMP_FILE}" diff --git a/hack/validate-components.sh b/hack/validate-components.sh new file mode 100755 index 000000000..37e43739b --- /dev/null +++ b/hack/validate-components.sh @@ -0,0 +1,170 @@ +#!/usr/bin/env bash + +# Copyright 2024 The TrustyAI Authors +# SPDX-License-Identifier: Apache-2.0 + +set -euo pipefail + +# Script to validate all generated components +# Checks that each component builds successfully with kustomize + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +COMPONENTS_DIR="${PROJECT_ROOT}/config/components" + +# Check if kustomize is available +if ! command -v kustomize &> /dev/null; then + echo "Error: kustomize not found. Please run 'make kustomize' first." + exit 1 +fi + +KUSTOMIZE="${PROJECT_ROOT}/bin/kustomize" +if [[ ! -x "${KUSTOMIZE}" ]]; then + KUSTOMIZE="kustomize" +fi + +echo "==> Validating Kustomize components" +echo "" + +FAILED_COMPONENTS=() +VALIDATED_COMPONENTS=() + +# Validate each component +for component_dir in "${COMPONENTS_DIR}"/*; do + if [[ ! -d "${component_dir}" ]]; then + continue + fi + + component_name=$(basename "${component_dir}") + echo "==> Validating component: ${component_name}" + + # Check kustomization.yaml exists + if [[ ! -f "${component_dir}/kustomization.yaml" ]]; then + echo " ✗ Missing kustomization.yaml" + FAILED_COMPONENTS+=("${component_name}") + continue + fi + + # Check CRD exists (skip for job-mgr which shares CRD with lmes) + if [[ "${component_name}" != "job-mgr" && ! -f "${component_dir}/crd.yaml" ]]; then + echo " ✗ Missing crd.yaml" + FAILED_COMPONENTS+=("${component_name}") + continue + fi + + # Try to build the component + if "${KUSTOMIZE}" build "${component_dir}" > /dev/null 2>&1; then + echo " ✓ Component builds successfully" + + # Check that output contains expected resources + output=$("${KUSTOMIZE}" build "${component_dir}") + + # Verify CRD is present (skip for job-mgr) + if [[ "${component_name}" != "job-mgr" ]]; then + if echo "${output}" | grep -q "^kind: CustomResourceDefinition"; then + echo " ✓ CRD present in output" + else + echo " ✗ Warning: CRD not found in output" + fi + else + echo " ✓ No CRD (shares with LMES component)" + fi + + # Verify ClusterRole is present + if echo "${output}" | grep -q "^kind: ClusterRole"; then + echo " ✓ ClusterRole present in output" + else + echo " ✗ Warning: ClusterRole not found in output" + fi + + VALIDATED_COMPONENTS+=("${component_name}") + else + echo " ✗ Failed to build component" + echo "" + echo "Error output:" + "${KUSTOMIZE}" build "${component_dir}" 2>&1 || true + echo "" + FAILED_COMPONENTS+=("${component_name}") + fi + + echo "" +done + +# Summary +echo "==> Validation Summary" +echo "" +echo "Validated components: ${#VALIDATED_COMPONENTS[@]}" +for component in "${VALIDATED_COMPONENTS[@]}"; do + echo " ✓ ${component}" +done + +if [[ ${#FAILED_COMPONENTS[@]} -gt 0 ]]; then + echo "" + echo "Failed components: ${#FAILED_COMPONENTS[@]}" + for component in "${FAILED_COMPONENTS[@]}"; do + echo " ✗ ${component}" + done + echo "" + exit 1 +fi + +echo "" +echo "==> Validating overlays with component composition" +echo "" + +OVERLAYS_DIR="${PROJECT_ROOT}/config/overlays" +FAILED_OVERLAYS=() +VALIDATED_OVERLAYS=() + +# Validate each overlay +for overlay_dir in "${OVERLAYS_DIR}"/*; do + if [[ ! -d "${overlay_dir}" ]]; then + continue + fi + + overlay_name=$(basename "${overlay_dir}") + echo "==> Validating overlay: ${overlay_name}" + + # Check kustomization.yaml exists + if [[ ! -f "${overlay_dir}/kustomization.yaml" ]]; then + echo " ✗ Missing kustomization.yaml" + FAILED_OVERLAYS+=("${overlay_name}") + continue + fi + + # Try to build the overlay + if "${KUSTOMIZE}" build "${overlay_dir}" > /dev/null 2>&1; then + echo " ✓ Overlay builds successfully" + VALIDATED_OVERLAYS+=("${overlay_name}") + else + echo " ✗ Failed to build overlay" + echo "" + echo "Error output:" + "${KUSTOMIZE}" build "${overlay_dir}" 2>&1 || true + echo "" + FAILED_OVERLAYS+=("${overlay_name}") + fi + + echo "" +done + +# Summary +echo "==> Overlay Validation Summary" +echo "" +echo "Validated overlays: ${#VALIDATED_OVERLAYS[@]}" +for overlay in "${VALIDATED_OVERLAYS[@]}"; do + echo " ✓ ${overlay}" +done + +if [[ ${#FAILED_OVERLAYS[@]} -gt 0 ]]; then + echo "" + echo "Failed overlays: ${#FAILED_OVERLAYS[@]}" + for overlay in "${FAILED_OVERLAYS[@]}"; do + echo " ✗ ${overlay}" + done + echo "" + exit 1 +fi + +echo "" +echo "==> All components and overlays validated successfully!" diff --git a/tests/smoke/test_smoke.sh b/tests/smoke/test_smoke.sh index c602a06c2..d53ecf6c4 100755 --- a/tests/smoke/test_smoke.sh +++ b/tests/smoke/test_smoke.sh @@ -22,6 +22,16 @@ log_success() { log_failure() { local message=$1 echo "❌ $message" + + # Dump operator logs if the pod exists + OPERATOR_POD=$(kubectl get pods -n system -l control-plane=controller-manager -o jsonpath='{.items[0].metadata.name}' 2>/dev/null) + if [[ -n "$OPERATOR_POD" ]]; then + echo "" + echo "========== Operator Pod Logs ==========" + kubectl logs -n system "$OPERATOR_POD" --all-containers --tail=100 || echo "Failed to retrieve operator logs" + echo "========================================" + fi + exit 1 }