diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5f97ff1f6..8e8fb2ea6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -85,7 +85,7 @@ jobs: timoni mod push ./timoni/podinfo oci://ghcr.io/stefanprodan/modules/podinfo \ --sign cosign \ --version ${{ steps.prep.outputs.VERSION }} \ - --source https://github.com/stefanprodan/podinfo \ + -a 'org.opencontainers.image.source=https://github.com/stefanprodan/podinfo' \ -a 'org.opencontainers.image.licenses=Apache-2.0' \ -a 'org.opencontainers.image.description=A timoni.sh module for deploying Podinfo.' \ -a 'org.opencontainers.image.documentation=https://github.com/stefanprodan/podinfo/blob/main/timoni/podinfo/README.md' diff --git a/timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/image.cue b/timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/image.cue index 06adebfdf..3c6b93c5b 100644 --- a/timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/image.cue +++ b/timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/image.cue @@ -1,19 +1,44 @@ +// Copyright 2023 Stefan Prodan +// SPDX-License-Identifier: Apache-2.0 + package v1alpha1 -// Image defines the schema for an OCI image reference. +import "strings" + +// Image defines the schema for OCI image reference used in Kubernetes PodSpec container image. #Image: { + + // Repository is the address of a container registry repository. + // An image repository is made up of slash-separated name components, optionally + // prefixed by a registry hostname and port in the format [HOST[:PORT_NUMBER]/]PATH. repository!: string - tag!: string - digest!: string - // Reference is the image address computed from - // repository, tag and digest. + // Tag identifies an image in the repository. + // A tag name may contain lowercase and uppercase characters, digits, underscores, periods and dashes. + // A tag name may not start with a period or a dash and may contain a maximum of 128 characters. + tag!: string & strings.MaxRunes(128) + + // Digest uniquely and immutably identifies an image in the repository. + // Spec: https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests. + digest!: string + + // Reference is the image address computed from repository, tag and digest + // in the format [REPOSITORY]:[TAG]@[DIGEST]. reference: string - if digest != "" { + if digest != "" && tag != "" { reference: "\(repository):\(tag)@\(digest)" } - if digest == "" { + + if digest != "" && tag == "" { + reference: "\(repository)@\(digest)" + } + + if digest == "" && tag != "" { reference: "\(repository):\(tag)" } + + if digest == "" && tag == "" { + reference: "\(repository):latest" + } } diff --git a/timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/metadata.cue b/timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/metadata.cue index d39448ea7..2b6cfe888 100644 --- a/timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/metadata.cue +++ b/timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/metadata.cue @@ -1,9 +1,15 @@ +// Copyright 2023 Stefan Prodan +// SPDX-License-Identifier: Apache-2.0 + package v1alpha1 import "strings" -// Metadata defines the schema for the Kubernetes object metadata. +// Metadata defines the schema for Kubernetes object metadata. #Metadata: { + // Version should be in the strict semver format. Is required when creating resources. + #Version!: string & strings.MaxRunes(63) + // Name must be unique within a namespace. Is required when creating resources. // Name is primarily intended for creation idempotence and configuration definition. // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names @@ -13,27 +19,18 @@ import "strings" // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces namespace!: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63) - // Version should be in the strict semver format. Is required when creating resources. - version!: string & strings.MaxRunes(63) - // Annotations is an unstructured key value map stored with a resource that may be - // set o store and retrieve arbitrary metadata. + // set to store and retrieve arbitrary metadata. // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations - annotations?: {[string]: string} + annotations?: {[string & =~"^(([A-Za-z0-9][-A-Za-z0-9_./]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)]: string} - // Map of string keys and values that can be used to organize and categorize - // (scope and select) objects. + // Map of string keys and values that can be used to organize and categorize (scope and select) objects. // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels - labels: {[string]: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)} + labels: {[string & =~"^(([A-Za-z0-9][-A-Za-z0-9_./]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)]: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)} // Standard Kubernetes labels: app name and version. labels: { "app.kubernetes.io/name": name - "app.kubernetes.io/version": version + "app.kubernetes.io/version": #Version } - - // Labels used to select pods for Kubernetes Deployment, Service, Job, etc. - labelSelector: *{ - "app.kubernetes.io/name": name - } | {[ string]: string} } diff --git a/timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/selector.cue b/timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/selector.cue new file mode 100644 index 000000000..3e8306b1a --- /dev/null +++ b/timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/selector.cue @@ -0,0 +1,21 @@ +// Copyright 2023 Stefan Prodan +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +import "strings" + +// Selector defines the schema for Kubernetes Pod label selector used in Deployments, Services, Jobs, etc. +#Selector: { + // Name must be unique within a namespace. Is required when creating resources. + // Name is primarily intended for creation idempotence and configuration definition. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names + #Name!: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MinRunes(1) & strings.MaxRunes(63) + + // Map of string keys and values that can be used to organize and categorize (scope and select) objects. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels + labels: {[string & =~"^(([A-Za-z0-9][-A-Za-z0-9_./]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)]: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)} + + // Standard Kubernetes label: app name. + labels: "app.kubernetes.io/name": #Name +} diff --git a/timoni/podinfo/templates/config.cue b/timoni/podinfo/templates/config.cue index 1260a9f1f..9dd432a04 100644 --- a/timoni/podinfo/templates/config.cue +++ b/timoni/podinfo/templates/config.cue @@ -19,8 +19,10 @@ import ( kubeVersion!: string // Metadata (common to all resources) - metadata: timoniv1.#Metadata - metadata: version: moduleVersion + metadata: timoniv1.#Metadata & {#Version: moduleVersion} + + // Label selector (common to all resources) + selector: timoniv1.#Selector & {#Name: metadata.name} // Deployment replicas: *1 | int & >=0 diff --git a/timoni/podinfo/templates/deployment.cue b/timoni/podinfo/templates/deployment.cue index 00b56aca0..bf75f40fa 100644 --- a/timoni/podinfo/templates/deployment.cue +++ b/timoni/podinfo/templates/deployment.cue @@ -9,15 +9,8 @@ import ( _config: #Config apiVersion: "apps/v1" kind: "Deployment" - metadata: { - name: _config.metadata.name - namespace: _config.metadata.namespace - labels: _config.metadata.labels - if _config.metadata.annotations != _|_ { - annotations: _config.metadata.annotations - } - } - spec: appsv1.#DeploymentSpec & { + metadata: _config.metadata + spec: appsv1.#DeploymentSpec & { if !_config.autoscaling.enabled { replicas: _config.replicas } @@ -25,10 +18,10 @@ import ( type: "RollingUpdate" rollingUpdate: maxUnavailable: "50%" } - selector: matchLabels: _config.metadata.labelSelector + selector: matchLabels: _config.selector.labels template: { metadata: { - labels: _config.metadata.labelSelector + labels: _config.selector.labels if _config.podAnnotations != _|_ { annotations: _config.podAnnotations } diff --git a/timoni/podinfo/templates/hpa.cue b/timoni/podinfo/templates/hpa.cue index 4138206f1..c8486318d 100644 --- a/timoni/podinfo/templates/hpa.cue +++ b/timoni/podinfo/templates/hpa.cue @@ -8,14 +8,7 @@ import ( _config: #Config apiVersion: "autoscaling/v2" kind: "HorizontalPodAutoscaler" - metadata: { - name: _config.metadata.name - namespace: _config.metadata.namespace - labels: _config.metadata.labels - if _config.metadata.annotations != _|_ { - annotations: _config.metadata.annotations - } - } + metadata: _config.metadata spec: { scaleTargetRef: { apiVersion: "apps/v1" diff --git a/timoni/podinfo/templates/ingress.cue b/timoni/podinfo/templates/ingress.cue index dac1f8b78..8b9c75806 100644 --- a/timoni/podinfo/templates/ingress.cue +++ b/timoni/podinfo/templates/ingress.cue @@ -8,16 +8,11 @@ import ( _config: #Config apiVersion: "networking.k8s.io/v1" kind: "Ingress" + metadata: _config.metadata metadata: { - name: _config.metadata.name - namespace: _config.metadata.namespace - labels: _config.metadata.labels if _config.ingress.labels != _|_ { labels: _config.ingress.labels } - if _config.metadata.annotations != _|_ { - annotations: _config.metadata.annotations - } if _config.ingress.annotations != _|_ { annotations: _config.ingress.annotations } diff --git a/timoni/podinfo/templates/service.cue b/timoni/podinfo/templates/service.cue index d286abf8a..a7e5cbfa9 100644 --- a/timoni/podinfo/templates/service.cue +++ b/timoni/podinfo/templates/service.cue @@ -8,23 +8,18 @@ import ( _config: #Config apiVersion: "v1" kind: "Service" + metadata: _config.metadata metadata: { - name: _config.metadata.name - namespace: _config.metadata.namespace - labels: _config.metadata.labels if _config.service.labels != _|_ { labels: _config.service.labels } - if _config.metadata.annotations != _|_ { - annotations: _config.metadata.annotations - } if _config.service.annotations != _|_ { annotations: _config.service.annotations } } spec: corev1.#ServiceSpec & { type: corev1.#ServiceTypeClusterIP - selector: _config.metadata.labelSelector + selector: _config.selector.labels ports: [ { name: "http" diff --git a/timoni/podinfo/templates/serviceaccount.cue b/timoni/podinfo/templates/serviceaccount.cue index 8cf6fb893..ec4c4c2f5 100644 --- a/timoni/podinfo/templates/serviceaccount.cue +++ b/timoni/podinfo/templates/serviceaccount.cue @@ -8,12 +8,5 @@ import ( _config: #Config apiVersion: "v1" kind: "ServiceAccount" - metadata: { - name: _config.metadata.name - namespace: _config.metadata.namespace - labels: _config.metadata.labels - if _config.metadata.annotations != _|_ { - annotations: _config.metadata.annotations - } - } + metadata: _config.metadata } diff --git a/timoni/podinfo/templates/servicemonitor.cue b/timoni/podinfo/templates/servicemonitor.cue index 8d3a329bc..9bb86c565 100644 --- a/timoni/podinfo/templates/servicemonitor.cue +++ b/timoni/podinfo/templates/servicemonitor.cue @@ -5,15 +5,8 @@ import ( ) #ServiceMonitor: promv1.#ServiceMonitor & { - _config: #Config - metadata: { - name: _config.metadata.name - namespace: _config.metadata.namespace - labels: _config.metadata.labels - if _config.metadata.annotations != _|_ { - annotations: _config.metadata.annotations - } - } + _config: #Config + metadata: _config.metadata spec: { endpoints: [{ path: "/metrics" @@ -21,6 +14,6 @@ import ( interval: "\(_config.monitoring.interval)s" }] namespaceSelector: matchNames: [_config.metadata.namespace] - selector: matchLabels: _config.metadata.labelSelector + selector: matchLabels: _config.selector.labels } }