stefanprodan / timoni

Timoni is a package manager for Kubernetes, powered by CUE and inspired by Helm.
https://timoni.sh
Apache License 2.0
1.51k stars 67 forks source link

Add `#MetaComponent` generator to Timoni's CUE schemas #270

Closed stefanprodan closed 8 months ago

stefanprodan commented 9 months ago

This PR adds generators for Kubernetes object metadata that can be used to set a prefix to the metadata.name and injects the app.kubernetes.io/component label.

The #MetaComponent exposes a #LabelSelector property that can be used for selector.matchLabels and template.metadata.labels to set the app.kubernetes.io/name and app.kubernetes.io/component labels.

Example:

#Frontend: appsv1.#Deployment & {
    _config: #Config
    _meta: timoniv1.#MetaComponent & {
        #Meta:      _config.metadata
        #Component: "frontend"
    }
    apiVersion: "apps/v1"
    kind:       "Deployment"
    metadata:   _meta
    spec: appsv1.#DeploymentSpec & {
        replicas: _config.replicas
        selector: matchLabels: _meta.#LabelSelector
        template: {
            metadata: {
                labels: _meta.#LabelSelector
            }
            spec: corev1.#PodSpec & {...}
        }
    }
}

The #MetaClusterComponent can be used for non-namespaced objects such as ClusterRole.

Nalum commented 9 months ago

This is great, thanks @stefanprodan ! :bow:

The following spec:

package templates

import (
        appsv1 "k8s.io/api/apps/v1"
        timoniv1 "timoni.sh/core/v1alpha1"
)

#Deployment: appsv1.#Deployment & {
        _config:    #Config
        _component: string
        _strategy:  appsv1.#DeploymentStrategy
        _prometheus?: {...}

        apiVersion: "apps/v1"
        kind:       "Deployment"

        metadata: timoniv1.#MetaComponent & {
                #Meta:      _config.metadata
                #Component: _component
        }

        spec: appsv1.#DeploymentSpec & {
                replicas: _config.replicaCount
                selector: matchLabels: _config.selector.labels

                if _strategy != _|_ {
                        strategy: _strategy
                }

                template: {
                        metadata: labels: _config.metadata.labels

                        if _config.metadata.annotations != _|_ {
                                metadata: annotations: _config.metadata.annotations
                        }

                        if _prometheus != _|_ && _prometheus.serviceMonitor == _|_ {
                                metadata: annotations: "prometheus.io/path":   "/metrics"
                                metadata: annotations: "prometheus.io/scrape": "true"
                                metadata: annotations: "prometheus.io/port":   "9402"
                        }

                        spec: {
                                if _config.serviceAccount != _|_ {
                                        serviceAccountName: _config.serviceAccount.name
                                }
                        }
                }
        }
}

Resulted in the expected out:

metadata:
  name: cert-manager-controller
  namespace: cert-manager
  labels:
    app.kubernetes.io/name: cert-manager
    app.kubernetes.io/version: v1.13.2
    app.kubernetes.io/managed-by: Timoni
    app.kubernetes.io/component: controller
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: cert-manager
  template:
    metadata:
      labels:
        app.kubernetes.io/name: cert-manager
        app.kubernetes.io/version: v1.13.2
        app.kubernetes.io/managed-by: Timoni
      annotations:
        prometheus.io/path: /metrics
        prometheus.io/scrape: "true"
        prometheus.io/port: "9402"
    spec:
      containers: []
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
kind: Deployment
apiVersion: apps/v1
---
metadata:
  name: cert-manager-webhook
  namespace: cert-manager
  labels:
    app.kubernetes.io/name: cert-manager
    app.kubernetes.io/version: v1.13.2
    app.kubernetes.io/managed-by: Timoni
    app.kubernetes.io/component: webhook
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: cert-manager
  template:
    metadata:
      labels:
        app.kubernetes.io/name: cert-manager
        app.kubernetes.io/version: v1.13.2
        app.kubernetes.io/managed-by: Timoni
    spec:
      containers: []
kind: Deployment
apiVersion: apps/v1
stefanprodan commented 9 months ago

We need a generator for the selector too, as now both deployments select the same pods.

Nalum commented 9 months ago

Yeah, I removed the component label from the selector. Would a selector label set in that meta component definition make sense?

Nalum commented 9 months ago

I can look at building up a #SelectorComponent if you want to merge this?