Merge pull request #192 from stefanprodan/cue-refac

Refactor CUE module
This commit is contained in:
Stefan Prodan
2022-04-18 09:44:21 +03:00
committed by GitHub
14 changed files with 191 additions and 992 deletions
+1 -1
View File
@@ -92,7 +92,7 @@ swagger:
.PHONY: cue-mod
cue-mod:
@cd cue && cue get go k8s.io/api/... && cue get go github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1
@cd cue && cue get go k8s.io/api/...
.PHONY: cue-gen
cue-gen:
+40 -7
View File
@@ -1,22 +1,55 @@
# CUE Demo
# Podinfo CUE module
This directory contains a [cuelang module](https://cuelang.org/docs/) and tooling to generate podinfo resources.
This directory contains a [CUE](https://cuelang.org/docs/) module and tooling
for generating podinfo's Kubernetes resources.
It defines a `podinfo.#Application` definition which takes a `podinfo.#Config` as input.
The `podinfo.#Config` definition is modelled on the `podinfo` Helm chart `values.yaml` file.
The module contains a `podinfo.#Application` definition which takes `podinfo.#Config` as input.
## Prerequisites
Generate the Kubernetes API definitions required by podinfo with:
Install CUE with:
```shell
brew install cue
```
Generate the Kubernetes API definitions required by this module with:
```shell
cue get go k8s.io/api/...
cue get go github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1
```
## Configuration
Configure the application in `main.cue`.
Configure the application in `main.cue`:
```cue
app: podinfo.#Application & {
config: {
meta: {
name: "podinfo"
namespace: "default"
}
image: tag: "6.1.3"
resources: requests: {
cpu: "100m"
memory: "16Mi"
}
hpa: {
enabled: true
maxReplicas: 3
}
ingress: {
enabled: true
className: "nginx"
host: "podinfo.example.com"
tls: true
annotations: "cert-manager.io/cluster-issuer": "letsencrypt"
}
serviceMonitor: enabled: true
}
}
```
## Generate the manifests
+7 -10
View File
@@ -3,24 +3,21 @@ module github.com/stefanprodan/podinfo/cue
go 1.17
require (
github.com/cert-manager/cert-manager v1.8.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/logr v1.2.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/go-cmp v0.5.7 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/go-cmp v0.5.5 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
golang.org/x/net v0.0.0-20220412020605-290c469a71a5 // indirect
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/api v0.23.5 // indirect
k8s.io/apiextensions-apiserver v0.23.4 // indirect
k8s.io/apimachinery v0.23.5 // indirect
k8s.io/klog/v2 v2.60.1 // indirect
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
sigs.k8s.io/gateway-api v0.4.1 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
k8s.io/klog/v2 v2.30.0 // indirect
k8s.io/utils v0.0.0-20211116205334-6203023598ed // indirect
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
)
-786
View File
File diff suppressed because it is too large Load Diff
+20 -14
View File
@@ -4,24 +4,30 @@ import (
podinfo "github.com/stefanprodan/podinfo/cue/podinfo"
)
resources: (podinfo.#Application & {
input: {
app: podinfo.#Application & {
config: {
meta: {
name: "podinfo"
annotations: {
"app.kubernetes.io/part-of": "podinfo"
}
name: "podinfo"
namespace: "default"
}
image: {
repository: "ghcr.io/stefanprodan/podinfo"
tag: "6.1.3"
image: tag: "6.1.3"
resources: requests: {
cpu: "100m"
memory: "16Mi"
}
resources: requests: cpu: "100m"
hpa: {
enabled: true
minReplicas: 2
maxReplicas: 4
cpu: 99
maxReplicas: 3
}
ingress: {
enabled: true
className: "nginx"
host: "podinfo.example.com"
tls: true
annotations: "cert-manager.io/cluster-issuer": "letsencrypt"
}
serviceMonitor: enabled: true
}
}).out
}
objects: app.objects
+1 -1
View File
@@ -7,6 +7,6 @@ import (
command: gen: {
task: print: cli.Print & {
text: yaml.MarshalStream([ for x in resources {x}])
text: yaml.MarshalStream([ for x in objects {x}])
}
}
+18 -13
View File
@@ -1,21 +1,26 @@
package podinfo
#Application: {
input: #Config
out: {
sa: #ServiceAccount & {_config: input}
deploy: #Deployment & {
_config: input
_serviceAccount: sa.metadata.name
config: #Config
objects: {
service: #Service & {_config: config}
account: #ServiceAccount & {_config: config}
deployment: #Deployment & {
_config: config
_serviceAccount: account.metadata.name
}
service: #Service & {_config: input}}
if input.hpa.enabled == true {
out: hpa: #HorizontalPodAutoscaler & {_config: input}
}
if input.serviceMonitor.enabled == true {
out: serviceMonitor: #ServiceMonitor & {_config: input}
if config.hpa.enabled == true {
objects: hpa: #HorizontalPodAutoscaler & {_config: config}
}
if input.ingress.enabled == true {
out: ingress: #Ingress & {_config: input}
if config.ingress.enabled == true {
objects: ingress: #Ingress & {_config: config}
}
if config.serviceMonitor.enabled == true {
objects: serviceMonitor: #ServiceMonitor & {_config: config}
}
}
-24
View File
@@ -1,24 +0,0 @@
package podinfo
import (
certmanv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
"encoding/yaml"
)
#certConfig: {
dnsNames: [string]
tlsSecretName: string
issuerRef: string
}
#Certificate: certmanv1.#Certificate & {
_config: #Config
apiVersion: "v1"
kind: "Certificate"
metadata: _config.meta
spec: certmanv1.#CertificateSpec & {
dnsNames: _config.cert.dnsNames
secretName: _config.cert.tlsSecretName
issuerRef: yaml.Marshal(_config.cert.issuerRef)
}
}
+22 -40
View File
@@ -6,54 +6,36 @@ import (
)
#Config: {
meta: metav1.#ObjectMeta
meta: metav1.#ObjectMeta
hpa: #hpaConfig
ingress: #ingressConfig
service: #serviceConfig
serviceMonitor: #serviceMonConfig
image: {
repository: *"ghcr.io/stefanprodan/podinfo" | string
tag: string
pullPolicy: *"IfNotPresent" | string
tag: string
}
selectorLabels: {
"app.kubernetes.io/name": meta.name
}
replicas: *1 | int
service: #serviceConfig
host: string
cache: string
backends: [string]
cache?: string & =~"^tcp://"
backends: [...string]
logLevel: *"info" | string
faults: {
delay: *false | bool
error: *false | bool
unhealthy: *false | bool
unready: *false | bool
}
h2c: {
enabled: *false | bool
}
ui: {
color: *"#34577c" | string
message: *"" | string
logo: *"" | string
}
podAnnotations: {[ string]: string}
securityContext: corev1.#PodSecurityContext
resources: *{
replicas: *1 | int
resources: *{
requests: {
cpu: "1m"
memory: "16Mi"
}
limits: memory: "128Mi"
} | corev1.#ResourceRequirements
nodeSelector: {[ string]: string}
affinity: corev1.#Affinity
tolerations: [ ...corev1.#Toleration]
tls: {
enabled: *false | bool
port: *9899 | int
certPath: *"/data/cert" | string
secretName: *"" | string
}
cert: #certConfig
hpa: #hpaConfig
ingress: #ingressConfig
serviceMonitor: #serviceMonConfig
selectorLabels: *{"app.kubernetes.io/name": meta.name} | {[ string]: string}
meta: annotations: *{"app.kubernetes.io/version": "\(image.tag)"} | {[ string]: string}
meta: labels: *selectorLabels | {[ string]: string}
securityContext?: corev1.#PodSecurityContext
affinity?: corev1.#Affinity
tolerations?: [ ...corev1.#Toleration]
}
+28 -41
View File
@@ -12,7 +12,7 @@ import (
kind: "Deployment"
metadata: _config.meta
spec: appsv1.#DeploymentSpec & {
if _config.hpa.enabled == false {
if !_config.hpa.enabled {
replicas: _config.replicas
}
strategy: {
@@ -23,29 +23,33 @@ import (
template: {
metadata: {
labels: _config.selectorLabels
annotations: {
"prometheus.io/scrape": "true"
"prometheus.io/port": "\(_config.service.metricsPort)"
_config.podAnnotations
if !_config.serviceMonitor.enabled {
annotations: {
"prometheus.io/scrape": "true"
"prometheus.io/port": "\(_config.service.metricsPort)"
}
}
}
spec: corev1.#PodSpec & {
terminationGracePeriodSeconds: 30
terminationGracePeriodSeconds: 15
serviceAccountName: _serviceAccount
containers: [
{
name: "podinfo"
image: "\(_config.image.repository):\(_config.image.tag)"
imagePullPolicy: _config.image.pullPolicy
securityContext: _config.securityContext
command: [
"./podinfo",
"--port=\(_config.service.httpPort)",
"--port-metrics=\(_config.service.metricsPort)",
"--grpc-port=\(_config.service.grpcPort)",
"--level=\(_config.logLevel)",
"--random-delay=\(_config.faults.delay)",
"--random-error=\(_config.faults.error)",
if _config.cache != _|_ {
"--cache-server=\(_config.cache)"
},
for b in _config.backends {
"--backend-url=\(b)"
},
]
ports: [
{
@@ -65,57 +69,40 @@ import (
},
]
livenessProbe: {
exec: {
command: [
"podcli",
"check",
"http",
"localhost:\(_config.service.httpPort)/healthz",
]
httpGet: {
path: "/healthz"
port: "http"
}
initialDelaySeconds: 1
timeoutSeconds: 5
}
readinessProbe: {
exec: {
command: [
"podcli",
"check",
"http",
"localhost:\(_config.service.httpPort)/readyz",
]
httpGet: {
path: "/readyz"
port: "http"
}
initialDelaySeconds: 1
timeoutSeconds: 5
}
volumeMounts: [
{
name: "data"
mountPath: "/data"
},
if _config.tls.secretName != "" {
name: "tls"
mountPath: _config.tls.certPath
readOnly: true
},
]
resources: _config.resources
if _config.securityContext != _|_ {
securityContext: _config.securityContext
}
},
]
nodeSelector: _config.nodeSelector
affinity: _config.affinity
tolerations: _config.tolerations
if _config.affinity != _|_ {
affinity: _config.affinity
}
if _config.tolerations != _|_ {
tolerations: _config.tolerations
}
volumes: [
{
name: "data"
emptyDir: {}
},
if _config.tls.secretName != "" {
name: "tls"
secret: {
secretName: _config.tls.secretName
}
},
]
}
}
+3 -3
View File
@@ -6,10 +6,10 @@ import (
#hpaConfig: {
enabled: *false | bool
cpu: *0 | int
cpu: *99 | int
memory: *"" | string
minReplicas: int
maxReplicas: int
minReplicas: *1 | int
maxReplicas: *1 | int
}
#HorizontalPodAutoscaler: autoscaling.#HorizontalPodAutoscaler & {
+29 -30
View File
@@ -5,21 +5,11 @@ import (
)
#ingressConfig: {
svcName: string
svcPort: int
enabled: *false | bool
className: *"" | string
tls: [{
hosts: [string]
secretName: string
}]
hosts: [{
host: "podinfo.local"
paths: [{
path: "/"
pathType: "ImplementationSpecific"
}]
}]
enabled: *false | bool
annotations?: {[ string]: string}
className?: string
tls: *false | bool
host: string
}
#Ingress: netv1.#Ingress & {
@@ -27,22 +17,31 @@ import (
apiVersion: "networking.k8s.io/v1"
kind: "Ingress"
metadata: _config.meta
spec: netv1.#IngressSpec & {
ingressClassName: _config.ingress.className
tls: [ for t in _config.ingress.tls {
hosts: t.hosts
secretName: t.secretName
if _config.ingress.annotations != _|_ {
metadata: annotations: _config.ingress.annotations
}
spec: netv1.#IngressSpec & {
rules: [{
host: _config.ingress.host
http: {
paths: [{
pathType: "Prefix"
path: "/"
backend: service: {
name: _config.meta.name
port: name: "http"
}
}]
}
}]
rules: [ for h in _config.ingress.hosts {
host: h.host
http: paths: [ for p in h.paths {
path: p.path
pathType: p.pathType
backend: service: {
name: _config.meta.name
port: number: _config.service.externalPort
}
if _config.ingress.tls {
tls: [{
hosts: [_config.ingress.host]
secretName: "\(_config.meta.name)-cert"
}]
}]
}
if _config.ingress.className != _|_ {
ingressClassName: _config.ingress.className
}
}
}
+20 -19
View File
@@ -10,8 +10,6 @@ import (
httpPort: *9898 | int
metricsPort: *9797 | int
grpcPort: *9999 | int
grpcService: "podinfo" | string
nodePort: *31198 | int
}
#Service: corev1.#Service & {
@@ -20,24 +18,27 @@ import (
kind: "Service"
metadata: _config.meta
spec: corev1.#ServiceSpec & {
type: "ClusterIP"
type: _config.service.type
selector: _config.selectorLabels
ports: [{
name: "http"
port: _config.service.externalPort
targetPort: _config.service.httpPort
protocol: "TCP"
}, if _config.tls.enabled == true {
name: "https"
port: _config.tls.port
targetPort: "https"
protocol: "TCP"
}, if _config.service.grpcPort != _|_ {
name: "grpc"
port: _config.service.grpcPort
targetPort: "grpc"
protocol: "TCP"
},
ports: [
{
name: "http"
port: _config.service.externalPort
targetPort: "\(name)"
protocol: "TCP"
},
{
name: "http-metrics"
port: _config.service.metricsPort
targetPort: "\(name)"
protocol: "TCP"
},
{
name: "grpc"
port: _config.service.grpcPort
targetPort: "\(name)"
protocol: "TCP"
},
]
}
}
+2 -3
View File
@@ -3,7 +3,6 @@ package podinfo
#serviceMonConfig: {
enabled: *false | bool
interval: *"15s" | string
matchLabels: {}
}
#ServiceMonitor: {
@@ -14,10 +13,10 @@ package podinfo
spec: {
endpoints: [{
path: "/metrics"
port: "http"
port: "http-metrics"
interval: _config.serviceMonitor.interval
}]
namespaceSelector: matchNames: _config.meta.namespace
selector: matchLabels: _config.selectorLabels
selector: matchLabels: _config.meta.labels
}
}