From 830ec252b92476cbdc2458c0bf8a237040626044 Mon Sep 17 00:00:00 2001 From: kklinch0 Date: Mon, 28 Jul 2025 16:50:32 +0300 Subject: [PATCH] Scaffold CozyRD CRD Signed-off-by: Timofei Larkin --- .gitignore | 2 + .../cozystackresourcedefinitions_types.go | 89 +++ api/v1alpha1/zz_generated.deepcopy.go | 144 +++++ hack/update-codegen.sh | 4 + .../cozystack-api/templates/configmap.yaml | 353 ------------ .../cozystack-resource-definitions.yaml | 505 ++++++++++++++++++ .../cozystack-api/templates/deployment.yaml | 14 - .../system/cozystack-api/templates/rbac.yaml | 13 +- ...stack.io_cozystackresourcedefinitions.yaml | 115 ++++ pkg/cmd/server/start.go | 64 ++- pkg/config/config.go | 37 -- pkg/generated/openapi/zz_generated.openapi.go | 6 +- 12 files changed, 922 insertions(+), 424 deletions(-) create mode 100644 api/v1alpha1/cozystackresourcedefinitions_types.go delete mode 100644 packages/system/cozystack-api/templates/configmap.yaml create mode 100644 packages/system/cozystack-api/templates/cozystack-resource-definitions.yaml create mode 100644 packages/system/cozystack-controller/templates/crds/cozystack.io_cozystackresourcedefinitions.yaml diff --git a/.gitignore b/.gitignore index de476be5..82d4606d 100644 --- a/.gitignore +++ b/.gitignore @@ -77,3 +77,5 @@ fabric.properties .DS_Store **/.DS_Store + +tmp/ diff --git a/api/v1alpha1/cozystackresourcedefinitions_types.go b/api/v1alpha1/cozystackresourcedefinitions_types.go new file mode 100644 index 00000000..ea7c5d51 --- /dev/null +++ b/api/v1alpha1/cozystackresourcedefinitions_types.go @@ -0,0 +1,89 @@ +/* +Copyright 2025. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +kubebuilder:object:root=true + +// CozystackResourceDefinition is the Schema for the cozystackresourcedefinitions API +type CozystackResourceDefinition struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec CozystackResourceDefinitionSpec `json:"spec,omitempty"` +} + +// +kubebuilder:object:root=true + +// CozystackResourceDefinitionList contains a list of CozystackResourceDefinition +type CozystackResourceDefinitionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []CozystackResourceDefinition `json:"items"` +} + +func init() { + SchemeBuilder.Register(&CozystackResourceDefinition{}, &CozystackResourceDefinitionList{}) +} + +type CozystackResourceDefinitionSpec struct { + // Application configuration + Application CozystackResourceDefinitionApplication `json:"application"` + // Release configuration + Release CozystackResourceDefinitionRelease `json:"release"` +} + +type CozystackResourceDefinitionChart struct { + // Name of the Helm chart + Name string `json:"name"` + // Source reference for the Helm chart + SourceRef SourceRef `json:"sourceRef"` +} + +type SourceRef struct { + // Kind of the source reference + // +kubebuilder:default:="HelmRepository" + Kind string `json:"kind"` + // Name of the source reference + Name string `json:"name"` + // Namespace of the source reference + // +kubebuilder:default:="cozy-public" + Namespace string `json:"namespace"` +} + +type CozystackResourceDefinitionApplication struct { + // Kind of the application, used for UI and API + Kind string `json:"kind"` + // OpenAPI schema for the application, used for API validation + OpenAPISchema string `json:"openAPISchema"` + // Plural name of the application, used for UI and API + Plural string `json:"plural"` + // Singular name of the application, used for UI and API + Singular string `json:"singular"` +} + +type CozystackResourceDefinitionRelease struct { + // Helm chart configuration + Chart CozystackResourceDefinitionChart `json:"chart"` + // Labels for the release + Labels map[string]string `json:"labels,omitempty"` + // Prefix for the release name + Prefix string `json:"prefix"` +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index f510e197..08ee2e13 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -25,6 +25,135 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CozystackResourceDefinition) DeepCopyInto(out *CozystackResourceDefinition) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinition. +func (in *CozystackResourceDefinition) DeepCopy() *CozystackResourceDefinition { + if in == nil { + return nil + } + out := new(CozystackResourceDefinition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CozystackResourceDefinition) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CozystackResourceDefinitionApplication) DeepCopyInto(out *CozystackResourceDefinitionApplication) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionApplication. +func (in *CozystackResourceDefinitionApplication) DeepCopy() *CozystackResourceDefinitionApplication { + if in == nil { + return nil + } + out := new(CozystackResourceDefinitionApplication) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CozystackResourceDefinitionChart) DeepCopyInto(out *CozystackResourceDefinitionChart) { + *out = *in + out.SourceRef = in.SourceRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionChart. +func (in *CozystackResourceDefinitionChart) DeepCopy() *CozystackResourceDefinitionChart { + if in == nil { + return nil + } + out := new(CozystackResourceDefinitionChart) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CozystackResourceDefinitionList) DeepCopyInto(out *CozystackResourceDefinitionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]CozystackResourceDefinition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionList. +func (in *CozystackResourceDefinitionList) DeepCopy() *CozystackResourceDefinitionList { + if in == nil { + return nil + } + out := new(CozystackResourceDefinitionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CozystackResourceDefinitionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CozystackResourceDefinitionRelease) DeepCopyInto(out *CozystackResourceDefinitionRelease) { + *out = *in + out.Chart = in.Chart + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionRelease. +func (in *CozystackResourceDefinitionRelease) DeepCopy() *CozystackResourceDefinitionRelease { + if in == nil { + return nil + } + out := new(CozystackResourceDefinitionRelease) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CozystackResourceDefinitionSpec) DeepCopyInto(out *CozystackResourceDefinitionSpec) { + *out = *in + out.Application = in.Application + in.Release.DeepCopyInto(&out.Release) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionSpec. +func (in *CozystackResourceDefinitionSpec) DeepCopy() *CozystackResourceDefinitionSpec { + if in == nil { + return nil + } + out := new(CozystackResourceDefinitionSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in Selector) DeepCopyInto(out *Selector) { { @@ -46,6 +175,21 @@ func (in Selector) DeepCopy() Selector { return *out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SourceRef) DeepCopyInto(out *SourceRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceRef. +func (in *SourceRef) DeepCopy() *SourceRef { + if in == nil { + return nil + } + out := new(SourceRef) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Workload) DeepCopyInto(out *Workload) { *out = *in diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index a2a3b581..7067b040 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -32,6 +32,10 @@ kube::codegen::gen_helpers \ --boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \ "${SCRIPT_ROOT}/pkg/apis" +kube::codegen::gen_helpers \ + --boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \ + "${SCRIPT_ROOT}/api" + if [[ -n "${API_KNOWN_VIOLATIONS_DIR:-}" ]]; then report_filename="${API_KNOWN_VIOLATIONS_DIR}/cozystack_api_violation_exceptions.list" if [[ "${UPDATE_API_KNOWN_VIOLATIONS:-}" == "true" ]]; then diff --git a/packages/system/cozystack-api/templates/configmap.yaml b/packages/system/cozystack-api/templates/configmap.yaml deleted file mode 100644 index b873ae69..00000000 --- a/packages/system/cozystack-api/templates/configmap.yaml +++ /dev/null @@ -1,353 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: cozystack-api - namespace: cozy-system -data: - config.yaml: | - resources: - - application: - kind: Bucket - singular: bucket - plural: buckets - openAPISchema: {{ .Files.Get "openapi-schemas/bucket.json" | fromJson | toJson | quote }} - release: - prefix: bucket- - labels: - cozystack.io/ui: "true" - chart: - name: bucket - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: ClickHouse - singular: clickhouse - plural: clickhouses - openAPISchema: {{ .Files.Get "openapi-schemas/clickhouse.json" | fromJson | toJson | quote }} - release: - prefix: clickhouse- - labels: - cozystack.io/ui: "true" - chart: - name: clickhouse - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: HTTPCache - singular: httpcache - plural: httpcaches - openAPISchema: {{ .Files.Get "openapi-schemas/http-cache.json" | fromJson | toJson | quote }} - release: - prefix: http-cache- - labels: - cozystack.io/ui: "true" - chart: - name: http-cache - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: NATS - singular: nats - plural: natses - openAPISchema: {{ .Files.Get "openapi-schemas/nats.json" | fromJson | toJson | quote }} - release: - prefix: nats- - labels: - cozystack.io/ui: "true" - chart: - name: nats - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: TCPBalancer - singular: tcpbalancer - plural: tcpbalancers - openAPISchema: {{ .Files.Get "openapi-schemas/tcp-balancer.json" | fromJson | toJson | quote }} - release: - prefix: tcp-balancer- - labels: - cozystack.io/ui: "true" - chart: - name: tcp-balancer - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: VirtualMachine - singular: virtualmachine - plural: virtualmachines - openAPISchema: {{ .Files.Get "openapi-schemas/virtual-machine.json" | fromJson | toJson | quote }} - release: - prefix: virtual-machine- - labels: - cozystack.io/ui: "true" - chart: - name: virtual-machine - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: VPN - singular: vpn - plural: vpns - openAPISchema: {{ .Files.Get "openapi-schemas/vpn.json" | fromJson | toJson | quote }} - release: - prefix: vpn- - labels: - cozystack.io/ui: "true" - chart: - name: vpn - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: MySQL - singular: mysql - plural: mysqls - openAPISchema: {{ .Files.Get "openapi-schemas/mysql.json" | fromJson | toJson | quote }} - release: - prefix: mysql- - labels: - cozystack.io/ui: "true" - chart: - name: mysql - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: Tenant - singular: tenant - plural: tenants - openAPISchema: {{ .Files.Get "openapi-schemas/tenant.json" | fromJson | toJson | quote }} - release: - prefix: tenant- - labels: - cozystack.io/ui: "true" - chart: - name: tenant - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: Kubernetes - singular: kubernetes - plural: kuberneteses - openAPISchema: {{ .Files.Get "openapi-schemas/kubernetes.json" | fromJson | toJson | quote }} - release: - prefix: kubernetes- - labels: - cozystack.io/ui: "true" - chart: - name: kubernetes - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: Redis - singular: redis - plural: redises - openAPISchema: {{ .Files.Get "openapi-schemas/redis.json" | fromJson | toJson | quote }} - release: - prefix: redis- - labels: - cozystack.io/ui: "true" - chart: - name: redis - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: RabbitMQ - singular: rabbitmq - plural: rabbitmqs - openAPISchema: {{ .Files.Get "openapi-schemas/rabbitmq.json" | fromJson | toJson | quote }} - release: - prefix: rabbitmq- - labels: - cozystack.io/ui: "true" - chart: - name: rabbitmq - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: Postgres - singular: postgres - plural: postgreses - openAPISchema: {{ .Files.Get "openapi-schemas/postgres.json" | fromJson | toJson | quote }} - release: - prefix: postgres- - labels: - cozystack.io/ui: "true" - chart: - name: postgres - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: FerretDB - singular: ferretdb - plural: ferretdb - openAPISchema: {{ .Files.Get "openapi-schemas/ferretdb.json" | fromJson | toJson | quote }} - release: - prefix: ferretdb- - labels: - cozystack.io/ui: "true" - chart: - name: ferretdb - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: Kafka - singular: kafka - plural: kafkas - openAPISchema: {{ .Files.Get "openapi-schemas/kafka.json" | fromJson | toJson | quote }} - release: - prefix: kafka- - labels: - cozystack.io/ui: "true" - chart: - name: kafka - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: VMDisk - plural: vmdisks - singular: vmdisk - openAPISchema: {{ .Files.Get "openapi-schemas/vm-disk.json" | fromJson | toJson | quote }} - release: - prefix: vm-disk- - labels: - cozystack.io/ui: "true" - chart: - name: vm-disk - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: VMInstance - plural: vminstances - singular: vminstance - openAPISchema: {{ .Files.Get "openapi-schemas/vm-instance.json" | fromJson | toJson | quote }} - release: - prefix: vm-instance- - labels: - cozystack.io/ui: "true" - chart: - name: vm-instance - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - - application: - kind: Monitoring - plural: monitorings - singular: monitoring - openAPISchema: {{ .Files.Get "openapi-schemas/monitoring.json" | fromJson | toJson | quote }} - release: - prefix: "" - labels: - cozystack.io/ui: "true" - chart: - name: monitoring - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public - - application: - kind: Etcd - plural: etcds - singular: etcd - openAPISchema: {{ .Files.Get "openapi-schemas/etcd.json" | fromJson | toJson | quote }} - release: - prefix: "" - labels: - cozystack.io/ui: "true" - chart: - name: etcd - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public - - application: - kind: Ingress - plural: ingresses - singular: ingress - openAPISchema: {{ .Files.Get "openapi-schemas/ingress.json" | fromJson | toJson | quote }} - release: - prefix: "" - labels: - cozystack.io/ui: "true" - chart: - name: ingress - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public - - application: - kind: SeaweedFS - plural: seaweedfses - singular: seaweedfs - openAPISchema: {{ .Files.Get "openapi-schemas/seaweedfs.json" | fromJson | toJson | quote }} - release: - prefix: "" - labels: - cozystack.io/ui: "true" - chart: - name: seaweedfs - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public - - application: - kind: BootBox - plural: bootboxes - singular: bootbox - openAPISchema: {{ .Files.Get "openapi-schemas/bootbox.json" | fromJson | toJson | quote }} - release: - prefix: "" - labels: - cozystack.io/ui: "true" - chart: - name: bootbox - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public - - application: - kind: Info - plural: infos - singular: info - openAPISchema: {{ .Files.Get "openapi-schemas/info.json" | fromJson | toJson | quote }} - release: - prefix: "" - labels: - cozystack.io/ui: "true" - chart: - name: info - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public diff --git a/packages/system/cozystack-api/templates/cozystack-resource-definitions.yaml b/packages/system/cozystack-api/templates/cozystack-resource-definitions.yaml new file mode 100644 index 00000000..90d3f629 --- /dev/null +++ b/packages/system/cozystack-api/templates/cozystack-resource-definitions.yaml @@ -0,0 +1,505 @@ +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: bucket +spec: + application: + kind: Bucket + singular: bucket + plural: buckets + openAPISchema: | + {{- .Files.Get "openapi-schemas/bucket.json" | fromJson | toJson | nindent 6 }} + release: + prefix: bucket- + labels: + cozystack.io/ui: "true" + chart: + name: bucket + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: clickhouse +spec: + application: + kind: ClickHouse + singular: clickhouse + plural: clickhouses + openAPISchema: | + {{- .Files.Get "openapi-schemas/clickhouse.json" | fromJson | toJson | nindent 6 }} + release: + prefix: clickhouse- + labels: + cozystack.io/ui: "true" + chart: + name: clickhouse + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: httpcache +spec: + application: + kind: HTTPCache + singular: httpcache + plural: httpcaches + openAPISchema: | + {{- .Files.Get "openapi-schemas/http-cache.json" | fromJson | toJson | nindent 6 }} + release: + prefix: http-cache- + labels: + cozystack.io/ui: "true" + chart: + name: http-cache + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: nats +spec: + application: + kind: NATS + singular: nats + plural: natses + openAPISchema: | + {{- .Files.Get "openapi-schemas/nats.json" | fromJson | toJson | nindent 6 }} + release: + prefix: nats- + labels: + cozystack.io/ui: "true" + chart: + name: nats + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: tcpbalancer +spec: + application: + kind: TCPBalancer + singular: tcpbalancer + plural: tcpbalancers + openAPISchema: | + {{- .Files.Get "openapi-schemas/tcp-balancer.json" | fromJson | toJson | nindent 6 }} + release: + prefix: tcp-balancer- + labels: + cozystack.io/ui: "true" + chart: + name: tcp-balancer + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: virtualmachine +spec: + application: + kind: VirtualMachine + singular: virtualmachine + plural: virtualmachines + openAPISchema: | + {{- .Files.Get "openapi-schemas/virtual-machine.json" | fromJson | toJson | nindent 6 }} + release: + prefix: virtual-machine- + labels: + cozystack.io/ui: "true" + chart: + name: virtual-machine + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: vpn +spec: + application: + kind: VPN + singular: vpn + plural: vpns + openAPISchema: | + {{- .Files.Get "openapi-schemas/vpn.json" | fromJson | toJson | nindent 6 }} + release: + prefix: vpn- + labels: + cozystack.io/ui: "true" + chart: + name: vpn + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: mysql +spec: + application: + kind: MySQL + singular: mysql + plural: mysqls + openAPISchema: | + {{- .Files.Get "openapi-schemas/mysql.json" | fromJson | toJson | nindent 6 }} + release: + prefix: mysql- + labels: + cozystack.io/ui: "true" + chart: + name: mysql + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: tenant +spec: + application: + kind: Tenant + singular: tenant + plural: tenants + openAPISchema: | + {{- .Files.Get "openapi-schemas/tenant.json" | fromJson | toJson | nindent 6 }} + release: + prefix: tenant- + labels: + cozystack.io/ui: "true" + chart: + name: tenant + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: kubernetes +spec: + application: + kind: Kubernetes + singular: kubernetes + plural: kuberneteses + openAPISchema: | + {{- .Files.Get "openapi-schemas/kubernetes.json" | fromJson | toJson | nindent 6 }} + release: + prefix: kubernetes- + labels: + cozystack.io/ui: "true" + chart: + name: kubernetes + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: redis +spec: + application: + kind: Redis + singular: redis + plural: redises + openAPISchema: | + {{- .Files.Get "openapi-schemas/redis.json" | fromJson | toJson | nindent 6 }} + release: + prefix: redis- + labels: + cozystack.io/ui: "true" + chart: + name: redis + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: rabbitmq +spec: + application: + kind: RabbitMQ + singular: rabbitmq + plural: rabbitmqs + openAPISchema: | + {{- .Files.Get "openapi-schemas/rabbitmq.json" | fromJson | toJson | nindent 6 }} + release: + prefix: rabbitmq- + labels: + cozystack.io/ui: "true" + chart: + name: rabbitmq + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: postgres +spec: + application: + kind: Postgres + singular: postgres + plural: postgreses + openAPISchema: | + {{- .Files.Get "openapi-schemas/postgres.json" | fromJson | toJson | nindent 6 }} + release: + prefix: postgres- + labels: + cozystack.io/ui: "true" + chart: + name: postgres + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: ferretdb +spec: + application: + kind: FerretDB + singular: ferretdb + plural: ferretdbs + openAPISchema: | + {{- .Files.Get "openapi-schemas/ferretdb.json" | fromJson | toJson | nindent 6 }} + release: + prefix: ferretdb- + labels: + cozystack.io/ui: "true" + chart: + name: ferretdb + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: kafka +spec: + application: + kind: Kafka + singular: kafka + plural: kafkas + openAPISchema: | + {{- .Files.Get "openapi-schemas/kafka.json" | fromJson | toJson | nindent 6 }} + release: + prefix: kafka- + labels: + cozystack.io/ui: "true" + chart: + name: kafka + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: vmdisk +spec: + application: + kind: VMDisk + singular: vmdisk + plural: vmdisks + openAPISchema: | + {{- .Files.Get "openapi-schemas/vm-disk.json" | fromJson | toJson | nindent 6 }} + release: + prefix: vm-disk- + labels: + cozystack.io/ui: "true" + chart: + name: vm-disk + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: vminstance +spec: + application: + kind: VMInstance + singular: vminstance + plural: vminstances + openAPISchema: | + {{- .Files.Get "openapi-schemas/vm-instance.json" | fromJson | toJson | nindent 6 }} + release: + prefix: vm-instance- + labels: + cozystack.io/ui: "true" + chart: + name: vm-instance + sourceRef: + kind: HelmRepository + name: cozystack-apps + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: monitoring +spec: + application: + kind: Monitoring + singular: monitoring + plural: monitorings + openAPISchema: | + {{- .Files.Get "openapi-schemas/monitoring.json" | fromJson | toJson | nindent 6 }} + release: + prefix: "" + labels: + cozystack.io/ui: "true" + chart: + name: monitoring + sourceRef: + kind: HelmRepository + name: cozystack-extra + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: etcd +spec: + application: + kind: Etcd + singular: etcd + plural: etcds + openAPISchema: | + {{- .Files.Get "openapi-schemas/etcd.json" | fromJson | toJson | nindent 6 }} + release: + prefix: "" + labels: + cozystack.io/ui: "true" + chart: + name: etcd + sourceRef: + kind: HelmRepository + name: cozystack-extra + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: ingress +spec: + application: + kind: Ingress + singular: ingress + plural: ingresses + openAPISchema: | + {{- .Files.Get "openapi-schemas/ingress.json" | fromJson | toJson | nindent 6 }} + release: + prefix: "" + labels: + cozystack.io/ui: "true" + chart: + name: ingress + sourceRef: + kind: HelmRepository + name: cozystack-extra + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: seaweedfs +spec: + application: + kind: SeaweedFS + singular: seaweedfs + plural: seaweedfses + openAPISchema: | + {{- .Files.Get "openapi-schemas/seaweedfs.json" | fromJson | toJson | nindent 6 }} + release: + prefix: "" + labels: + cozystack.io/ui: "true" + chart: + name: seaweedfs + sourceRef: + kind: HelmRepository + name: cozystack-extra + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: bootbox +spec: + application: + kind: BootBox + singular: bootbox + plural: bootboxes + openAPISchema: | + {{- .Files.Get "openapi-schemas/bootbox.json" | fromJson | toJson | nindent 6 }} + release: + prefix: "" + labels: + cozystack.io/ui: "true" + chart: + name: bootbox + sourceRef: + kind: HelmRepository + name: cozystack-extra + namespace: cozy-public +--- +apiVersion: cozystack.io/v1alpha1 +kind: CozystackResourceDefinition +metadata: + name: info +spec: + application: + kind: Info + singular: info + plural: infos + openAPISchema: | + {{- .Files.Get "openapi-schemas/info.json" | fromJson | toJson | nindent 6 }} + release: + prefix: "" + labels: + cozystack.io/ui: "true" + chart: + name: info + sourceRef: + kind: HelmRepository + name: cozystack-extra + namespace: cozy-public diff --git a/packages/system/cozystack-api/templates/deployment.yaml b/packages/system/cozystack-api/templates/deployment.yaml index 3dd93bd8..46779d2b 100644 --- a/packages/system/cozystack-api/templates/deployment.yaml +++ b/packages/system/cozystack-api/templates/deployment.yaml @@ -14,22 +14,8 @@ spec: metadata: labels: app: cozystack-api - annotations: - checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} spec: serviceAccountName: cozystack-api containers: - name: cozystack-api image: "{{ .Values.cozystackAPI.image }}" - args: ["--config=/config/config.yaml"] - volumeMounts: - - name: config-volume - mountPath: /config/config.yaml - subPath: config.yaml - volumes: - - name: config-volume - configMap: - name: cozystack-api - items: - - key: config.yaml - path: config.yaml diff --git a/packages/system/cozystack-api/templates/rbac.yaml b/packages/system/cozystack-api/templates/rbac.yaml index 7cfd4282..b6a3469b 100644 --- a/packages/system/cozystack-api/templates/rbac.yaml +++ b/packages/system/cozystack-api/templates/rbac.yaml @@ -10,8 +10,11 @@ rules: resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations", "validatingadmissionpolicies", "validatingadmissionpolicybindings"] verbs: ["get", "watch", "list"] - apiGroups: ["flowcontrol.apiserver.k8s.io"] - resources: ['prioritylevelconfigurations', 'flowschemas'] - verbs: ['list', 'watch'] -- apiGroups: ['helm.toolkit.fluxcd.io'] - resources: ['*'] - verbs: ['*'] + resources: ["prioritylevelconfigurations", "flowschemas"] + verbs: ["list", "watch"] +- apiGroups: ["cozystack.io"] + resources: ["*"] + verbs: ["get", "watch", "list"] +- apiGroups: ["helm.toolkit.fluxcd.io"] + resources: ["*"] + verbs: ["*"] diff --git a/packages/system/cozystack-controller/templates/crds/cozystack.io_cozystackresourcedefinitions.yaml b/packages/system/cozystack-controller/templates/crds/cozystack.io_cozystackresourcedefinitions.yaml new file mode 100644 index 00000000..4fb0ff61 --- /dev/null +++ b/packages/system/cozystack-controller/templates/crds/cozystack.io_cozystackresourcedefinitions.yaml @@ -0,0 +1,115 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: cozystackresourcedefinitions.cozystack.io +spec: + group: cozystack.io + names: + kind: CozystackResourceDefinition + listKind: CozystackResourceDefinitionList + plural: cozystackresourcedefinitions + singular: cozystackresourcedefinition + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: CozystackResourceDefinition is the Schema for the cozystackresourcedefinitions + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + application: + description: Application configuration + properties: + kind: + description: Kind of the application, used for UI and API + type: string + openAPISchema: + description: OpenAPI schema for the application, used for API + validation + type: string + plural: + description: Plural name of the application, used for UI and API + type: string + singular: + description: Singular name of the application, used for UI and + API + type: string + required: + - kind + - openAPISchema + - plural + - singular + type: object + release: + description: Release configuration + properties: + chart: + description: Helm chart configuration + properties: + name: + description: Name of the Helm chart + type: string + sourceRef: + description: Source reference for the Helm chart + properties: + kind: + default: HelmRepository + description: Kind of the source reference + type: string + name: + description: Name of the source reference + type: string + namespace: + default: cozy-public + description: Namespace of the source reference + type: string + required: + - kind + - name + - namespace + type: object + required: + - name + - sourceRef + type: object + labels: + additionalProperties: + type: string + description: Labels for the release + type: object + prefix: + description: Prefix for the release name + type: string + required: + - chart + - prefix + type: object + required: + - application + - release + type: object + type: object + served: true + storage: true diff --git a/pkg/cmd/server/start.go b/pkg/cmd/server/start.go index 6f0cfac4..8f26b76c 100644 --- a/pkg/cmd/server/start.go +++ b/pkg/cmd/server/start.go @@ -25,11 +25,13 @@ import ( "io" "net" + corev1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1" "github.com/cozystack/cozystack/pkg/apiserver" "github.com/cozystack/cozystack/pkg/config" sampleopenapi "github.com/cozystack/cozystack/pkg/generated/openapi" "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime" utilerrors "k8s.io/apimachinery/pkg/util/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/version" @@ -38,9 +40,11 @@ import ( genericoptions "k8s.io/apiserver/pkg/server/options" utilfeature "k8s.io/apiserver/pkg/util/feature" utilversionpkg "k8s.io/apiserver/pkg/util/version" + "k8s.io/client-go/tools/clientcmd" "k8s.io/component-base/featuregate" baseversion "k8s.io/component-base/version" netutils "k8s.io/utils/net" + "sigs.k8s.io/controller-runtime/pkg/client" ) // AppsServerOptions holds the state for the Apps API server @@ -51,9 +55,7 @@ type AppsServerOptions struct { StdErr io.Writer AlternateDNS []string - - // Add a field to store the configuration path - ResourceConfigPath string + Client client.Client // Add a field to store the configuration ResourceConfig *config.ResourceConfig @@ -66,7 +68,6 @@ func NewAppsServerOptions(out, errOut io.Writer) *AppsServerOptions { "", apiserver.Codecs.LegacyCodec(v1alpha1.SchemeGroupVersion), ), - StdOut: out, StdErr: errOut, } @@ -101,9 +102,6 @@ func NewCommandStartAppsServer(ctx context.Context, defaults *AppsServerOptions) flags := cmd.Flags() o.RecommendedOptions.AddFlags(flags) - // Add a flag for the config path - flags.StringVar(&o.ResourceConfigPath, "config", "config.yaml", "Path to the resource configuration file") - // The following lines demonstrate how to configure version compatibility and feature gates // for the "Apps" component according to KEP-4330. @@ -142,12 +140,54 @@ func NewCommandStartAppsServer(ctx context.Context, defaults *AppsServerOptions) // Complete fills in the fields that are not set func (o *AppsServerOptions) Complete() error { - // Load the configuration file - cfg, err := config.LoadConfig(o.ResourceConfigPath) - if err != nil { - return fmt.Errorf("failed to load config from %s: %v", o.ResourceConfigPath, err) + scheme := runtime.NewScheme() + if err := corev1alpha1.AddToScheme(scheme); err != nil { + return fmt.Errorf("failed to register types: %w", err) } - o.ResourceConfig = cfg + + cfg, err := clientcmd.BuildConfigFromFlags("", "") + if err != nil { + return fmt.Errorf("failed to get kubeconfig: %w", err) + } + + o.Client, err = client.New(cfg, client.Options{Scheme: scheme}) + if err != nil { + return fmt.Errorf("client initialization failed: %w", err) + } + + crdList := &corev1alpha1.CozystackResourceDefinitionList{} + + if err := o.Client.List(context.Background(), crdList); err != nil { + return fmt.Errorf("failed to list CozystackResourceDefinitions: %w", err) + } + + // Convert to ResourceConfig + o.ResourceConfig = &config.ResourceConfig{} + for _, crd := range crdList.Items { + resource := config.Resource{ + Application: config.ApplicationConfig{ + Kind: crd.Spec.Application.Kind, + Singular: crd.Spec.Application.Singular, + Plural: crd.Spec.Application.Plural, + ShortNames: []string{}, // TODO: implement shortnames + OpenAPISchema: crd.Spec.Application.OpenAPISchema, + }, + Release: config.ReleaseConfig{ + Prefix: crd.Spec.Release.Prefix, + Labels: crd.Spec.Release.Labels, + Chart: config.ChartConfig{ + Name: crd.Spec.Release.Chart.Name, + SourceRef: config.SourceRefConfig{ + Kind: crd.Spec.Release.Chart.SourceRef.Kind, + Name: crd.Spec.Release.Chart.SourceRef.Name, + Namespace: crd.Spec.Release.Chart.SourceRef.Namespace, + }, + }, + }, + } + o.ResourceConfig.Resources = append(o.ResourceConfig.Resources, resource) + } + return nil } diff --git a/pkg/config/config.go b/pkg/config/config.go index 6ada99d3..390918a6 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -16,13 +16,6 @@ limitations under the License. package config -import ( - "fmt" - "os" - - "gopkg.in/yaml.v2" -) - // ResourceConfig represents the structure of the configuration file. type ResourceConfig struct { Resources []Resource `yaml:"resources"` @@ -62,33 +55,3 @@ type SourceRefConfig struct { Name string `yaml:"name"` Namespace string `yaml:"namespace"` } - -// LoadConfig loads the configuration from the specified path and validates it. -func LoadConfig(path string) (*ResourceConfig, error) { - data, err := os.ReadFile(path) - if err != nil { - return nil, err - } - - var config ResourceConfig - if err := yaml.Unmarshal(data, &config); err != nil { - return nil, err - } - - // Validate the configuration. - for i, res := range config.Resources { - if res.Application.Kind == "" { - return nil, fmt.Errorf("resource at index %d has an empty kind", i) - } - if res.Application.Plural == "" { - return nil, fmt.Errorf("resource at index %d has an empty plural", i) - } - if res.Release.Chart.Name == "" { - return nil, fmt.Errorf("resource at index %d has an empty chart name in release", i) - } - if res.Release.Chart.SourceRef.Kind == "" || res.Release.Chart.SourceRef.Name == "" || res.Release.Chart.SourceRef.Namespace == "" { - return nil, fmt.Errorf("resource at index %d has an incomplete sourceRef for chart in release", i) - } - } - return &config, nil -} diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 2df4a3bd..ed1d159c 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -30,9 +30,9 @@ import ( func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ - "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.Application": schema_pkg_apis_apps_v1alpha1_Application(ref), - "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.ApplicationList": schema_pkg_apis_apps_v1alpha1_ApplicationList(ref), - "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.ApplicationStatus": schema_pkg_apis_apps_v1alpha1_ApplicationStatus(ref), + "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.Application": schema_pkg_apis_apps_v1alpha1_Application(ref), + "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.ApplicationList": schema_pkg_apis_apps_v1alpha1_ApplicationList(ref), + "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.ApplicationStatus": schema_pkg_apis_apps_v1alpha1_ApplicationStatus(ref), "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1.ConversionRequest": schema_pkg_apis_apiextensions_v1_ConversionRequest(ref), "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1.ConversionResponse": schema_pkg_apis_apiextensions_v1_ConversionResponse(ref), "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1.ConversionReview": schema_pkg_apis_apiextensions_v1_ConversionReview(ref),