Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Timoni CUE schemas #328

Merged
merged 1 commit into from
Dec 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,4 @@ swagger:

.PHONY: timoni-build
timoni-build:
@timoni build podinfo ./timoni/podinfo -f ./timoni/podinfo/test_values.cue
@timoni build podinfo ./timoni/podinfo -f ./timoni/podinfo/debug_values.cue
59 changes: 58 additions & 1 deletion timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/image.cue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

package v1alpha1

import "strings"
import (
"encoding/base64"
"strings"
)

// Image defines the schema for OCI image reference used in Kubernetes PodSpec container image.
#Image: {
Expand All @@ -22,6 +25,10 @@ import "strings"
// Spec: https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests.
digest!: string

// PullPolicy defines the pull policy for the image.
// By default, it is set to IfNotPresent.
pullPolicy: *"IfNotPresent" | "Always" | "Never"

// Reference is the image address computed from repository, tag and digest
// in the format [REPOSITORY]:[TAG]@[DIGEST].
reference: string
Expand All @@ -42,3 +49,53 @@ import "strings"
reference: "\(repository):latest"
}
}

// ImagePullSecret is a generator for Kubernetes Secrets of type kubernetes.io/dockerconfigjson.
// Spec: https://kubernetes.io/docs/concepts/configuration/secret/#docker-config-secrets.
#ImagePullSecret: {
// Metadata is the Kubernetes object's metadata generated by Timoni.
meta=metadata: #Metadata

// Registry is the hostname of the container registry in the format [HOST[:PORT_NUMBER]].
registry!: string

// Username is the username used to authenticate to the container registry.
username!: string

// Password is the password used to authenticate to the container registry.
password!: string

// Optional suffix used to generate the Secret name.
suffix: *"" | string

let auth = base64.Encode(null, username+":"+password)

