Skip to content

Commit 1024537

Browse files
authored
Merge pull request #282 from stefanprodan/update-redis
Refactor Redis module using latest schemas
2 parents c974c6f + 2913dff commit 1024537

17 files changed

+332
-99
lines changed

examples/redis/cue.mod/pkg/timoni.sh/core/v1alpha1/image.cue

+58-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33

44
package v1alpha1
55

6-
import "strings"
6+
import (
7+
"encoding/base64"
8+
"strings"
9+
)
710

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

28+
// PullPolicy defines the pull policy for the image.
29+
// By default, it is set to IfNotPresent.
30+
pullPolicy: *"IfNotPresent" | "Always" | "Never"
31+
2532
// Reference is the image address computed from repository, tag and digest
2633
// in the format [REPOSITORY]:[TAG]@[DIGEST].
2734
reference: string
@@ -42,3 +49,53 @@ import "strings"
4249
reference: "\(repository):latest"
4350
}
4451
}
52+
53+
// ImagePullSecret is a generator for Kubernetes Secrets of type kubernetes.io/dockerconfigjson.
54+
// Spec: https://kubernetes.io/docs/concepts/configuration/secret/#docker-config-secrets.
55+
#ImagePullSecret: {
56+
// Metadata is the Kubernetes object's metadata generated by Timoni.
57+
meta=metadata: #Metadata
58+
59+
// Registry is the hostname of the container registry in the format [HOST[:PORT_NUMBER]].
60+
registry!: string
61+
62+
// Username is the username used to authenticate to the container registry.
63+
username!: string
64+
65+
// Password is the password used to authenticate to the container registry.
66+
password!: string
67+
68+
// Optional suffix used to generate the Secret name.
69+
suffix: *"" | string
70+
71+
let auth = base64.Encode(null, username+":"+password)
72+
73+
// The object is a read-only struct that contains the generated
74+
// Kubernetes Secret of type kubernetes.io/dockerconfigjson.
75+
object: {
76+
apiVersion: "v1"
77+
kind: "Secret"
78+
type: "kubernetes.io/dockerconfigjson"
79+
metadata: {
80+
name: meta.name + suffix
81+
namespace: meta.namespace
82+
labels: meta.labels
83+
if meta.annotations != _|_ {
84+
annotations: meta.annotations
85+
}
86+
}
87+
stringData: {
88+
".dockerconfigjson": #"""
89+
{
90+
"auths": {
91+
"\#(registry)": {
92+
"username": "\#(username)",
93+
"password": "\#(password)",
94+
"auth": "\#(auth)"
95+
}
96+
}
97+
}
98+
"""#
99+
}
100+
}
101+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2023 Stefan Prodan
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package v1alpha1
5+
6+
import "strings"
7+
8+
// InstanceName defines the schema for the name of a Timoni instance.
9+
// The instance name is used as a Kubernetes label value and must be 63 characters or less.
10+
#InstanceName: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MinRunes(1) & strings.MaxRunes(63)
11+
12+
// InstanceNamespace defines the schema for the namespace of a Timoni instance.
13+
// The instance namespace is used as a Kubernetes label value and must be 63 characters or less.
14+
#InstanceNamespace: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MinRunes(1) & strings.MaxRunes(63)
15+
16+
// InstanceOwnerReference defines the schema for Kubernetes labels used to denote ownership.
17+
#InstanceOwnerReference: {
18+
#Name: "instance.timoni.sh/name"
19+
#Namespace: "instance.timoni.sh/namespace"
20+
}
21+
22+
// InstanceModule defines the schema for the Module of a Timoni instance.
23+
#InstanceModule: {
24+
url: string & =~"^((oci|file)://.*)$"
25+
version: *"latest" | string
26+
digest?: string
27+
}

examples/redis/cue.mod/pkg/timoni.sh/core/v1alpha1/metadata.cue

+86-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ package v1alpha1
55

66
import "strings"
77

8+
// Annotations defines the schema for Kubernetes object metadata annotations.
9+
#Annotations: {[string & strings.MaxRunes(253)]: string}
10+
11+
// Labels defines the schema for Kubernetes object metadata labels.
12+
#Labels: {[string & strings.MaxRunes(253)]: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)}
13+
14+
#StdLabelName: "app.kubernetes.io/name"
15+
#StdLabelVersion: "app.kubernetes.io/version"
16+
#StdLabelPartOf: "app.kubernetes.io/part-of"
17+
#StdLabelManagedBy: "app.kubernetes.io/managed-by"
18+
#StdLabelComponent: "app.kubernetes.io/component"
19+
#StdLabelInstance: "app.kubernetes.io/instance"
20+
821
// Metadata defines the schema for Kubernetes object metadata.
922
#Metadata: {
1023
// Version should be in the strict semver format. Is required when creating resources.
@@ -13,24 +26,90 @@ import "strings"
1326
// Name must be unique within a namespace. Is required when creating resources.
1427
// Name is primarily intended for creation idempotence and configuration definition.
1528
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names
16-
name!: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)
29+
name!: #InstanceName
1730

1831
// Namespace defines the space within which each name must be unique.
1932
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces
20-
namespace!: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)
33+
namespace!: #InstanceNamespace
2134

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

2740
// Map of string keys and values that can be used to organize and categorize (scope and select) objects.
2841
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
29-
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)}
42+
labels: #Labels
3043

31-
// Standard Kubernetes labels: app name and version.
44+
// Standard Kubernetes labels: app name, version and managed-by.
3245
labels: {
33-
"app.kubernetes.io/name": name
34-
"app.kubernetes.io/version": #Version
46+
"\(#StdLabelName)": name
47+
"\(#StdLabelVersion)": #Version
48+
"\(#StdLabelManagedBy)": "Timoni"
49+
}
50+
51+
// LabelSelector selects Pods based on the app.kubernetes.io/name label.
52+
#LabelSelector: #Labels & {
53+
"\(#StdLabelName)": name
54+
}
55+
}
56+
57+
// MetaComponent generates the Kubernetes object metadata for a module namespaced component.
58+
// The metadata.name is composed of the instance name and the component name.
59+
// The metadata.labels contain the app.kubernetes.io/component label.
60+
#MetaComponent: {
61+
// Meta is the Kubernetes object's metadata generated by Timoni.
62+
#Meta!: #Metadata
63+
64+
// Component is the name of the component used
65+
// as a suffix for the generate object name.
66+
#Component!: string & strings.MaxRunes(30)
67+
68+
name: #Meta.name + "-" + #Component
69+
namespace: #Meta.namespace
70+
71+
labels: #Meta.labels
72+
labels: "\(#StdLabelComponent)": #Component
73+
74+
annotations?: #Annotations
75+
if #Meta.annotations != _|_ {
76+
annotations: #Meta.annotations
77+
}
78+
79+
// LabelSelector selects Pods based on the app.kubernetes.io/name
80+
// and app.kubernetes.io/component labels.
81+
#LabelSelector: #Labels & {
82+
"\(#StdLabelComponent)": #Component
83+
"\(#StdLabelName)": #Meta.name
84+
}
85+
}
86+
87+
// MetaClusterComponent generates the Kubernetes object metadata for a module non-namespaced component.
88+
// The metadata.name is composed of the instance name and the component name.
89+
// The metadata.namespace is unset.
90+
// The metadata.labels contain the app.kubernetes.io/component label.
91+
#MetaClusterComponent: {
92+
// Meta is the Kubernetes object's metadata generated by Timoni.
93+
#Meta!: #Metadata
94+
95+
// Component is the name of the component used
96+
// as a suffix for the generate object name.
97+
#Component!: string & strings.MaxRunes(30)
98+
99+
name: #Meta.name + "-" + #Component
100+
101+
labels: #Meta.labels
102+
labels: "\(#StdLabelComponent)": #Component
103+
104+
annotations?: #Annotations
105+
if #Meta.annotations != _|_ {
106+
annotations: #Meta.annotations
107+
}
108+
109+
// LabelSelector selects Pods based on the app.kubernetes.io/name
110+
// and app.kubernetes.io/component labels.
111+
#LabelSelector: #Labels & {
112+
"\(#StdLabelComponent)": #Component
113+
"\(#StdLabelName)": #Meta.name
35114
}
36115
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2023 Stefan Prodan
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package v1alpha1
5+
6+
import (
7+
"strconv"
8+
"strings"
9+
)
10+
11+
// CPUQuantity is a string that is validated as a quantity of CPU, such as 100m or 2000m.
12+
#CPUQuantity: string & =~"^[1-9]\\d*m$"
13+
14+
// MemoryQuantity is a string that is validated as a quantity of memory, such as 128Mi or 2Gi.
15+
#MemoryQuantity: string & =~"^[1-9]\\d*(Mi|Gi)$"
16+
17+
// ResourceRequirement defines the schema for the CPU and Memory resource requirements.
18+
#ResourceRequirement: {
19+
cpu?: #CPUQuantity
20+
memory?: #MemoryQuantity
21+
}
22+
23+
// ResourceRequirements defines the schema for the compute resource requirements of a container.
24+
// More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/.
25+
#ResourceRequirements: {
26+
// Limits describes the maximum amount of compute resources allowed.
27+
limits?: #ResourceRequirement
28+
29+
// Requests describes the minimum amount of compute resources required.
30+
// Requests cannot exceed Limits.
31+
requests?: #ResourceRequirement & {
32+
if limits != _|_ {
33+
if limits.cpu != _|_ {
34+
_lc: strconv.Atoi(strings.Split(limits.cpu, "m")[0])
35+
_rc: strconv.Atoi(strings.Split(requests.cpu, "m")[0])
36+
#cpu: int & >=_rc & _lc
37+
}
38+
}
39+
}
40+
}

examples/redis/cue.mod/pkg/timoni.sh/core/v1alpha1/selector.cue

+4-5
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@
33

44
package v1alpha1
55

6-
import "strings"
7-
86
// Selector defines the schema for Kubernetes Pod label selector used in Deployments, Services, Jobs, etc.
7+
// Depreacted in favor of #Metadata.#LabelSelector
98
#Selector: {
109
// Name must be unique within a namespace. Is required when creating resources.
1110
// Name is primarily intended for creation idempotence and configuration definition.
1211
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names
13-
#Name!: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MinRunes(1) & strings.MaxRunes(63)
12+
#Name!: #InstanceName
1413

1514
// Map of string keys and values that can be used to organize and categorize (scope and select) objects.
1615
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
17-
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)}
16+
labels: #Labels
1817

1918
// Standard Kubernetes label: app name.
20-
labels: "app.kubernetes.io/name": #Name
19+
labels: "\(#StdLabelName)": #Name
2120
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2023 Stefan Prodan
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package v1alpha1
5+
6+
import (
7+
"strconv"
8+
"strings"
9+
)
10+
11+
// SemVer validates the input version string and extracts the major and minor version numbers.
12+
// When Minimum is set, the major and minor parts must be greater or equal to the minimum
13+
// or a validation error is returned.
14+
#SemVer: {
15+
// Input version string in strict semver format.
16+
#Version!: string & =~"^\\d+\\.\\d+\\.\\d+(-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$"
17+
18+
// Minimum is the minimum allowed MAJOR.MINOR version.
19+
#Minimum: *"0.0.0" | string & =~"^\\d+\\.\\d+\\.\\d+(-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$"
20+
21+
let minMajor = strconv.Atoi(strings.Split(#Minimum, ".")[0])
22+
let minMinor = strconv.Atoi(strings.Split(#Minimum, ".")[1])
23+
24+
major: int & >=minMajor
25+
major: strconv.Atoi(strings.Split(#Version, ".")[0])
26+
27+
minor: int & >=minMinor
28+
minor: strconv.Atoi(strings.Split(#Version, ".")[1])
29+
}

examples/redis/debug_tool.cue

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ import (
99
_resources: timoni.apply.master + timoni.apply.replica + timoni.apply.test
1010

1111
// The build command generates the Kubernetes manifests and prints the multi-docs YAML to stdout.
12-
// Example 'cue cmd -t debug -t name=test -t namespace=test -t mv=1.0.0 -t kv=1.28.0 build'.
12+
// Example 'cue cmd -t debug -t name=redis -t namespace=test -t mv=1.0.0 -t kv=1.28.0 build'.
1313
command: build: {
1414
task: print: cli.Print & {
1515
text: yaml.MarshalStream(_resources)
1616
}
1717
}
1818

1919
// The ls command prints a table with the Kubernetes resources kind, namespace, name and version.
20-
// Example 'cue cmd -t debug -t name=test -t namespace=test -t mv=1.0.0 -t kv=1.28.0 ls'.
20+
// Example 'cue cmd -t debug -t name=redis -t namespace=test -t mv=1.0.0 -t kv=1.28.0 ls'.
2121
command: ls: {
2222
task: print: cli.Print & {
2323
text: tabwriter.Write([

examples/redis/debug_values.cue

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
package main
44

55
// Values used by debug_tool.cue.
6-
// Debug example 'cue cmd -t debug -t name=test -t namespace=test -t mv=1.0.0 -t kv=1.28.0 build'.
6+
// Debug example 'cue cmd -t debug -t name=redis -t namespace=test -t mv=1.0.0 -t kv=1.28.0 build'.
77
values: {
88
podAnnotations: "cluster-autoscaler.kubernetes.io/safe-to-evict": "true"
99
image: {
1010
repository: "docker.io/redis"
1111
tag: "7-alpine"
1212
digest: ""
1313
}
14+
test: enabled: true
1415
}

0 commit comments

Comments
 (0)