// The object is a read-only struct that contains the generated
// Kubernetes Secret of type kubernetes.io/dockerconfigjson.
object: {
apiVersion: "v1"
kind: "Secret"
type: "kubernetes.io/dockerconfigjson"
metadata: {
name: meta.name + suffix
namespace: meta.namespace
labels: meta.labels
if meta.annotations != _|_ {
annotations: meta.annotations
}
}
stringData: {
".dockerconfigjson": #"""
{
"auths": {
"\#(registry)": {
"username": "\#(username)",
"password": "\#(password)",
"auth": "\#(auth)"
}
}
}
"""#
}
}
}
27 changes: 27 additions & 0 deletions timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/instance.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2023 Stefan Prodan
// SPDX-License-Identifier: Apache-2.0

package v1alpha1

import "strings"

// InstanceName defines the schema for the name of a Timoni instance.
// The instance name is used as a Kubernetes label value and must be 63 characters or less.
#InstanceName: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MinRunes(1) & strings.MaxRunes(63)

// InstanceNamespace defines the schema for the namespace of a Timoni instance.
// The instance namespace is used as a Kubernetes label value and must be 63 characters or less.
#InstanceNamespace: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MinRunes(1) & strings.MaxRunes(63)

// InstanceOwnerReference defines the schema for Kubernetes labels used to denote ownership.
#InstanceOwnerReference: {
#Name: "instance.timoni.sh/name"
#Namespace: "instance.timoni.sh/namespace"
}

// InstanceModule defines the schema for the Module of a Timoni instance.
#InstanceModule: {
url: string & =~"^((oci|file)://.*)$"
version: *"latest" | string
digest?: string
}
93 changes: 86 additions & 7 deletions timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/metadata.cue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ package v1alpha1

import "strings"

// Annotations defines the schema for Kubernetes object metadata annotations.
#Annotations: {[string & strings.MaxRunes(253)]: string}

// Labels defines the schema for Kubernetes object metadata labels.
#Labels: {[string & strings.MaxRunes(253)]: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)}

#StdLabelName: "app.kubernetes.io/name"
#StdLabelVersion: "app.kubernetes.io/version"
#StdLabelPartOf: "app.kubernetes.io/part-of"
#StdLabelManagedBy: "app.kubernetes.io/managed-by"
#StdLabelComponent: "app.kubernetes.io/component"
#StdLabelInstance: "app.kubernetes.io/instance"

// Metadata defines the schema for Kubernetes object metadata.
#Metadata: {
// Version should be in the strict semver format. Is required when creating resources.
Expand All @@ -13,24 +26,90 @@ import "strings"
// 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.MaxRunes(63)
name!: #InstanceName

// Namespace defines the space within which each name must be unique.
// 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)
namespace!: #InstanceNamespace

// Annotations is an unstructured key value map stored with a resource that may be
// set to store and retrieve arbitrary metadata.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations
annotations?: {[string & =~"^(([A-Za-z0-9][-A-Za-z0-9_./]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)]: string}
annotations?: #Annotations

// 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)}
labels: #Labels

// Standard Kubernetes labels: app name and version.
// Standard Kubernetes labels: app name, version and managed-by.
labels: {
"app.kubernetes.io/name": name
"app.kubernetes.io/version": #Version
"\(#StdLabelName)": name
"\(#StdLabelVersion)": #Version
"\(#StdLabelManagedBy)": "timoni"
}

// LabelSelector selects Pods based on the app.kubernetes.io/name label.
#LabelSelector: #Labels & {
"\(#StdLabelName)": name
}
}

// MetaComponent generates the Kubernetes object metadata for a module namespaced component.
// The metadata.name is composed of the instance name and the component name.
// The metadata.labels contain the app.kubernetes.io/component label.
#MetaComponent: {
// Meta is the Kubernetes object's metadata generated by Timoni.
#Meta!: #Metadata

// Component is the name of the component used
// as a suffix for the generate object name.
#Component!: string & strings.MaxRunes(30)

name: #Meta.name + "-" + #Component
namespace: #Meta.namespace

labels: #Meta.labels
labels: "\(#StdLabelComponent)": #Component

annotations?: #Annotations
if #Meta.annotations != _|_ {
annotations: #Meta.annotations
}

// LabelSelector selects Pods based on the app.kubernetes.io/name
// and app.kubernetes.io/component labels.
#LabelSelector: #Labels & {
"\(#StdLabelComponent)": #Component
"\(#StdLabelName)": #Meta.name
}
}

// MetaClusterComponent generates the Kubernetes object metadata for a module non-namespaced component.
// The metadata.name is composed of the instance name and the component name.
// The metadata.namespace is unset.
// The metadata.labels contain the app.kubernetes.io/component label.
#MetaClusterComponent: {
// Meta is the Kubernetes object's metadata generated by Timoni.
#Meta!: #Metadata

// Component is the name of the component used
// as a suffix for the generate object name.
#Component!: string & strings.MaxRunes(30)

name: #Meta.name + "-" + #Component

labels: #Meta.labels
labels: "\(#StdLabelComponent)": #Component

annotations?: #Annotations
if #Meta.annotations != _|_ {
annotations: #Meta.annotations
}

// LabelSelector selects Pods based on the app.kubernetes.io/name
// and app.kubernetes.io/component labels.
#LabelSelector: #Labels & {
"\(#StdLabelComponent)": #Component
"\(#StdLabelName)": #Meta.name
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2023 Stefan Prodan
// SPDX-License-Identifier: Apache-2.0

package v1alpha1

import (
"strconv"
"strings"
)

// CPUQuantity is a string that is validated as a quantity of CPU, such as 100m or 2000m.
#CPUQuantity: string & =~"^[1-9]\\d*m$"

// MemoryQuantity is a string that is validated as a quantity of memory, such as 128Mi or 2Gi.
#MemoryQuantity: string & =~"^[1-9]\\d*(Mi|Gi)$"

// ResourceRequirement defines the schema for the CPU and Memory resource requirements.
#ResourceRequirement: {
cpu?: #CPUQuantity
memory?: #MemoryQuantity
}

// ResourceRequirements defines the schema for the compute resource requirements of a container.
// More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/.
#ResourceRequirements: {
// Limits describes the maximum amount of compute resources allowed.
limits?: #ResourceRequirement

// Requests describes the minimum amount of compute resources required.
// Requests cannot exceed Limits.
requests?: #ResourceRequirement & {
if limits != _|_ {
if limits.cpu != _|_ {
_lc: strconv.Atoi(strings.Split(limits.cpu, "m")[0])
_rc: strconv.Atoi(strings.Split(requests.cpu, "m")[0])
#cpu: int & >=_rc & _lc
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@

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)
#Name!: #InstanceName

// 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)}
labels: #Labels

// Standard Kubernetes label: app name.
labels: "app.kubernetes.io/name": #Name
labels: "\(#StdLabelName)": #Name
}
29 changes: 29 additions & 0 deletions timoni/podinfo/cue.mod/pkg/timoni.sh/core/v1alpha1/semver.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2023 Stefan Prodan
// SPDX-License-Identifier: Apache-2.0

package v1alpha1

import (
"strconv"
"strings"
)

// SemVer validates the input version string and extracts the major and minor version numbers.
// When Minimum is set, the major and minor parts must be greater or equal to the minimum
// or a validation error is returned.
#SemVer: {
// Input version string in strict semver format.
#Version!: string & =~"^\\d+\\.\\d+\\.\\d+(-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$"

// Minimum is the minimum allowed MAJOR.MINOR version.
#Minimum: *"0.0.0" | string & =~"^\\d+\\.\\d+\\.\\d+(-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$"

let minMajor = strconv.Atoi(strings.Split(#Minimum, ".")[0])
let minMinor = strconv.Atoi(strings.Split(#Minimum, ".")[1])

major: int & >=minMajor
major: strconv.Atoi(strings.Split(#Version, ".")[0])

minor: int & >=minMinor
minor: strconv.Atoi(strings.Split(#Version, ".")[1])
}
Loading