├── cue.mod ├── module.cue ├── gen │ ├── k8s.io │ │ ├── api │ │ │ ├── core │ │ │ │ └── v1 │ │ │ │ │ ├── register_go_gen.cue │ │ │ │ │ ├── doc_go_gen.cue │ │ │ │ │ ├── well_known_taints_go_gen.cue │ │ │ │ │ ├── well_known_labels_go_gen.cue │ │ │ │ │ └── annotation_key_constants_go_gen.cue │ │ │ ├── apps │ │ │ │ └── v1 │ │ │ │ │ └── register_go_gen.cue │ │ │ ├── batch │ │ │ │ └── v1 │ │ │ │ │ └── register_go_gen.cue │ │ │ ├── policy │ │ │ │ └── v1 │ │ │ │ │ ├── register_go_gen.cue │ │ │ │ │ └── doc_go_gen.cue │ │ │ ├── node │ │ │ │ └── v1 │ │ │ │ │ ├── register_go_gen.cue │ │ │ │ │ └── types_go_gen.cue │ │ │ ├── events │ │ │ │ └── v1 │ │ │ │ │ ├── register_go_gen.cue │ │ │ │ │ └── types_go_gen.cue │ │ │ ├── storage │ │ │ │ └── v1 │ │ │ │ │ └── register_go_gen.cue │ │ │ ├── autoscaling │ │ │ │ ├── v1 │ │ │ │ │ └── register_go_gen.cue │ │ │ │ └── v2 │ │ │ │ │ └── register_go_gen.cue │ │ │ ├── rbac │ │ │ │ └── v1 │ │ │ │ │ ├── register_go_gen.cue │ │ │ │ │ └── types_go_gen.cue │ │ │ ├── admission │ │ │ │ └── v1 │ │ │ │ │ └── register_go_gen.cue │ │ │ ├── discovery │ │ │ │ └── v1 │ │ │ │ │ ├── register_go_gen.cue │ │ │ │ │ └── well_known_labels_go_gen.cue │ │ │ ├── networking │ │ │ │ └── v1 │ │ │ │ │ ├── register_go_gen.cue │ │ │ │ │ └── well_known_annotations_go_gen.cue │ │ │ ├── scheduling │ │ │ │ └── v1 │ │ │ │ │ ├── register_go_gen.cue │ │ │ │ │ └── types_go_gen.cue │ │ │ ├── certificates │ │ │ │ └── v1 │ │ │ │ │ └── register_go_gen.cue │ │ │ ├── coordination │ │ │ │ └── v1 │ │ │ │ │ ├── register_go_gen.cue │ │ │ │ │ └── types_go_gen.cue │ │ │ ├── authorization │ │ │ │ └── v1 │ │ │ │ │ └── register_go_gen.cue │ │ │ ├── authentication │ │ │ │ └── v1 │ │ │ │ │ └── register_go_gen.cue │ │ │ ├── flowcontrol │ │ │ │ └── v1 │ │ │ │ │ ├── register_go_gen.cue │ │ │ │ │ └── doc_go_gen.cue │ │ │ └── admissionregistration │ │ │ │ └── v1 │ │ │ │ ├── register_go_gen.cue │ │ │ │ └── doc_go_gen.cue │ │ ├── apimachinery │ │ │ └── pkg │ │ │ │ ├── runtime │ │ │ │ ├── embedded_go_gen.cue │ │ │ │ ├── types_proto_go_gen.cue │ │ │ │ ├── conversion_go_gen.cue │ │ │ │ ├── allocator_go_gen.cue │ │ │ │ ├── converter_go_gen.cue │ │ │ │ ├── negotiate_go_gen.cue │ │ │ │ ├── swagger_doc_generator_go_gen.cue │ │ │ │ ├── splice_go_gen.cue │ │ │ │ ├── helper_go_gen.cue │ │ │ │ ├── codec_go_gen.cue │ │ │ │ ├── doc_go_gen.cue │ │ │ │ ├── types_go_gen.cue │ │ │ │ └── interfaces_go_gen.cue │ │ │ │ ├── types │ │ │ │ ├── doc_go_gen.cue │ │ │ │ ├── namespacedname_go_gen.cue │ │ │ │ ├── uid_go_gen.cue │ │ │ │ ├── patch_go_gen.cue │ │ │ │ └── nodename_go_gen.cue │ │ │ │ ├── apis │ │ │ │ └── meta │ │ │ │ │ └── v1 │ │ │ │ │ ├── register_go_gen.cue │ │ │ │ │ ├── duration_go_gen.cue │ │ │ │ │ ├── micro_time_go_gen.cue │ │ │ │ │ ├── time_go_gen.cue │ │ │ │ │ ├── time_proto_go_gen.cue │ │ │ │ │ ├── watch_go_gen.cue │ │ │ │ │ ├── meta_go_gen.cue │ │ │ │ │ └── group_version_go_gen.cue │ │ │ │ ├── watch │ │ │ │ ├── doc_go_gen.cue │ │ │ │ ├── filter_go_gen.cue │ │ │ │ ├── streamwatcher_go_gen.cue │ │ │ │ ├── mux_go_gen.cue │ │ │ │ └── watch_go_gen.cue │ │ │ │ ├── api │ │ │ │ └── resource │ │ │ │ │ ├── suffix_go_gen.cue │ │ │ │ │ ├── math_go_gen.cue │ │ │ │ │ ├── amount_go_gen.cue │ │ │ │ │ └── quantity_go_gen.cue │ │ │ │ └── util │ │ │ │ └── intstr │ │ │ │ └── intstr_go_gen.cue │ │ └── apiextensions-apiserver │ │ │ └── pkg │ │ │ └── apis │ │ │ └── apiextensions │ │ │ └── v1 │ │ │ ├── doc_go_gen.cue │ │ │ └── register_go_gen.cue │ └── monitoring.coreos.com │ │ ├── prometheusrule │ │ └── v1 │ │ │ └── types_gen.cue │ │ ├── podmonitor │ │ └── v1 │ │ │ └── types_gen.cue │ │ ├── servicemonitor │ │ └── v1 │ │ │ └── types_gen.cue │ │ ├── probe │ │ └── v1 │ │ │ └── types_gen.cue │ │ └── scrapeconfig │ │ └── v1alpha1 │ │ └── types_gen.cue └── pkg │ └── timoni.sh │ └── core │ └── v1alpha1 │ ├── object.cue │ ├── action.cue │ ├── selector.cue │ ├── semver.cue │ ├── instance.cue │ ├── immutable.cue │ ├── requirements.cue │ ├── image.cue │ └── metadata.cue ├── test └── data │ ├── values-rbac.cue │ ├── values-high-availability.cue │ ├── values-monitoring.cue │ ├── values-rbac-aggregate.cue │ ├── values-podSecurityAdmission.cue │ ├── values-monitoring-serviceMonitor.cue │ ├── clusterIssuer.yaml │ └── certificate.yaml ├── values.cue ├── timoni.ignore ├── templates ├── namespace.cue ├── configMap.cue ├── clusterRoleBinding.cue ├── config │ ├── images.cue │ ├── component.cue │ ├── config.cue │ └── components.cue ├── podDisruptionBudget.cue ├── podMonitor.cue ├── serviceMonitor.cue ├── service.cue ├── deploymentSpecCAInjector.cue ├── mutatingWebhook.cue ├── roleBinding.cue ├── networkPolicy.cue ├── serviceAccount.cue ├── validatingWebhook.cue ├── role.cue ├── startupAPICheckJob.cue ├── deployment.cue ├── deploymentSpecWebhook.cue ├── deploymentSpecController.cue └── instance.cue ├── .github ├── workflows │ ├── vet.yaml │ ├── release.yaml │ └── e2e.yaml └── dependabot.yml ├── debug_tool.cue ├── DCO ├── debug_values.cue ├── timoni.cue ├── .gitignore └── Makefile /cue.mod/module.cue: -------------------------------------------------------------------------------- 1 | module: "timoni.sh/cert-manager" 2 | -------------------------------------------------------------------------------- /test/data/values-rbac.cue: -------------------------------------------------------------------------------- 1 | values: rbac: enabled: false 2 | -------------------------------------------------------------------------------- /test/data/values-high-availability.cue: -------------------------------------------------------------------------------- 1 | values: highAvailability: enabled: true 2 | -------------------------------------------------------------------------------- /test/data/values-monitoring.cue: -------------------------------------------------------------------------------- 1 | values: controller: monitoring: enabled: true 2 | -------------------------------------------------------------------------------- /test/data/values-rbac-aggregate.cue: -------------------------------------------------------------------------------- 1 | values: rbac: aggregateClusterRoles: false 2 | -------------------------------------------------------------------------------- /test/data/values-podSecurityAdmission.cue: -------------------------------------------------------------------------------- 1 | values: podSecurityAdmission: mode: "audit" 2 | values: podSecurityAdmission: level: "privileged" 3 | -------------------------------------------------------------------------------- /test/data/values-monitoring-serviceMonitor.cue: -------------------------------------------------------------------------------- 1 | values: controller: monitoring: enabled: true 2 | values: controller: monitoring: type: "ServiceMonitor" 3 | -------------------------------------------------------------------------------- /test/data/clusterIssuer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: ClusterIssuer 3 | metadata: 4 | name: selfsigned-cluster-issuer 5 | spec: 6 | selfSigned: {} 7 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/core/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/core/v1 4 | 5 | package v1 6 | 7 | #GroupName: "" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/apps/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/apps/v1 4 | 5 | package v1 6 | 7 | #GroupName: "apps" 8 | -------------------------------------------------------------------------------- /values.cue: -------------------------------------------------------------------------------- 1 | // Code generated by timoni. 2 | // Note that this file must have no imports and all values must be concrete. 3 | 4 | @if(!debug) 5 | 6 | package main 7 | 8 | values: { 9 | } 10 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/batch/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/batch/v1 4 | 5 | package v1 6 | 7 | #GroupName: "batch" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/policy/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/policy/v1 4 | 5 | package v1 6 | 7 | #GroupName: "policy" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/node/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/node/v1 4 | 5 | package v1 6 | 7 | #GroupName: "node.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/events/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/events/v1 4 | 5 | package v1 6 | 7 | #GroupName: "events.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/storage/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/storage/v1 4 | 5 | package v1 6 | 7 | #GroupName: "storage.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/autoscaling/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/autoscaling/v1 4 | 5 | package v1 6 | 7 | #GroupName: "autoscaling" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/autoscaling/v2/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/autoscaling/v2 4 | 5 | package v2 6 | 7 | #GroupName: "autoscaling" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/core/v1/doc_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/core/v1 4 | 5 | // Package v1 is the v1 version of the core API. 6 | package v1 7 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/rbac/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/rbac/v1 4 | 5 | package v1 6 | 7 | #GroupName: "rbac.authorization.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/admission/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/admission/v1 4 | 5 | package v1 6 | 7 | #GroupName: "admission.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/discovery/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/discovery/v1 4 | 5 | package v1 6 | 7 | #GroupName: "discovery.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/networking/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/networking/v1 4 | 5 | package v1 6 | 7 | #GroupName: "networking.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/scheduling/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/scheduling/v1 4 | 5 | package v1 6 | 7 | #GroupName: "scheduling.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/certificates/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/certificates/v1 4 | 5 | package v1 6 | 7 | #GroupName: "certificates.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/coordination/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/coordination/v1 4 | 5 | package v1 6 | 7 | #GroupName: "coordination.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/embedded_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | package runtime 6 | 7 | _#encodable: _ 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/authorization/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/authorization/v1 4 | 5 | package v1 6 | 7 | #GroupName: "authorization.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/authentication/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/authentication/v1 4 | 5 | package v1 6 | 7 | #GroupName: "authentication.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/flowcontrol/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/flowcontrol/v1 4 | 5 | package v1 6 | 7 | #GroupName: "flowcontrol.apiserver.k8s.io" 8 | -------------------------------------------------------------------------------- /timoni.ignore: -------------------------------------------------------------------------------- 1 | # VCS 2 | .git/ 3 | .gitignore 4 | .gitmodules 5 | .gitattributes 6 | 7 | # Go 8 | vendor/ 9 | go.mod 10 | go.sum 11 | 12 | # CUE 13 | *_tool.cue 14 | debug_values.cue 15 | 16 | .github 17 | Makefile 18 | test 19 | DCO 20 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/admissionregistration/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/admissionregistration/v1 4 | 5 | package v1 6 | 7 | #GroupName: "admissionregistration.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/flowcontrol/v1/doc_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/flowcontrol/v1 4 | 5 | // Package v1 holds api types of version v1 for group "flowcontrol.apiserver.k8s.io". 6 | package v1 7 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/types/doc_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/types 4 | 5 | // Package types implements various generic types used throughout kubernetes. 6 | package types 7 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/doc_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1 4 | 5 | // Package v1 is the v1 version of the API. 6 | package v1 7 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/types_proto_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | package runtime 6 | 7 | #ProtobufMarshaller: _ 8 | 9 | #ProtobufReverseMarshaller: _ 10 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1 4 | 5 | package v1 6 | 7 | #GroupName: "apiextensions.k8s.io" 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/apis/meta/v1/register_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/apis/meta/v1 4 | 5 | package v1 6 | 7 | #GroupName: "meta.k8s.io" 8 | 9 | #WatchEventKind: "WatchEvent" 10 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/watch/doc_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/watch 4 | 5 | // Package watch contains a generic watchable interface, and a fake for 6 | // testing code that uses the watch interface. 7 | package watch 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/api/resource/suffix_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/api/resource 4 | 5 | package resource 6 | 7 | _#suffix: string 8 | 9 | // suffixer can interpret and construct suffixes. 10 | _#suffixer: _ 11 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/conversion_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | // Package runtime defines conversions between generic types and structs to map query strings 6 | // to struct objects. 7 | package runtime 8 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/types/namespacedname_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/types 4 | 5 | package types 6 | 7 | #NamespacedName: { 8 | Namespace: string 9 | Name: string 10 | } 11 | 12 | #Separator: 47 // '/' 13 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/policy/v1/doc_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/policy/v1 4 | 5 | // Package policy is for any kind of policy object. Suitable examples, even if 6 | // they aren't all here, are PodDisruptionBudget, 7 | // NetworkPolicy, etc. 8 | package v1 9 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/watch/filter_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/watch 4 | 5 | package watch 6 | 7 | // Recorder records all events that are sent from the watch until it is closed. 8 | #Recorder: { 9 | Interface: #Interface 10 | } 11 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/allocator_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | package runtime 6 | 7 | // SimpleAllocator a wrapper around make([]byte) 8 | // conforms to the MemoryAllocator interface 9 | #SimpleAllocator: { 10 | } 11 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/converter_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | package runtime 6 | 7 | // UnstructuredConverter is an interface for converting between interface{} 8 | // and map[string]interface representation. 9 | #UnstructuredConverter: _ 10 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/negotiate_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | package runtime 6 | 7 | // NegotiateError is returned when a ClientNegotiator is unable to locate 8 | // a serializer for the requested operation. 9 | #NegotiateError: { 10 | ContentType: string 11 | Stream: bool 12 | } 13 | -------------------------------------------------------------------------------- /test/data/certificate.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: Certificate 3 | metadata: 4 | name: my-selfsigned-ca 5 | namespace: test 6 | spec: 7 | isCA: true 8 | commonName: my-selfsigned-ca 9 | secretName: root-secret 10 | privateKey: 11 | algorithm: ECDSA 12 | size: 256 13 | issuerRef: 14 | name: selfsigned-cluster-issuer 15 | kind: ClusterIssuer 16 | group: cert-manager.io 17 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/apis/meta/v1/duration_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/apis/meta/v1 4 | 5 | package v1 6 | 7 | // Duration is a wrapper around time.Duration which supports correct 8 | // marshaling to YAML and JSON. In particular, it marshals into strings, which 9 | // can be used as map keys in json. 10 | #Duration: _ 11 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/types/uid_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/types 4 | 5 | package types 6 | 7 | // UID is a type that holds unique ID values, including UUIDs. Because we 8 | // don't ONLY use UUIDs, this is an alias to string. Being a type captures 9 | // intent and helps make sure that UIDs and names do not get conflated. 10 | #UID: string 11 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/swagger_doc_generator_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | package runtime 6 | 7 | // Pair of strings. We keed the name of fields and the doc 8 | #Pair: { 9 | Name: string 10 | Doc: string 11 | } 12 | 13 | // KubeTypes is an array to represent all available types in a parsed file. [0] is for the type itself 14 | #KubeTypes: [...#Pair] 15 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/splice_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | package runtime 6 | 7 | // Splice is the interface that wraps the Splice method. 8 | // 9 | // Splice moves data from given slice without copying the underlying data for 10 | // efficiency purpose. Therefore, the caller should make sure the underlying 11 | // data is not changed later. 12 | #Splice: _ 13 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/admissionregistration/v1/doc_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/admissionregistration/v1 4 | 5 | // Package v1 is the v1 version of the API. 6 | // AdmissionConfiguration and AdmissionPluginConfiguration are legacy static admission plugin configuration 7 | // MutatingWebhookConfiguration and ValidatingWebhookConfiguration are for the 8 | // new dynamic admission controller configuration. 9 | package v1 10 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/apis/meta/v1 4 | 5 | package v1 6 | 7 | #RFC3339Micro: "2006-01-02T15:04:05.000000Z07:00" 8 | 9 | // MicroTime is version of Time with microsecond level precision. 10 | // 11 | // +protobuf.options.marshal=false 12 | // +protobuf.as=Timestamp 13 | // +protobuf.options.(gogoproto.goproto_stringer)=false 14 | #MicroTime: _ 15 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/watch/streamwatcher_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/watch 4 | 5 | package watch 6 | 7 | // Decoder allows StreamWatcher to watch any stream for which a Decoder can be written. 8 | #Decoder: _ 9 | 10 | // Reporter hides the details of how an error is turned into a runtime.Object for 11 | // reporting on a watch stream since this package may not import a higher level report. 12 | #Reporter: _ 13 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/api/resource/math_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/api/resource 4 | 5 | package resource 6 | 7 | // maxInt64Factors is the highest value that will be checked when removing factors of 10 from an int64. 8 | // It is also the maximum decimal digits that can be represented with an int64. 9 | _#maxInt64Factors: 18 10 | 11 | _#mostNegative: -9223372036854775808 12 | 13 | _#mostPositive: 9223372036854775807 14 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/apis/meta/v1/time_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/apis/meta/v1 4 | 5 | package v1 6 | 7 | // Time is a wrapper around time.Time which supports correct 8 | // marshaling to YAML and JSON. Wrappers are provided for many 9 | // of the factory methods that the time package offers. 10 | // 11 | // +protobuf.options.marshal=false 12 | // +protobuf.as=Timestamp 13 | // +protobuf.options.(gogoproto.goproto_stringer)=false 14 | #Time: _ 15 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/networking/v1/well_known_annotations_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/networking/v1 4 | 5 | package v1 6 | 7 | // AnnotationIsDefaultIngressClass can be used to indicate that an 8 | // IngressClass should be considered default. When a single IngressClass 9 | // resource has this annotation set to true, new Ingress resources without a 10 | // class specified will be assigned this default class. 11 | #AnnotationIsDefaultIngressClass: "ingressclass.kubernetes.io/is-default-class" 12 | -------------------------------------------------------------------------------- /cue.mod/pkg/timoni.sh/core/v1alpha1/object.cue: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Stefan Prodan 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package v1alpha1 5 | 6 | import "strings" 7 | 8 | // ObjectReference is a reference to a Kubernetes object. 9 | #ObjectReference: { 10 | // Name of the referent. 11 | name!: string & strings.MaxRunes(256) 12 | 13 | // Namespace of the referent. 14 | namespace?: string & strings.MaxRunes(256) 15 | 16 | // API version of the referent. 17 | apiVersion?: string & strings.MaxRunes(256) 18 | 19 | // Kind of the referent. 20 | kind?: string & strings.MaxRunes(256) 21 | } 22 | -------------------------------------------------------------------------------- /templates/namespace.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | corev1 "k8s.io/api/core/v1" 5 | 6 | cfg "timoni.sh/cert-manager/templates/config" 7 | ) 8 | 9 | #Namespace: corev1.#Namespace & { 10 | #config: cfg.#Config 11 | 12 | apiVersion: "v1" 13 | kind: "Namespace" 14 | metadata: { 15 | name: #config.metadata.namespace 16 | labels: #config.metadata.labels 17 | labels: "pod-security.kubernetes.io/\(#config.podSecurityAdmission.mode)": #config.podSecurityAdmission.level 18 | 19 | if #config.metadata.annotations != _|_ { 20 | annotations: #config.metadata.annotations 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/helper_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | package runtime 6 | 7 | // MultiObjectTyper returns the types of objects across multiple schemes in order. 8 | #MultiObjectTyper: [...#ObjectTyper] 9 | 10 | _#defaultFramer: { 11 | } 12 | 13 | // WithVersionEncoder serializes an object and ensures the GVK is set. 14 | #WithVersionEncoder: { 15 | Version: #GroupVersioner 16 | Encoder: #Encoder 17 | ObjectTyper: #ObjectTyper 18 | } 19 | 20 | // WithoutVersionDecoder clears the group version kind of a deserialized object. 21 | #WithoutVersionDecoder: { 22 | Decoder: #Decoder 23 | } 24 | -------------------------------------------------------------------------------- /templates/configMap.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | "encoding/yaml" 5 | corev1 "k8s.io/api/core/v1" 6 | timoniv1 "timoni.sh/core/v1alpha1" 7 | 8 | cfg "timoni.sh/cert-manager/templates/config" 9 | ) 10 | 11 | #ConfigMap: corev1.#ConfigMap & { 12 | #config: cfg.#Config 13 | #component: string 14 | 15 | #meta: timoniv1.#MetaComponent & { 16 | #Meta: #config.metadata 17 | #Component: #component 18 | } 19 | 20 | apiVersion: "v1" 21 | kind: "ConfigMap" 22 | metadata: #meta 23 | 24 | data: { 25 | if #component == "controller" { 26 | "config.yaml": yaml.Marshal(#config.controller.config) 27 | } 28 | 29 | if #component == "webhook" { 30 | "config.yaml": yaml.Marshal(#config.webhook.config) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/watch/mux_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/watch 4 | 5 | package watch 6 | 7 | // FullChannelBehavior controls how the Broadcaster reacts if a watcher's watch 8 | // channel is full. 9 | #FullChannelBehavior: int // #enumFullChannelBehavior 10 | 11 | #enumFullChannelBehavior: 12 | #WaitIfChannelFull | 13 | #DropIfChannelFull 14 | 15 | #values_FullChannelBehavior: { 16 | WaitIfChannelFull: #WaitIfChannelFull 17 | DropIfChannelFull: #DropIfChannelFull 18 | } 19 | 20 | #WaitIfChannelFull: #FullChannelBehavior & 0 21 | #DropIfChannelFull: #FullChannelBehavior & 1 22 | 23 | _#incomingQueueLength: 25 24 | 25 | _#internalRunFunctionMarker: "internal-do-function" 26 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/types/patch_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/types 4 | 5 | package types 6 | 7 | // Similarly to above, these are constants to support HTTP PATCH utilized by 8 | // both the client and server that didn't make sense for a whole package to be 9 | // dedicated to. 10 | #PatchType: string // #enumPatchType 11 | 12 | #enumPatchType: 13 | #JSONPatchType | 14 | #MergePatchType | 15 | #StrategicMergePatchType | 16 | #ApplyPatchType 17 | 18 | #JSONPatchType: #PatchType & "application/json-patch+json" 19 | #MergePatchType: #PatchType & "application/merge-patch+json" 20 | #StrategicMergePatchType: #PatchType & "application/strategic-merge-patch+json" 21 | #ApplyPatchType: #PatchType & "application/apply-patch+yaml" 22 | -------------------------------------------------------------------------------- /cue.mod/pkg/timoni.sh/core/v1alpha1/action.cue: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Stefan Prodan 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package v1alpha1 5 | 6 | // Action holds the list of annotations for controlling 7 | // Timoni's apply behaviour of Kubernetes resources. 8 | Action: { 9 | // Force annotation for recreating immutable resources such as Kubernetes Jobs. 10 | Force: { 11 | "action.timoni.sh/force": ActionStatus.Enabled 12 | } 13 | // One-off annotation for appling resources only if they don't exist on the cluster. 14 | Oneoff: { 15 | "action.timoni.sh/one-off": ActionStatus.Enabled 16 | } 17 | // Keep annotation for preventing Timoni's garbage collector from deleting resources. 18 | Keep: { 19 | "action.timoni.sh/prune": ActionStatus.Disabled 20 | } 21 | } 22 | 23 | ActionStatus: { 24 | Enabled: "enabled" 25 | Disabled: "disabled" 26 | } 27 | -------------------------------------------------------------------------------- /.github/workflows/vet.yaml: -------------------------------------------------------------------------------- 1 | name: vet 2 | 3 | on: 4 | pull_request: 5 | branches: [ main ] 6 | push: 7 | branches: [ main ] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | vet-module: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v3 18 | - name: Setup Timoni 19 | uses: stefanprodan/timoni/actions/setup@main 20 | - name: Vet Module 21 | run: | 22 | timoni mod vet --namespace cert-manager --name cert-manager ./ 23 | vet-debug-module: 24 | runs-on: ubuntu-latest 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | - name: Setup Timoni 29 | uses: stefanprodan/timoni/actions/setup@main 30 | - name: Debug Vet Module 31 | run: | 32 | timoni mod vet --debug --namespace cert-manager --name cert-manager ./ 33 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/util/intstr/intstr_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/util/intstr 4 | 5 | package intstr 6 | 7 | // IntOrString is a type that can hold an int32 or a string. When used in 8 | // JSON or YAML marshalling and unmarshalling, it produces or consumes the 9 | // inner type. This allows you to have, for example, a JSON field that can 10 | // accept a name or number. 11 | // TODO: Rename to Int32OrString 12 | // 13 | // +protobuf=true 14 | // +protobuf.options.(gogoproto.goproto_stringer)=false 15 | // +k8s:openapi-gen=true 16 | #IntOrString: _ 17 | 18 | // Type represents the stored type of IntOrString. 19 | #Type: int64 // #enumType 20 | 21 | #enumType: 22 | #Int | 23 | #String 24 | 25 | #values_Type: { 26 | Int: #Int 27 | String: #String 28 | } 29 | 30 | #Int: #Type & 0 31 | #String: #Type & 1 32 | -------------------------------------------------------------------------------- /cue.mod/pkg/timoni.sh/core/v1alpha1/selector.cue: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Stefan Prodan 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package v1alpha1 5 | 6 | // Selector defines the schema for Kubernetes Pod label selector used in Deployments, Services, Jobs, etc. 7 | #Selector: { 8 | // Name must be unique within a namespace. Is required when creating resources. 9 | // Name is primarily intended for creation idempotence and configuration definition. 10 | // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names 11 | #Name!: #InstanceName 12 | 13 | // Map of string keys and values that can be used to organize and categorize (scope and select) objects. 14 | // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels 15 | labels: #Labels 16 | 17 | // Standard Kubernetes label: app name. 18 | // +nodoc 19 | labels: "\(#StdLabelName)": #Name 20 | } 21 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/discovery/v1/well_known_labels_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/discovery/v1 4 | 5 | package v1 6 | 7 | // LabelServiceName is used to indicate the name of a Kubernetes service. 8 | #LabelServiceName: "kubernetes.io/service-name" 9 | 10 | // LabelManagedBy is used to indicate the controller or entity that manages 11 | // an EndpointSlice. This label aims to enable different EndpointSlice 12 | // objects to be managed by different controllers or entities within the 13 | // same cluster. It is highly recommended to configure this label for all 14 | // EndpointSlices. 15 | #LabelManagedBy: "endpointslice.kubernetes.io/managed-by" 16 | 17 | // LabelSkipMirror can be set to true on an Endpoints resource to indicate 18 | // that the EndpointSliceMirroring controller should not mirror this 19 | // resource with EndpointSlices. 20 | #LabelSkipMirror: "endpointslice.kubernetes.io/skip-mirror" 21 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/codec_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | package runtime 6 | 7 | // codec binds an encoder and decoder. 8 | _#codec: { 9 | Encoder: #Encoder 10 | Decoder: #Decoder 11 | } 12 | 13 | // NoopEncoder converts an Decoder to a Serializer or Codec for code that expects them but only uses decoding. 14 | #NoopEncoder: { 15 | Decoder: #Decoder 16 | } 17 | 18 | _#noopEncoderIdentifier: #Identifier & "noop" 19 | 20 | // NoopDecoder converts an Encoder to a Serializer or Codec for code that expects them but only uses encoding. 21 | #NoopDecoder: { 22 | Encoder: #Encoder 23 | } 24 | 25 | _#base64Serializer: { 26 | Encoder: #Encoder 27 | Decoder: #Decoder 28 | } 29 | 30 | _#internalGroupVersionerIdentifier: "internal" 31 | _#disabledGroupVersionerIdentifier: "disabled" 32 | 33 | _#internalGroupVersioner: { 34 | } 35 | 36 | _#disabledGroupVersioner: { 37 | } 38 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/apis/meta/v1/time_proto_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/apis/meta/v1 4 | 5 | package v1 6 | 7 | // Timestamp is a struct that is equivalent to Time, but intended for 8 | // protobuf marshalling/unmarshalling. It is generated into a serialization 9 | // that matches Time. Do not use in Go structs. 10 | #Timestamp: { 11 | // Represents seconds of UTC time since Unix epoch 12 | // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to 13 | // 9999-12-31T23:59:59Z inclusive. 14 | seconds: int64 @go(Seconds) @protobuf(1,varint,opt) 15 | 16 | // Non-negative fractions of a second at nanosecond resolution. Negative 17 | // second values with fractions must still have non-negative nanos values 18 | // that count forward in time. Must be from 0 to 999,999,999 19 | // inclusive. This field may be limited in precision depending on context. 20 | nanos: int32 @go(Nanos) @protobuf(2,varint,opt) 21 | } 22 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" # See documentation for possible values 9 | directory: "/.github" # Location of package manifests 10 | labels: ["area/ci", "dependencies"] 11 | groups: 12 | # Group all updates together, so that they are all applied in a single PR. 13 | # Grouped updates are currently in beta and is subject to change. 14 | # xref: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#groups 15 | ci: 16 | patterns: 17 | - "*" 18 | schedule: 19 | interval: "weekly" 20 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/apis/meta/v1/watch_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/apis/meta/v1 4 | 5 | package v1 6 | 7 | import ( 8 | "k8s.io/apimachinery/pkg/runtime" 9 | "k8s.io/apimachinery/pkg/watch" 10 | ) 11 | 12 | // Event represents a single event to a watched resource. 13 | // 14 | // +protobuf=true 15 | // +k8s:deepcopy-gen=true 16 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 17 | #WatchEvent: { 18 | type: string @go(Type) @protobuf(1,bytes,opt) 19 | 20 | // Object is: 21 | // * If Type is Added or Modified: the new state of the object. 22 | // * If Type is Deleted: the state of the object immediately before deletion. 23 | // * If Type is Error: *Status is recommended; other types may make sense 24 | // depending on context. 25 | object: runtime.#RawExtension @go(Object) @protobuf(2,bytes,opt) 26 | } 27 | 28 | // InternalEvent makes watch.Event versioned 29 | // +protobuf=false 30 | #InternalEvent: watch.#Event 31 | -------------------------------------------------------------------------------- /debug_tool.cue: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "tool/cli" 5 | "encoding/yaml" 6 | "text/tabwriter" 7 | ) 8 | 9 | _resources: timoni.apply.app + timoni.apply.test 10 | 11 | // 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'. 13 | command: build: { 14 | task: print: cli.Print & { 15 | text: yaml.MarshalStream(_resources) 16 | } 17 | } 18 | 19 | // 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'. 21 | command: ls: { 22 | task: print: cli.Print & { 23 | text: tabwriter.Write([ 24 | "RESOURCE \tAPI VERSION", 25 | for r in _resources { 26 | if r.metadata.namespace == _|_ { 27 | "\(r.kind)/\(r.metadata.name) \t\(r.apiVersion)" 28 | } 29 | if r.metadata.namespace != _|_ { 30 | "\(r.kind)/\(r.metadata.namespace)/\(r.metadata.name) \t\(r.apiVersion)" 31 | } 32 | }, 33 | ]) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/api/resource/amount_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/api/resource 4 | 5 | package resource 6 | 7 | // Scale is used for getting and setting the base-10 scaled value. 8 | // Base-2 scales are omitted for mathematical simplicity. 9 | // See Quantity.ScaledValue for more details. 10 | #Scale: int32 // #enumScale 11 | 12 | #enumScale: 13 | #Nano | 14 | #Micro | 15 | #Milli | 16 | #Kilo | 17 | #Mega | 18 | #Giga | 19 | #Tera | 20 | #Peta | 21 | #Exa 22 | 23 | #values_Scale: { 24 | Nano: #Nano 25 | Micro: #Micro 26 | Milli: #Milli 27 | Kilo: #Kilo 28 | Mega: #Mega 29 | Giga: #Giga 30 | Tera: #Tera 31 | Peta: #Peta 32 | Exa: #Exa 33 | } 34 | 35 | #Nano: #Scale & -9 36 | #Micro: #Scale & -6 37 | #Milli: #Scale & -3 38 | #Kilo: #Scale & 3 39 | #Mega: #Scale & 6 40 | #Giga: #Scale & 9 41 | #Tera: #Scale & 12 42 | #Peta: #Scale & 15 43 | #Exa: #Scale & 18 44 | 45 | // infDecAmount implements common operations over an inf.Dec that are specific to the quantity 46 | // representation. 47 | _#infDecAmount: string 48 | -------------------------------------------------------------------------------- /cue.mod/pkg/timoni.sh/core/v1alpha1/semver.cue: -------------------------------------------------------------------------------- 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 | // +nodoc 25 | major: int & >=minMajor 26 | major: strconv.Atoi(strings.Split(#Version, ".")[0]) 27 | 28 | // +nodoc 29 | minor: int & >=minMinor 30 | minor: strconv.Atoi(strings.Split(#Version, ".")[1]) 31 | } 32 | -------------------------------------------------------------------------------- /cue.mod/pkg/timoni.sh/core/v1alpha1/instance.cue: -------------------------------------------------------------------------------- 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 | } 28 | -------------------------------------------------------------------------------- /templates/clusterRoleBinding.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | "strings" 5 | rbacv1 "k8s.io/api/rbac/v1" 6 | timoniv1 "timoni.sh/core/v1alpha1" 7 | 8 | cfg "timoni.sh/cert-manager/templates/config" 9 | ) 10 | 11 | #ClusterRoleBinding: rbacv1.#ClusterRoleBinding & { 12 | #config: cfg.#Config 13 | #component: string 14 | #role?: string 15 | 16 | #meta: timoniv1.#MetaComponent & { 17 | #Meta: #config.metadata 18 | #Component: strings.ToLower(#component) 19 | } 20 | 21 | apiVersion: "rbac.authorization.k8s.io/v1" 22 | kind: "ClusterRoleBinding" 23 | 24 | if #role != _|_ { 25 | metadata: name: "\(#meta.name)-\(#role)" 26 | } 27 | 28 | if #role == _|_ { 29 | metadata: name: "\(#meta.name)" 30 | } 31 | 32 | metadata: labels: #meta.labels 33 | 34 | if #meta.annotations != _|_ { 35 | metadata: annotations: #meta.annotations 36 | } 37 | 38 | roleRef: { 39 | apiGroup: "rbac.authorization.k8s.io" 40 | kind: "ClusterRole" 41 | 42 | if #role != _|_ { 43 | name: "\(#meta.name)-\(#role)" 44 | } 45 | 46 | if #role == _|_ { 47 | name: "\(#meta.name)" 48 | } 49 | } 50 | subjects: [{ 51 | kind: "ServiceAccount" 52 | name: #meta.name 53 | namespace: #meta.namespace 54 | }] 55 | } 56 | -------------------------------------------------------------------------------- /templates/config/images.cue: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | #AppVersion: *"v1.14.5" | string 4 | 5 | #Controller: image: { 6 | repository: *"quay.io/jetstack/cert-manager-controller" | string 7 | tag: #AppVersion 8 | digest: *"sha256:9c0527cab629b61bd60c20f0c25615a8593314d3504add968b42bc5b891b253a" | string 9 | } 10 | 11 | #Webhook: image: { 12 | repository: *"quay.io/jetstack/cert-manager-webhook" | string 13 | tag: #AppVersion 14 | digest: *"sha256:ef419261a209c5409fb1539dbd45c805d05936e955b4530b8ec4ac780577f151" | string 15 | } 16 | 17 | #CAInjector: image: { 18 | repository: *"quay.io/jetstack/cert-manager-cainjector" | string 19 | tag: #AppVersion 20 | digest: *"sha256:4ffda7facb4da16dab20a88e7607b75ebdab4e6c9069a840216a89f47261ee0b" | string 21 | } 22 | 23 | #StartupAPICheck: image: { 24 | repository: *"quay.io/jetstack/cert-manager-ctl" | string 25 | tag: #AppVersion 26 | digest: *"sha256:2ddf50d0961658812b8bc89789ec955a1ffd38b601891fb6b09276d5741299c5" | string 27 | } 28 | 29 | #ACMESolver: image: { 30 | repository: *"quay.io/jetstack/cert-manager-acmesolver" | string 31 | tag: #AppVersion 32 | digest: *"sha256:5e807851354e51b6d978dde72523952464ecc3e79678a88892d2598c7bba9fd5" | string 33 | } 34 | -------------------------------------------------------------------------------- /templates/podDisruptionBudget.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | "strings" 5 | policyv1 "k8s.io/api/policy/v1" 6 | timoniv1 "timoni.sh/core/v1alpha1" 7 | cfg "timoni.sh/cert-manager/templates/config" 8 | ) 9 | 10 | #PodDisruptionBudget: policyv1.#PodDisruptionBudget & { 11 | #config: cfg.#Config 12 | #component: string 13 | 14 | #meta: timoniv1.#MetaComponent & { 15 | #Meta: #config.metadata 16 | #Component: strings.ToLower(#component) 17 | } 18 | 19 | apiVersion: "policy/v1" 20 | kind: "PodDisruptionBudget" 21 | metadata: #meta 22 | 23 | spec: { 24 | selector: matchLabels: #meta.#LabelSelector 25 | if #config.highAvailability.enabled && 26 | #config[#component].podDisruptionBudget.minAvailable == _|_ && 27 | #config[#component].podDisruptionBudget.maxUnavailable == _|_ { 28 | minAvailable: #config[#component].replicas - 1 29 | } 30 | if #config[#component].podDisruptionBudget.minAvailable != _|_ { 31 | minAvailable: #config[#component].podDisruptionBudget.minAvailable & {uint16 & <=#config[#component].replicas | cfg.#Percent} 32 | } 33 | if #config[#component].podDisruptionBudget.maxUnavailable != _|_ { 34 | maxUnavailable: #config[#component].podDisruptionBudget.maxUnavailable 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /cue.mod/pkg/timoni.sh/core/v1alpha1/immutable.cue: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Stefan Prodan 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package v1alpha1 5 | 6 | import ( 7 | "encoding/json" 8 | "strings" 9 | "uuid" 10 | ) 11 | 12 | #ConfigMapKind: "ConfigMap" 13 | #SecretKind: "Secret" 14 | 15 | // ImmutableConfig is a generator for immutable Kubernetes ConfigMaps and Secrets. 16 | // The metadata.name of the generated object is suffixed with the hash of the input data. 17 | #ImmutableConfig: { 18 | // Kind of the generated object. 19 | #Kind: *#ConfigMapKind | #SecretKind 20 | 21 | // Metadata of the generated object. 22 | #Meta: #Metadata 23 | 24 | // Optional suffix appended to the generate name. 25 | #Suffix: *"" | string 26 | 27 | // Data of the generated object. 28 | #Data: {[string]: string} 29 | 30 | let hash = strings.Split(uuid.SHA1(uuid.ns.DNS, json.Marshal(#Data)), "-")[0] 31 | 32 | apiVersion: "v1" 33 | kind: #Kind 34 | metadata: { 35 | name: #Meta.name + #Suffix + "-" + hash 36 | namespace: #Meta.namespace 37 | labels: #Meta.labels 38 | if #Meta.annotations != _|_ { 39 | annotations: #Meta.annotations 40 | } 41 | } 42 | immutable: true 43 | if kind == #ConfigMapKind { 44 | data: #Data 45 | } 46 | if kind == #SecretKind { 47 | stringData: #Data 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /cue.mod/pkg/timoni.sh/core/v1alpha1/requirements.cue: -------------------------------------------------------------------------------- 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 | } 41 | -------------------------------------------------------------------------------- /templates/podMonitor.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | podmonitorv1 "monitoring.coreos.com/podmonitor/v1" 5 | timoniv1 "timoni.sh/core/v1alpha1" 6 | 7 | cfg "timoni.sh/cert-manager/templates/config" 8 | ) 9 | 10 | #PodMonitor: podmonitorv1.#PodMonitor & { 11 | #config: cfg.#Config 12 | #component: string 13 | 14 | #meta: timoniv1.#MetaComponent & { 15 | #Meta: #config.metadata 16 | #Component: #component 17 | } 18 | 19 | metadata: #meta 20 | metadata: labels: prometheus: #config.controller.monitoring.prometheusInstance 21 | 22 | if #config.controller.monitoring.annotations != _|_ { 23 | metadata: annotations: #config.controller.monitoring.annotations 24 | } 25 | 26 | spec: { 27 | jobLabel: #config.metadata.name 28 | selector: matchLabels: #meta.#LabelSelector 29 | namespaceSelector: matchNames: [#config.controller.monitoring.namespace] 30 | 31 | podMetricsEndpoints: [{ 32 | port: #config.controller.monitoring.targetPort 33 | path: #config.controller.monitoring.path 34 | interval: #config.controller.monitoring.interval 35 | scrapeTimeout: #config.controller.monitoring.scrapeTimeout 36 | honorLabels: #config.controller.monitoring.honorLabels 37 | 38 | if #config.controller.monitoring.endpointAdditionalProperties != _|_ { 39 | for k, v in #config.controller.monitoring.endpointAdditionalProperties { 40 | "\(k)": v 41 | } 42 | } 43 | }] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /templates/serviceMonitor.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | servicemonitorv1 "monitoring.coreos.com/servicemonitor/v1" 5 | timoniv1 "timoni.sh/core/v1alpha1" 6 | 7 | cfg "timoni.sh/cert-manager/templates/config" 8 | ) 9 | 10 | #ServiceMonitor: servicemonitorv1.#ServiceMonitor & { 11 | #config: cfg.#Config 12 | #component: string 13 | 14 | #meta: timoniv1.#MetaComponent & { 15 | #Meta: #config.metadata 16 | #Component: #component 17 | } 18 | 19 | metadata: #meta 20 | metadata: labels: prometheus: #config.controller.monitoring.prometheusInstance 21 | 22 | if #config.controller.monitoring.annotations != _|_ { 23 | metadata: annotations: #config.controller.monitoring.annotations 24 | } 25 | 26 | spec: { 27 | jobLabel: #config.metadata.name 28 | selector: matchLabels: #meta.#LabelSelector 29 | namespaceSelector: matchNames: [#config.controller.monitoring.namespace] 30 | 31 | endpoints: [{ 32 | targetPort: #config.controller.monitoring.targetPort 33 | path: #config.controller.monitoring.path 34 | interval: #config.controller.monitoring.interval 35 | scrapeTimeout: #config.controller.monitoring.scrapeTimeout 36 | honorLabels: #config.controller.monitoring.honorLabels 37 | 38 | if #config.controller.monitoring.endpointAdditionalProperties != _|_ { 39 | for k, v in #config.controller.monitoring.endpointAdditionalProperties { 40 | "\(k)": v 41 | } 42 | } 43 | }] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | tags: [ 'v*' ] 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | publish-artifacts: 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: read 15 | id-token: write 16 | packages: write 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 20 | - name: Setup Cosign 21 | uses: sigstore/cosign-installer@9614fae9e5c5eddabb09f90a270fcb487c9f7149 # v3.3.0 22 | - name: Setup Timoni 23 | uses: stefanprodan/timoni/actions/setup@main 24 | - name: Login to GHCR 25 | uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 26 | with: 27 | registry: ghcr.io 28 | username: ${{ github.actor }} 29 | password: ${{ secrets.GITHUB_TOKEN }} 30 | - name: Push cert-manager module 31 | run: | 32 | timoni mod push ./ oci://ghcr.io/nalum/timoni/modules/cert-manager \ 33 | -v ${GITHUB_REF_NAME#v} --latest \ 34 | -a 'org.opencontainers.image.licenses=Apache-2.0' \ 35 | -a 'org.opencontainers.image.source=https://github.com/nalum/cert-manager-module' \ 36 | -a 'org.opencontainers.image.description=A timoni.sh module for cert-manager.' \ 37 | -a "org.opencontainers.image.documentation=https://github.com/Nalum/cert-manager-module/blob/${GITHUB_REF_NAME}/README.md" \ 38 | --sign cosign 39 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/apis/meta/v1/meta_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/apis/meta/v1 4 | 5 | package v1 6 | 7 | // TODO: move this, Object, List, and Type to a different package 8 | #ObjectMetaAccessor: _ 9 | 10 | // Object lets you work with object metadata from any of the versioned or 11 | // internal API objects. Attempting to set or retrieve a field on an object that does 12 | // not support that field (Name, UID, Namespace on lists) will be a no-op and return 13 | // a default value. 14 | #Object: _ 15 | 16 | // ListMetaAccessor retrieves the list interface from an object 17 | #ListMetaAccessor: _ 18 | 19 | // Common lets you work with core metadata from any of the versioned or 20 | // internal API objects. Attempting to set or retrieve a field on an object that does 21 | // not support that field will be a no-op and return a default value. 22 | // TODO: move this, and TypeMeta and ListMeta, to a different package 23 | #Common: _ 24 | 25 | // ListInterface lets you work with list metadata from any of the versioned or 26 | // internal API objects. Attempting to set or retrieve a field on an object that does 27 | // not support that field will be a no-op and return a default value. 28 | // TODO: move this, and TypeMeta and ListMeta, to a different package 29 | #ListInterface: _ 30 | 31 | // Type exposes the type and APIVersion of versioned or internal API objects. 32 | // TODO: move this, and TypeMeta and ListMeta, to a different package 33 | #Type: _ 34 | -------------------------------------------------------------------------------- /DCO: -------------------------------------------------------------------------------- 1 | Developer Certificate of Origin 2 | Version 1.1 3 | 4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 5 | 660 York Street, Suite 102, 6 | San Francisco, CA 94110 USA 7 | 8 | Everyone is permitted to copy and distribute verbatim copies of this 9 | license document, but changing it is not allowed. 10 | 11 | 12 | Developer's Certificate of Origin 1.1 13 | 14 | By making a contribution to this project, I certify that: 15 | 16 | (a) The contribution was created in whole or in part by me and I 17 | have the right to submit it under the open source license 18 | indicated in the file; or 19 | 20 | (b) The contribution is based upon previous work that, to the best 21 | of my knowledge, is covered under an appropriate open source 22 | license and I have the right under that license to submit that 23 | work with modifications, whether created in whole or in part 24 | by me, under the same open source license (unless I am 25 | permitted to submit under a different license), as indicated 26 | in the file; or 27 | 28 | (c) The contribution was provided directly to me by some other 29 | person who certified (a), (b) or (c) and I have not modified 30 | it. 31 | 32 | (d) I understand and agree that this project and the contribution 33 | are public and that a record of the contribution (including all 34 | personal information I submit with it, including my sign-off) is 35 | maintained indefinitely and may be redistributed consistent with 36 | this project or the open source license(s) involved. -------------------------------------------------------------------------------- /cue.mod/gen/monitoring.coreos.com/prometheusrule/v1/types_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by timoni. DO NOT EDIT. 2 | 3 | //timoni:generate timoni vendor crd -f https://github.com/prometheus-operator/prometheus-operator/releases/download/v0.68.0/stripped-down-crds.yaml 4 | 5 | package v1 6 | 7 | import "strings" 8 | 9 | #PrometheusRule: { 10 | apiVersion: "monitoring.coreos.com/v1" 11 | kind: "PrometheusRule" 12 | metadata!: { 13 | name!: strings.MaxRunes(253) & strings.MinRunes(1) & { 14 | string 15 | } 16 | namespace!: strings.MaxRunes(63) & strings.MinRunes(1) & { 17 | string 18 | } 19 | labels?: { 20 | [string]: string 21 | } 22 | annotations?: { 23 | [string]: string 24 | } 25 | } 26 | spec!: #PrometheusRuleSpec 27 | } 28 | #PrometheusRuleSpec: { 29 | groups?: [...{ 30 | interval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 31 | limit?: int 32 | name: strings.MinRunes(1) 33 | partial_response_strategy?: =~"^(?i)(abort|warn)?$" 34 | rules?: [...{ 35 | alert?: string 36 | annotations?: { 37 | [string]: string 38 | } 39 | expr: (int | string) & { 40 | string 41 | } 42 | for?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 43 | keep_firing_for?: strings.MinRunes(1) & { 44 | =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 45 | } 46 | labels?: { 47 | [string]: string 48 | } 49 | record?: string 50 | }] 51 | }] 52 | } 53 | -------------------------------------------------------------------------------- /templates/service.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | "strings" 5 | corev1 "k8s.io/api/core/v1" 6 | timoniv1 "timoni.sh/core/v1alpha1" 7 | 8 | cfg "timoni.sh/cert-manager/templates/config" 9 | ) 10 | 11 | #Service: corev1.#Service & { 12 | #config: cfg.#Config 13 | #component: string 14 | 15 | #meta: timoniv1.#MetaComponent & { 16 | #Meta: #config.metadata 17 | #Component: strings.ToLower(#component) 18 | } 19 | 20 | apiVersion: "v1" 21 | kind: "Service" 22 | metadata: #meta 23 | 24 | if #config[#component].serviceLabels != _|_ { 25 | metadata: labels: #config[#component].service.labels 26 | } 27 | if #config[#component].serviceAnnotations != _|_ { 28 | metadata: annotations: #config[#component].service.annotations 29 | } 30 | 31 | spec: { 32 | selector: #meta.#LabelSelector 33 | } 34 | } 35 | 36 | #ServiceController: #Service & { 37 | #config: cfg.#Config 38 | #component: "controller" 39 | 40 | spec: { 41 | type: "ClusterIP" 42 | ports: [{ 43 | protocol: "TCP" 44 | port: 9402 45 | name: "tcp-prometheus-servicemonitor" 46 | targetPort: #config[#component].monitoring.targetPort 47 | }] 48 | } 49 | } 50 | 51 | #ServiceWebhook: #Service & { 52 | #config: cfg.#Config 53 | #component: "webhook" 54 | 55 | spec: { 56 | 57 | type: #config.webhook.service.type 58 | 59 | if #config.webhook.loadBalancerIP != _|_ { 60 | loadBalancerIP: #config.webhook.loadBalancerIP 61 | } 62 | ports: [{ 63 | protocol: "TCP" 64 | port: 443 65 | name: "https" 66 | targetPort: "https" 67 | }] 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/watch/watch_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/watch 4 | 5 | package watch 6 | 7 | import "k8s.io/apimachinery/pkg/runtime" 8 | 9 | // Interface can be implemented by anything that knows how to watch and report changes. 10 | #Interface: _ 11 | 12 | // EventType defines the possible types of events. 13 | #EventType: string // #enumEventType 14 | 15 | #enumEventType: 16 | #Added | 17 | #Modified | 18 | #Deleted | 19 | #Bookmark | 20 | #Error 21 | 22 | #Added: #EventType & "ADDED" 23 | #Modified: #EventType & "MODIFIED" 24 | #Deleted: #EventType & "DELETED" 25 | #Bookmark: #EventType & "BOOKMARK" 26 | #Error: #EventType & "ERROR" 27 | 28 | // Event represents a single event to a watched resource. 29 | // +k8s:deepcopy-gen=true 30 | #Event: { 31 | Type: #EventType 32 | 33 | // Object is: 34 | // * If Type is Added or Modified: the new state of the object. 35 | // * If Type is Deleted: the state of the object immediately before deletion. 36 | // * If Type is Bookmark: the object (instance of a type being watched) where 37 | // only ResourceVersion field is set. On successful restart of watch from a 38 | // bookmark resourceVersion, client is guaranteed to not get repeat event 39 | // nor miss any events. 40 | // * If Type is Error: *api.Status is recommended; other types may make sense 41 | // depending on context. 42 | Object: runtime.#Object 43 | } 44 | 45 | // RaceFreeFakeWatcher lets you test anything that consumes a watch.Interface; threadsafe. 46 | #RaceFreeFakeWatcher: { 47 | Stopped: bool 48 | } 49 | -------------------------------------------------------------------------------- /templates/deploymentSpecCAInjector.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | appsv1 "k8s.io/api/apps/v1" 5 | corev1 "k8s.io/api/core/v1" 6 | timoniv1 "timoni.sh/core/v1alpha1" 7 | 8 | cfg "timoni.sh/cert-manager/templates/config" 9 | ) 10 | 11 | #CAInjectorDeploymentSpec: appsv1.#DeploymentSpec & { 12 | #main_config: cfg.#Config 13 | #deployment_meta: timoniv1.#MetaComponent 14 | 15 | selector: matchLabels: #deployment_meta.#LabelSelector 16 | 17 | template: corev1.#PodTemplateSpec & { 18 | spec: corev1.#PodSpec & { 19 | containers: [...corev1.#Container] & [ 20 | { 21 | args: [ 22 | "--v=\(#main_config.logLevel)", 23 | "--leader-election-namespace=\(#main_config.leaderElection.namespace)", 24 | 25 | if #main_config.leaderElection.leaseDuration != _|_ { 26 | "--leader-election-lease-duration=\(#main_config.leaderElection.leaseDuration)" 27 | }, 28 | 29 | if #main_config.leaderElection.renewDeadline != _|_ { 30 | "--leader-election-renew-deadline=\(#main_config.leaderElection.renewDeadline)" 31 | }, 32 | 33 | if #main_config.leaderElection.retryPeriod != _|_ { 34 | "--leader-election-retry-period=\(#main_config.leaderElection.retryPeriod)" 35 | }, 36 | 37 | if #main_config.caInjector.extraArgs != _|_ { 38 | for a in #main_config.caInjector.extraArgs {a} 39 | }, 40 | ] 41 | 42 | if #main_config.caInjector.volumeMounts != _|_ { 43 | volumeMounts: #main_config.caInjector.volumeMounts 44 | } 45 | }, 46 | ] 47 | 48 | if #main_config.caInjector.volumes != _|_ { 49 | volumes: #main_config.caInjector.volumes 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /debug_values.cue: -------------------------------------------------------------------------------- 1 | @if(debug) 2 | 3 | package main 4 | 5 | // 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'. 7 | values: { 8 | metadata: labels: team: "dev" 9 | metadata: annotations: "cert-manager.timoni.sh/testing": "true" 10 | 11 | highAvailability: enabled: true 12 | 13 | rbac: { 14 | enabled: true 15 | aggregateClusterRoles: false 16 | } 17 | 18 | controller: { 19 | replicas: 5 20 | podDisruptionBudget: minAvailable: 3 21 | 22 | config: logging: format: "json" 23 | resources: requests: cpu: "100m" 24 | ingressShim: defaultIssuerName: "dev" 25 | monitoring: enabled: true 26 | 27 | livenessProbe: { 28 | initialDelaySeconds: 30 29 | periodSeconds: 15 30 | failureThreshold: 4 31 | timeoutSeconds: 2 32 | } 33 | 34 | strategy: { 35 | type: "RollingUpdate" 36 | rollingUpdate: { 37 | maxSurge: 1 38 | } 39 | } 40 | } 41 | 42 | webhook: { 43 | 44 | livenessProbe: { 45 | initialDelaySeconds: 30 46 | periodSeconds: 15 47 | failureThreshold: 4 48 | timeoutSeconds: 2 49 | } 50 | 51 | readinessProbe: { 52 | initialDelaySeconds: 20 53 | periodSeconds: 10 54 | failureThreshold: 6 55 | timeoutSeconds: 2 56 | } 57 | 58 | strategy: { 59 | type: "RollingUpdate" 60 | rollingUpdate: { 61 | maxSurge: 1 62 | } 63 | } 64 | } 65 | 66 | caInjector: { 67 | podDisruptionBudget: maxUnavailable: "20%" 68 | 69 | strategy: { 70 | type: "RollingUpdate" 71 | rollingUpdate: { 72 | maxSurge: 1 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/types/nodename_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/types 4 | 5 | package types 6 | 7 | // NodeName is a type that holds a api.Node's Name identifier. 8 | // Being a type captures intent and helps make sure that the node name 9 | // is not confused with similar concepts (the hostname, the cloud provider id, 10 | // the cloud provider name etc) 11 | // 12 | // To clarify the various types: 13 | // 14 | // - Node.Name is the Name field of the Node in the API. This should be stored in a NodeName. 15 | // Unfortunately, because Name is part of ObjectMeta, we can't store it as a NodeName at the API level. 16 | // 17 | // - Hostname is the hostname of the local machine (from uname -n). 18 | // However, some components allow the user to pass in a --hostname-override flag, 19 | // which will override this in most places. In the absence of anything more meaningful, 20 | // kubelet will use Hostname as the Node.Name when it creates the Node. 21 | // 22 | // * The cloudproviders have the own names: GCE has InstanceName, AWS has InstanceId. 23 | // 24 | // For GCE, InstanceName is the Name of an Instance object in the GCE API. On GCE, Instance.Name becomes the 25 | // Hostname, and thus it makes sense also to use it as the Node.Name. But that is GCE specific, and it is up 26 | // to the cloudprovider how to do this mapping. 27 | // 28 | // For AWS, the InstanceID is not yet suitable for use as a Node.Name, so we actually use the 29 | // PrivateDnsName for the Node.Name. And this is _not_ always the same as the hostname: if 30 | // we are using a custom DHCP domain it won't be. 31 | #NodeName: string 32 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/doc_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | // Package runtime includes helper functions for working with API objects 6 | // that follow the kubernetes API object conventions, which are: 7 | // 8 | // 0. Your API objects have a common metadata struct member, TypeMeta. 9 | // 10 | // 1. Your code refers to an internal set of API objects. 11 | // 12 | // 2. In a separate package, you have an external set of API objects. 13 | // 14 | // 3. The external set is considered to be versioned, and no breaking 15 | // changes are ever made to it (fields may be added but not changed 16 | // or removed). 17 | // 18 | // 4. As your api evolves, you'll make an additional versioned package 19 | // with every major change. 20 | // 21 | // 5. Versioned packages have conversion functions which convert to 22 | // and from the internal version. 23 | // 24 | // 6. You'll continue to support older versions according to your 25 | // deprecation policy, and you can easily provide a program/library 26 | // to update old versions into new versions because of 5. 27 | // 28 | // 7. All of your serializations and deserializations are handled in a 29 | // centralized place. 30 | // 31 | // Package runtime provides a conversion helper to make 5 easy, and the 32 | // Encode/Decode/DecodeInto trio to accomplish 7. You can also register 33 | // additional "codecs" which use a version of your choice. It's 34 | // recommended that you register your types with runtime in your 35 | // package's init function. 36 | // 37 | // As a bonus, a few common types useful from all api objects and versions 38 | // are provided in types.go. 39 | package runtime 40 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/core/v1/well_known_taints_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/core/v1 4 | 5 | package v1 6 | 7 | // TaintNodeNotReady will be added when node is not ready 8 | // and removed when node becomes ready. 9 | #TaintNodeNotReady: "node.kubernetes.io/not-ready" 10 | 11 | // TaintNodeUnreachable will be added when node becomes unreachable 12 | // (corresponding to NodeReady status ConditionUnknown) 13 | // and removed when node becomes reachable (NodeReady status ConditionTrue). 14 | #TaintNodeUnreachable: "node.kubernetes.io/unreachable" 15 | 16 | // TaintNodeUnschedulable will be added when node becomes unschedulable 17 | // and removed when node becomes schedulable. 18 | #TaintNodeUnschedulable: "node.kubernetes.io/unschedulable" 19 | 20 | // TaintNodeMemoryPressure will be added when node has memory pressure 21 | // and removed when node has enough memory. 22 | #TaintNodeMemoryPressure: "node.kubernetes.io/memory-pressure" 23 | 24 | // TaintNodeDiskPressure will be added when node has disk pressure 25 | // and removed when node has enough disk. 26 | #TaintNodeDiskPressure: "node.kubernetes.io/disk-pressure" 27 | 28 | // TaintNodeNetworkUnavailable will be added when node's network is unavailable 29 | // and removed when network becomes ready. 30 | #TaintNodeNetworkUnavailable: "node.kubernetes.io/network-unavailable" 31 | 32 | // TaintNodePIDPressure will be added when node has pid pressure 33 | // and removed when node has enough pid. 34 | #TaintNodePIDPressure: "node.kubernetes.io/pid-pressure" 35 | 36 | // TaintNodeOutOfService can be added when node is out of service in case of 37 | // a non-graceful shutdown 38 | #TaintNodeOutOfService: "node.kubernetes.io/out-of-service" 39 | -------------------------------------------------------------------------------- /templates/mutatingWebhook.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | admissionregistrationv1 "k8s.io/api/admissionregistration/v1" 5 | timoniv1 "timoni.sh/core/v1alpha1" 6 | 7 | cfg "timoni.sh/cert-manager/templates/config" 8 | ) 9 | 10 | #MutatingWebhook: admissionregistrationv1.#MutatingWebhookConfiguration & { 11 | #config: cfg.#Config 12 | 13 | #meta: timoniv1.#MetaClusterComponent & { 14 | #Meta: #config.metadata 15 | #Component: "webhook" 16 | } 17 | 18 | apiVersion: "admissionregistration.k8s.io/v1" 19 | kind: "MutatingWebhookConfiguration" 20 | metadata: #meta 21 | metadata: annotations: "cert-manager.io/inject-ca-from-secret": "\(#config.metadata.namespace)/\(#meta.name)-ca" 22 | 23 | webhooks: [{ 24 | name: "webhook.cert-manager.io" 25 | rules: [{ 26 | apiGroups: [ 27 | "cert-manager.io", 28 | "acme.cert-manager.io", 29 | ] 30 | apiVersions: [ 31 | "v1", 32 | ] 33 | operations: [ 34 | "CREATE", 35 | "UPDATE", 36 | ] 37 | resources: [ 38 | "*/*", 39 | ] 40 | }] 41 | admissionReviewVersions: ["v1"] 42 | // This webhook only accepts v1 cert-manager resources. 43 | // Equivalent matchPolicy ensures that non-v1 resource requests are sent to 44 | // this webhook (after the resources have been converted to v1). 45 | matchPolicy: "Equivalent" 46 | timeoutSeconds: #config.webhook.timeoutSeconds 47 | failurePolicy: "Fail" 48 | // Only include 'sideEffects' field in Kubernetes 1.12+ 49 | sideEffects: "None" 50 | clientConfig: { 51 | if #config.webhook.url.host != _|_ { 52 | url: "https://\(#config.webhook.url.host)/mutate" 53 | } 54 | if #config.webhook.url.host == _|_ { 55 | service: { 56 | name: #meta.name 57 | namespace: #config.metadata.namespace 58 | path: "/mutate" 59 | } 60 | } 61 | } 62 | }] 63 | } 64 | -------------------------------------------------------------------------------- /templates/roleBinding.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | "strings" 5 | rbacv1 "k8s.io/api/rbac/v1" 6 | timoniv1 "timoni.sh/core/v1alpha1" 7 | 8 | cfg "timoni.sh/cert-manager/templates/config" 9 | ) 10 | 11 | #RoleBinding: rbacv1.#RoleBinding & { 12 | #config: cfg.#Config 13 | #component: string 14 | #roleSuffix: string 15 | #namespace?: string 16 | 17 | #meta: timoniv1.#MetaComponent & { 18 | #Meta: #config.metadata 19 | #Component: strings.ToLower(#component) 20 | } 21 | 22 | apiVersion: "rbac.authorization.k8s.io/v1" 23 | kind: "RoleBinding" 24 | 25 | metadata: { 26 | name: "\(#meta.name):\(#roleSuffix)" 27 | namespace: *#namespace | #config.metadata.namespace 28 | labels: #meta.labels 29 | if #config.metadata.annotations != _|_ { 30 | annotations: #config.metadata.annotations 31 | } 32 | } 33 | roleRef: { 34 | apiGroup: "rbac.authorization.k8s.io" 35 | kind: "Role" 36 | name: "\(#meta.name):\(#roleSuffix)" 37 | } 38 | subjects: [{ 39 | apiGroup: "" 40 | kind: "ServiceAccount" 41 | name: #meta.name 42 | namespace: #meta.namespace 43 | }] 44 | } 45 | 46 | #ControllerRoleBinding: #RoleBinding & { 47 | #config: cfg.#Config 48 | #component: "controller" 49 | #roleSuffix: "leaderelection" 50 | #namespace: #config.leaderElection.namespace 51 | } 52 | 53 | #CaInjectorRoleBinding: #RoleBinding & { 54 | #config: cfg.#Config 55 | #component: "caInjector" 56 | #roleSuffix: "leaderelection" 57 | #namespace: #config.leaderElection.namespace 58 | } 59 | 60 | #StartupApiCheckRoleBinding: #RoleBinding & { 61 | #config: cfg.#Config 62 | #component: "startupapicheck" 63 | #roleSuffix: "create-cert" 64 | } 65 | 66 | #WebhookRoleBinding: #RoleBinding & { 67 | #config: cfg.#Config 68 | #component: "webhook" 69 | #roleSuffix: "dynamic-serving" 70 | } 71 | -------------------------------------------------------------------------------- /templates/networkPolicy.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | networkingv1 "k8s.io/api/networking/v1" 5 | timoniv1 "timoni.sh/core/v1alpha1" 6 | 7 | cfg "timoni.sh/cert-manager/templates/config" 8 | ) 9 | 10 | #NetworkPolicyAllowEgress: networkingv1.#NetworkPolicy & { 11 | #config: cfg.#Config 12 | #component: string 13 | 14 | #meta: timoniv1.#MetaComponent & { 15 | #Meta: #config.metadata 16 | #Component: #component 17 | } 18 | 19 | apiVersion: "networking.k8s.io/v1" 20 | kind: "NetworkPolicy" 21 | metadata: name: "\(#meta.name)-allow-egress" 22 | metadata: namespace: #meta.namespace 23 | metadata: labels: #meta.labels 24 | 25 | if #meta.annotations != _|_ { 26 | metadata: annotations: #meta.annotations 27 | } 28 | 29 | spec: { 30 | egress: [ 31 | if #config.webhook.networkPolicy.egress != _|_ { 32 | for k, v in #config.webhook.networkPolicy.egress { 33 | v 34 | } 35 | }, 36 | ] 37 | podSelector: matchLabels: #meta.#LabelSelector 38 | policyTypes: ["Egress"] 39 | } 40 | } 41 | 42 | #NetworkPolicyAllowIngress: networkingv1.#NetworkPolicy & { 43 | #config: cfg.#Config 44 | #component: string 45 | 46 | #meta: timoniv1.#MetaComponent & { 47 | #Meta: #config.metadata 48 | #Component: #component 49 | } 50 | 51 | apiVersion: "networking.k8s.io/v1" 52 | kind: "NetworkPolicy" 53 | metadata: name: "\(#meta.name)-allow-ingress" 54 | metadata: namespace: #meta.namespace 55 | metadata: labels: #meta.labels 56 | 57 | if #meta.annotations != _|_ { 58 | metadata: annotations: #meta.annotations 59 | } 60 | 61 | spec: { 62 | ingress: [ 63 | if #config.webhook.networkPolicy.ingress != _|_ { 64 | for k, v in #config.webhook.networkPolicy.ingress { 65 | v 66 | } 67 | }, 68 | ] 69 | podSelector: matchLabels: #meta.#LabelSelector 70 | policyTypes: ["Ingress"] 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /timoni.cue: -------------------------------------------------------------------------------- 1 | // Code generated by timoni. 2 | // Note that this file is required and should contain 3 | // the values schema and the timoni workflow. 4 | 5 | package main 6 | 7 | import ( 8 | "strconv" 9 | "strings" 10 | 11 | cfg "timoni.sh/cert-manager/templates/config" 12 | templates "timoni.sh/cert-manager/templates" 13 | ) 14 | 15 | // Define the schema for the user-supplied values. 16 | // At runtime, Timoni injects the supplied values 17 | // and validates them according to the Config schema. 18 | values: cfg.#Config 19 | 20 | // Define how Timoni should build, validate and 21 | // apply the Kubernetes resources. 22 | timoni: { 23 | apiVersion: "v1alpha1" 24 | 25 | // Define the instance that outputs the Kubernetes resources. 26 | // At runtime, Timoni builds the instance and validates 27 | // the resulting resources according to their Kubernetes schema. 28 | instance: templates.#Instance & { 29 | // The user-supplied values are merged with the 30 | // default values at runtime by Timoni. 31 | config: values 32 | // These values are injected at runtime by Timoni. 33 | config: { 34 | // +nodoc 35 | metadata: { 36 | // +nodoc 37 | name: string @tag(name) 38 | // +nodoc 39 | namespace: string @tag(namespace) 40 | } 41 | // +nodoc 42 | moduleVersion: string @tag(mv, var=moduleVersion) 43 | // +nodoc 44 | kubeVersion: string @tag(kv, var=kubeVersion) 45 | } 46 | } 47 | 48 | // Enforce minimum Kubernetes version. 49 | kubeMinorVersion: int & >=20 50 | kubeMinorVersion: strconv.Atoi(strings.Split(instance.config.kubeVersion, ".")[1]) 51 | 52 | // Pass Kubernetes resources outputted by the instance 53 | // to Timoni's multi-step apply. 54 | apply: app: [for obj in instance.objects {obj}] 55 | 56 | // Conditionally run tests after an install or upgrade. 57 | if instance.config.test.enabled { 58 | apply: test: [for obj in instance.tests {obj}] 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /templates/serviceAccount.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | "strings" 5 | corev1 "k8s.io/api/core/v1" 6 | timoniv1 "timoni.sh/core/v1alpha1" 7 | cfg "timoni.sh/cert-manager/templates/config" 8 | ) 9 | 10 | #ServiceAccount: corev1.#ServiceAccount & { 11 | #config: cfg.#Config 12 | #component: string 13 | 14 | #meta: timoniv1.#MetaComponent & { 15 | #Meta: #config.metadata 16 | #Component: strings.ToLower(#component) 17 | } 18 | 19 | apiVersion: "v1" 20 | kind: "ServiceAccount" 21 | metadata: #meta 22 | automountServiceAccountToken: #config[#component].serviceAccount.automountServiceAccountToken 23 | 24 | if #config.imagePullSecrets != _|_ { 25 | imagePullSecrets: #config.imagePullSecrets 26 | } 27 | 28 | if #config[#component].serviceAccount.labels != _|_ { 29 | metadata: labels: #config[#component].serviceAccount.labels 30 | } 31 | if #config[#component].serviceAccount.annotations != _|_ { 32 | metadata: annotations: #config[#component].serviceAccount.annotations 33 | } 34 | } 35 | 36 | #TestServiceAccount: corev1.#ServiceAccount & { 37 | #config: cfg.#Config 38 | #component: string 39 | 40 | #meta: timoniv1.#MetaComponent & { 41 | #Meta: #config.metadata 42 | #Component: strings.ToLower(#component) 43 | } 44 | 45 | apiVersion: "v1" 46 | kind: "ServiceAccount" 47 | metadata: #meta 48 | automountServiceAccountToken: #config.test[#component].serviceAccount.automountServiceAccountToken 49 | 50 | if #config.imagePullSecrets != _|_ { 51 | imagePullSecrets: #config.imagePullSecrets 52 | } 53 | 54 | if #config.test[#component].serviceAccount.labels != _|_ { 55 | metadata: labels: #config.test[#component].serviceAccount.labels 56 | } 57 | if #config.test[#component].serviceAccount.annotations != _|_ { 58 | metadata: annotations: #config.test[#component].serviceAccount.annotations 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /templates/validatingWebhook.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | admissionregistrationv1 "k8s.io/api/admissionregistration/v1" 5 | timoniv1 "timoni.sh/core/v1alpha1" 6 | 7 | cfg "timoni.sh/cert-manager/templates/config" 8 | ) 9 | 10 | #ValidatingWebhook: admissionregistrationv1.#ValidatingWebhookConfiguration & { 11 | #config: cfg.#Config 12 | 13 | #meta: timoniv1.#MetaClusterComponent & { 14 | #Meta: #config.metadata 15 | #Component: "webhook" 16 | } 17 | 18 | apiVersion: "admissionregistration.k8s.io/v1" 19 | kind: "ValidatingWebhookConfiguration" 20 | metadata: #meta 21 | metadata: annotations: "cert-manager.io/inject-ca-from-secret": "\(#config.metadata.namespace)/\(#meta.name)-ca" 22 | 23 | webhooks: [{ 24 | name: "webhook.cert-manager.io" 25 | namespaceSelector: { 26 | matchExpressions: [{ 27 | key: "cert-manager.io/disable-validation" 28 | operator: "NotIn" 29 | values: [ 30 | "true", 31 | ] 32 | }] 33 | } 34 | rules: [{ 35 | apiGroups: [ 36 | "cert-manager.io", 37 | "acme.cert-manager.io", 38 | ] 39 | apiVersions: [ 40 | "v1", 41 | ] 42 | operations: [ 43 | "CREATE", 44 | "UPDATE", 45 | ] 46 | resources: [ 47 | "*/*", 48 | ] 49 | }] 50 | admissionReviewVersions: ["v1"] 51 | // This webhook only accepts v1 cert-manager resources. 52 | // Equivalent matchPolicy ensures that non-v1 resource requests are sent to 53 | // this webhook (after the resources have been converted to v1). 54 | matchPolicy: "Equivalent" 55 | timeoutSeconds: #config.webhook.timeoutSeconds 56 | failurePolicy: "Fail" 57 | sideEffects: "None" 58 | clientConfig: { 59 | if #config.webhook.url.host != _|_ { 60 | url: "https://\(#config.webhook.url.host)/validate" 61 | } 62 | if #config.webhook.url.host == _|_ { 63 | service: { 64 | name: #meta.name 65 | namespace: #config.metadata.namespace 66 | path: "/validate" 67 | } 68 | } 69 | } 70 | }] 71 | } 72 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/apis/meta/v1 4 | 5 | package v1 6 | 7 | // GroupResource specifies a Group and a Resource, but does not force a version. This is useful for identifying 8 | // concepts during lookup stages without having partially valid types 9 | // 10 | // +protobuf.options.(gogoproto.goproto_stringer)=false 11 | #GroupResource: { 12 | group: string @go(Group) @protobuf(1,bytes,opt) 13 | resource: string @go(Resource) @protobuf(2,bytes,opt) 14 | } 15 | 16 | // GroupVersionResource unambiguously identifies a resource. It doesn't anonymously include GroupVersion 17 | // to avoid automatic coercion. It doesn't use a GroupVersion to avoid custom marshalling 18 | // 19 | // +protobuf.options.(gogoproto.goproto_stringer)=false 20 | #GroupVersionResource: { 21 | group: string @go(Group) @protobuf(1,bytes,opt) 22 | version: string @go(Version) @protobuf(2,bytes,opt) 23 | resource: string @go(Resource) @protobuf(3,bytes,opt) 24 | } 25 | 26 | // GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying 27 | // concepts during lookup stages without having partially valid types 28 | // 29 | // +protobuf.options.(gogoproto.goproto_stringer)=false 30 | #GroupKind: { 31 | group: string @go(Group) @protobuf(1,bytes,opt) 32 | kind: string @go(Kind) @protobuf(2,bytes,opt) 33 | } 34 | 35 | // GroupVersionKind unambiguously identifies a kind. It doesn't anonymously include GroupVersion 36 | // to avoid automatic coercion. It doesn't use a GroupVersion to avoid custom marshalling 37 | // 38 | // +protobuf.options.(gogoproto.goproto_stringer)=false 39 | #GroupVersionKind: { 40 | group: string @go(Group) @protobuf(1,bytes,opt) 41 | version: string @go(Version) @protobuf(2,bytes,opt) 42 | kind: string @go(Kind) @protobuf(3,bytes,opt) 43 | } 44 | 45 | // GroupVersion contains the "group" and the "version", which uniquely identifies the API. 46 | // 47 | // +protobuf.options.(gogoproto.goproto_stringer)=false 48 | #GroupVersion: _ 49 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/coordination/v1/types_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/coordination/v1 4 | 5 | package v1 6 | 7 | import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | 9 | // Lease defines a lease concept. 10 | #Lease: { 11 | metav1.#TypeMeta 12 | 13 | // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata 14 | // +optional 15 | metadata?: metav1.#ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt) 16 | 17 | // spec contains the specification of the Lease. 18 | // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status 19 | // +optional 20 | spec?: #LeaseSpec @go(Spec) @protobuf(2,bytes,opt) 21 | } 22 | 23 | // LeaseSpec is a specification of a Lease. 24 | #LeaseSpec: { 25 | // holderIdentity contains the identity of the holder of a current lease. 26 | // +optional 27 | holderIdentity?: null | string @go(HolderIdentity,*string) @protobuf(1,bytes,opt) 28 | 29 | // leaseDurationSeconds is a duration that candidates for a lease need 30 | // to wait to force acquire it. This is measure against time of last 31 | // observed renewTime. 32 | // +optional 33 | leaseDurationSeconds?: null | int32 @go(LeaseDurationSeconds,*int32) @protobuf(2,varint,opt) 34 | 35 | // acquireTime is a time when the current lease was acquired. 36 | // +optional 37 | acquireTime?: null | metav1.#MicroTime @go(AcquireTime,*metav1.MicroTime) @protobuf(3,bytes,opt) 38 | 39 | // renewTime is a time when the current holder of a lease has last 40 | // updated the lease. 41 | // +optional 42 | renewTime?: null | metav1.#MicroTime @go(RenewTime,*metav1.MicroTime) @protobuf(4,bytes,opt) 43 | 44 | // leaseTransitions is the number of transitions of a lease between 45 | // holders. 46 | // +optional 47 | leaseTransitions?: null | int32 @go(LeaseTransitions,*int32) @protobuf(5,varint,opt) 48 | } 49 | 50 | // LeaseList is a list of Lease objects. 51 | #LeaseList: { 52 | metav1.#TypeMeta 53 | 54 | // Standard list metadata. 55 | // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata 56 | // +optional 57 | metadata?: metav1.#ListMeta @go(ListMeta) @protobuf(1,bytes,opt) 58 | 59 | // items is a list of schema objects. 60 | items: [...#Lease] @go(Items,[]Lease) @protobuf(2,bytes,rep) 61 | } 62 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/scheduling/v1/types_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/scheduling/v1 4 | 5 | package v1 6 | 7 | import ( 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | apiv1 "k8s.io/api/core/v1" 10 | ) 11 | 12 | // PriorityClass defines mapping from a priority class name to the priority 13 | // integer value. The value can be any valid integer. 14 | #PriorityClass: { 15 | metav1.#TypeMeta 16 | 17 | // Standard object's metadata. 18 | // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata 19 | // +optional 20 | metadata?: metav1.#ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt) 21 | 22 | // value represents the integer value of this priority class. This is the actual priority that pods 23 | // receive when they have the name of this class in their pod spec. 24 | value: int32 @go(Value) @protobuf(2,bytes,opt) 25 | 26 | // globalDefault specifies whether this PriorityClass should be considered as 27 | // the default priority for pods that do not have any priority class. 28 | // Only one PriorityClass can be marked as `globalDefault`. However, if more than 29 | // one PriorityClasses exists with their `globalDefault` field set to true, 30 | // the smallest value of such global default PriorityClasses will be used as the default priority. 31 | // +optional 32 | globalDefault?: bool @go(GlobalDefault) @protobuf(3,bytes,opt) 33 | 34 | // description is an arbitrary string that usually provides guidelines on 35 | // when this priority class should be used. 36 | // +optional 37 | description?: string @go(Description) @protobuf(4,bytes,opt) 38 | 39 | // preemptionPolicy is the Policy for preempting pods with lower priority. 40 | // One of Never, PreemptLowerPriority. 41 | // Defaults to PreemptLowerPriority if unset. 42 | // +optional 43 | preemptionPolicy?: null | apiv1.#PreemptionPolicy @go(PreemptionPolicy,*apiv1.PreemptionPolicy) @protobuf(5,bytes,opt) 44 | } 45 | 46 | // PriorityClassList is a collection of priority classes. 47 | #PriorityClassList: { 48 | metav1.#TypeMeta 49 | 50 | // Standard list metadata 51 | // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata 52 | // +optional 53 | metadata?: metav1.#ListMeta @go(ListMeta) @protobuf(1,bytes,opt) 54 | 55 | // items is the list of PriorityClasses 56 | items: [...#PriorityClass] @go(Items,[]PriorityClass) @protobuf(2,bytes,rep) 57 | } 58 | -------------------------------------------------------------------------------- /templates/role.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | "strings" 5 | rbacv1 "k8s.io/api/rbac/v1" 6 | timoniv1 "timoni.sh/core/v1alpha1" 7 | 8 | cfg "timoni.sh/cert-manager/templates/config" 9 | ) 10 | 11 | #Role: rbacv1.#Role & { 12 | #config: cfg.#Config 13 | #component: string 14 | #roleSuffix: string 15 | #namespace?: string 16 | 17 | #meta: timoniv1.#MetaComponent & { 18 | #Meta: #config.metadata 19 | #Component: strings.ToLower(#component) 20 | } 21 | apiVersion: "rbac.authorization.k8s.io/v1" 22 | kind: "Role" 23 | metadata: { 24 | name: "\(#meta.name):\(#roleSuffix)" 25 | namespace: *#namespace | #config.metadata.namespace 26 | labels: #meta.labels 27 | if #config.metadata.annotations != _|_ { 28 | annotations: #config.metadata.annotations 29 | } 30 | } 31 | } 32 | 33 | #ControllerRole: #Role & { 34 | #config: cfg.#Config 35 | #component: "controller" 36 | #roleSuffix: "leaderelection" 37 | #namespace: #config.leaderElection.namespace 38 | rules: [{ 39 | apiGroups: ["coordination.k8s.io"] 40 | resources: ["leases"] 41 | resourceNames: ["cert-manager-controller"] 42 | verbs: ["get", "update", "patch"] 43 | }, { 44 | apiGroups: ["coordination.k8s.io"] 45 | resources: ["leases"] 46 | verbs: ["create"] 47 | }] 48 | } 49 | 50 | #CaInjectorRole: #Role & { 51 | #config: cfg.#Config 52 | #component: "caInjector" 53 | #roleSuffix: "leaderelection" 54 | #namespace: #config.leaderElection.namespace 55 | rules: [{ 56 | apiGroups: ["coordination.k8s.io"] 57 | resources: ["leases"] 58 | resourceNames: ["cert-manager-cainjector-leader-election", "cert-manager-cainjector-leader-election-core"] 59 | verbs: ["get", "update", "patch"] 60 | }, { 61 | apiGroups: ["coordination.k8s.io"] 62 | resources: ["leases"] 63 | verbs: ["create"] 64 | }] 65 | } 66 | 67 | #StartupApiCheckRole: #Role & { 68 | #config: cfg.#Config 69 | #component: "startupAPICheck" 70 | #roleSuffix: "create-cert" 71 | rules: [{ 72 | apiGroups: ["cert-manager.io"] 73 | resources: ["certificates"] 74 | verbs: ["create"] 75 | }] 76 | } 77 | 78 | #WebhookRole: #Role & { 79 | #config: cfg.#Config 80 | #component: "webhook" 81 | #roleSuffix: "dynamic-serving" 82 | rules: [{ 83 | apiGroups: [""] 84 | resources: ["secrets"] 85 | resourceNames: [ 86 | "\(#config.metadata.name)-\(#component)-ca", 87 | ] 88 | verbs: ["get", "list", "watch", "update"] 89 | }, { 90 | apiGroups: [""] 91 | resources: ["secrets"] 92 | verbs: ["create"] 93 | }] 94 | } 95 | -------------------------------------------------------------------------------- /templates/startupAPICheckJob.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | batchv1 "k8s.io/api/batch/v1" 5 | timoniv1 "timoni.sh/core/v1alpha1" 6 | 7 | cfg "timoni.sh/cert-manager/templates/config" 8 | ) 9 | 10 | #StartupAPICheckJob: batchv1.#Job & { 11 | #config: cfg.#Config 12 | 13 | #meta: timoniv1.#MetaComponent & { 14 | #Meta: #config.metadata 15 | #Component: "startupapicheck" 16 | } 17 | 18 | apiVersion: "batch/v1" 19 | kind: "Job" 20 | metadata: #meta 21 | metadata: annotations: timoniv1.Action.Force 22 | 23 | if #config.test.startupAPICheck.jobAnnotations != _|_ { 24 | metadata: annotations: #config.test.startupAPICheck.jobAnnotations 25 | } 26 | 27 | spec: { 28 | backoffLimit: #config.test.startupAPICheck.backoffLimit 29 | template: { 30 | metadata: { 31 | labels: #meta.labels 32 | 33 | if #config.test.startupAPICheck.podLabels != _|_ { 34 | labels: #config.test.startupAPICheck.podLabels 35 | } 36 | 37 | if #config.test.startupAPICheck.podAnnotations != _|_ { 38 | annotations: #config.test.startupAPICheck.podAnnotations 39 | } 40 | } 41 | 42 | spec: { 43 | restartPolicy: "OnFailure" 44 | serviceAccountName: #meta.name 45 | enableServiceLinks: #config.test.startupAPICheck.enableServiceLinks 46 | automountServiceAccountToken: #config.test.startupAPICheck.automountServiceAccountToken 47 | securityContext: #config.test.startupAPICheck.securityContext 48 | nodeSelector: #config.test.startupAPICheck.nodeSelector 49 | 50 | if #config.priorityClassName != _|_ { 51 | priorityClassName: #config.priorityClassName 52 | } 53 | 54 | containers: [{ 55 | name: #meta.name 56 | image: #config.test.startupAPICheck.image.reference 57 | imagePullPolicy: #config.test.startupAPICheck.image.pullPolicy 58 | securityContext: #config.test.startupAPICheck.containerSecurityContext 59 | 60 | args: [ 61 | "check", 62 | "api", 63 | "--wait=\(#config.test.startupAPICheck.timeout)", 64 | for arg in #config.test.startupAPICheck.extraArgs {arg}, 65 | ] 66 | 67 | if #config.test.startupAPICheck.resources != _|_ { 68 | resources: #config.test.startupAPICheck.resources 69 | } 70 | 71 | if #config.test.startupAPICheck.volumeMounts != _|_ { 72 | volumeMounts: #config.test.startupAPICheck.volumeMounts 73 | } 74 | }] 75 | 76 | if #config.test.startupAPICheck.affinity != _|_ { 77 | affinity: #config.test.startupAPICheck.affinity 78 | } 79 | 80 | if #config.test.startupAPICheck.tolerations != _|_ { 81 | tolerations: #config.test.startupAPICheck.tolerations 82 | } 83 | 84 | if #config.test.startupAPICheck.volumes != _|_ { 85 | volumes: #config.test.startupAPICheck.volumes 86 | } 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/linux 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=linux 3 | 4 | ### Linux ### 5 | *~ 6 | 7 | # temporary files which can be created if a process still has a handle open of a deleted file 8 | .fuse_hidden* 9 | 10 | # KDE directory preferences 11 | .directory 12 | 13 | # Linux trash folder which might appear on any partition or disk 14 | .Trash-* 15 | 16 | # .nfs files are created when an open file is removed but is still being accessed 17 | .nfs* 18 | 19 | # End of https://www.toptal.com/developers/gitignore/api/linux 20 | # Created by https://www.toptal.com/developers/gitignore/api/macos 21 | # Edit at https://www.toptal.com/developers/gitignore?templates=macos 22 | 23 | ### macOS ### 24 | # General 25 | .DS_Store 26 | .AppleDouble 27 | .LSOverride 28 | 29 | # Icon must end with two \r 30 | Icon 31 | 32 | 33 | # Thumbnails 34 | ._* 35 | 36 | # Files that might appear in the root of a volume 37 | .DocumentRevisions-V100 38 | .fseventsd 39 | .Spotlight-V100 40 | .TemporaryItems 41 | .Trashes 42 | .VolumeIcon.icns 43 | .com.apple.timemachine.donotpresent 44 | 45 | # Directories potentially created on remote AFP share 46 | .AppleDB 47 | .AppleDesktop 48 | Network Trash Folder 49 | Temporary Items 50 | .apdisk 51 | 52 | ### macOS Patch ### 53 | # iCloud generated files 54 | *.icloud 55 | 56 | # End of https://www.toptal.com/developers/gitignore/api/macos 57 | # Created by https://www.toptal.com/developers/gitignore/api/windows 58 | # Edit at https://www.toptal.com/developers/gitignore?templates=windows 59 | 60 | ### Windows ### 61 | # Windows thumbnail cache files 62 | Thumbs.db 63 | Thumbs.db:encryptable 64 | ehthumbs.db 65 | ehthumbs_vista.db 66 | 67 | # Dump file 68 | *.stackdump 69 | 70 | # Folder config file 71 | [Dd]esktop.ini 72 | 73 | # Recycle Bin used on file shares 74 | $RECYCLE.BIN/ 75 | 76 | # Windows Installer files 77 | *.cab 78 | *.msi 79 | *.msix 80 | *.msm 81 | *.msp 82 | 83 | # Windows shortcuts 84 | *.lnk 85 | 86 | # End of https://www.toptal.com/developers/gitignore/api/windows 87 | # Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode 88 | # Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode 89 | 90 | ### VisualStudioCode ### 91 | .vscode/* 92 | !.vscode/settings.json 93 | !.vscode/tasks.json 94 | !.vscode/launch.json 95 | !.vscode/extensions.json 96 | !.vscode/*.code-snippets 97 | 98 | ### IntelliJ ### 99 | *.iml 100 | .idea 101 | 102 | # Local History for Visual Studio Code 103 | .history/ 104 | 105 | # Built Visual Studio Code Extensions 106 | *.vsix 107 | 108 | ### VisualStudioCode Patch ### 109 | # Ignore all local history of files 110 | .history 111 | .ionide 112 | 113 | # End of https://www.toptal.com/developers/gitignore/api/visualstudiocode 114 | 115 | output 116 | -------------------------------------------------------------------------------- /.github/workflows/e2e.yaml: -------------------------------------------------------------------------------- 1 | name: e2e 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | branches: [ main ] 7 | push: 8 | branches: [ main ] 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | kubernetes: 15 | strategy: 16 | matrix: 17 | version: [1.27.11, 1.28.7, 1.29.2] 18 | runs-on: ubuntu-latest 19 | services: 20 | registry: 21 | image: registry:2 22 | ports: 23 | - 5000:5000 24 | steps: 25 | - name: Checkout 26 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 27 | - name: Setup Go 28 | uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 29 | with: 30 | go-version: 1.21.x 31 | cache-dependency-path: | 32 | **/go.sum 33 | **/go.mod 34 | - name: Setup Kubernetes 35 | uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0 36 | with: 37 | version: v0.20.0 38 | node_image: kindest/node:v${{ matrix.version }} 39 | cluster_name: kind 40 | kubectl_version: v${{ matrix.version }} 41 | - name: Setup Timoni 42 | uses: stefanprodan/timoni/actions/setup@main 43 | - name: Push module 44 | run: | 45 | timoni mod push ./ oci://localhost:5000/cert-manager -v 1.0.0 --latest 46 | - name: Install module without rbac, expect failure 47 | continue-on-error: true 48 | run: | 49 | timoni -n test apply cert-manager oci://localhost:5000/cert-manager -f test/data/values-rbac.cue --timeout 60s 50 | - name: List modules 51 | run: | 52 | timoni list -A 53 | - name: Upgrade module, enable rbac, HA and monitoring 54 | run: | 55 | timoni -n test apply cert-manager oci://localhost:5000/cert-manager -v 1.0.0 -f test/data/values-high-availability.cue -f test/data/values-monitoring.cue 56 | - name: Upgrade module with debug values 57 | run: | 58 | timoni -n test apply cert-manager oci://localhost:5000/cert-manager -f ./debug_values.cue -f test/data/values-high-availability.cue -f test/data/values-monitoring.cue 59 | - name: Inspect module 60 | run: | 61 | timoni -n test inspect resources cert-manager 62 | timoni -n test inspect module cert-manager 63 | timoni -n test inspect values cert-manager 64 | - name: Status module 65 | run: | 66 | timoni -n test status cert-manager 67 | - name: Create ClusterIssuer 68 | run: | 69 | kubectl apply -f test/data/clusterIssuer.yaml 70 | kubectl describe -f test/data/clusterIssuer.yaml 71 | - name: Create Certificate 72 | run: | 73 | kubectl apply -f test/data/certificate.yaml 74 | echo "Sleeping for 30 seconds" 75 | sleep 30 76 | kubectl describe -f test/data/certificate.yaml 77 | READY=$(kubectl -n test get certificate my-selfsigned-ca -o jsonpath="{$.status.conditions[?(@.type=='Ready')].status}") 78 | [ "${READY}" = "True" ] && echo "Certificate created successfully" 79 | - name: Uninstall module 80 | run: | 81 | timoni -n test delete cert-manager --wait 82 | -------------------------------------------------------------------------------- /cue.mod/pkg/timoni.sh/core/v1alpha1/image.cue: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Stefan Prodan 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package v1alpha1 5 | 6 | import ( 7 | "encoding/base64" 8 | "strings" 9 | ) 10 | 11 | // Image defines the schema for OCI image reference used in Kubernetes PodSpec container image. 12 | #Image: { 13 | 14 | // Repository is the address of a container registry repository. 15 | // An image repository is made up of slash-separated name components, optionally 16 | // prefixed by a registry hostname and port in the format [HOST[:PORT_NUMBER]/]PATH. 17 | repository!: string 18 | 19 | // Tag identifies an image in the repository. 20 | // A tag name may contain lowercase and uppercase characters, digits, underscores, periods and dashes. 21 | // A tag name may not start with a period or a dash and may contain a maximum of 128 characters. 22 | tag!: string & strings.MaxRunes(128) 23 | 24 | // Digest uniquely and immutably identifies an image in the repository. 25 | // Spec: https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests. 26 | digest!: string 27 | 28 | // PullPolicy defines the pull policy for the image. 29 | // By default, it is set to IfNotPresent. 30 | pullPolicy: *"IfNotPresent" | "Always" | "Never" 31 | 32 | // Reference is the image address computed from repository, tag and digest 33 | // in the format [REPOSITORY]:[TAG]@[DIGEST]. 34 | // +nodoc 35 | reference: string 36 | 37 | if digest != "" && tag != "" { 38 | reference: "\(repository):\(tag)@\(digest)" 39 | } 40 | 41 | if digest != "" && tag == "" { 42 | reference: "\(repository)@\(digest)" 43 | } 44 | 45 | if digest == "" && tag != "" { 46 | reference: "\(repository):\(tag)" 47 | } 48 | 49 | if digest == "" && tag == "" { 50 | reference: "\(repository):latest" 51 | } 52 | } 53 | 54 | // ImagePullSecret is a generator for Kubernetes Secrets of type kubernetes.io/dockerconfigjson. 55 | // Spec: https://kubernetes.io/docs/concepts/configuration/secret/#docker-config-secrets. 56 | #ImagePullSecret: { 57 | // Metadata is the Kubernetes object's metadata generated by Timoni. 58 | meta=metadata: #Metadata 59 | 60 | // Registry is the hostname of the container registry in the format [HOST[:PORT_NUMBER]]. 61 | registry!: string 62 | 63 | // Username is the username used to authenticate to the container registry. 64 | username!: string 65 | 66 | // Password is the password used to authenticate to the container registry. 67 | password!: string 68 | 69 | // Optional suffix used to generate the Secret name. 70 | suffix: *"" | string 71 | 72 | let auth = base64.Encode(null, username+":"+password) 73 | 74 | // The object is a read-only struct that contains the generated 75 | // Kubernetes Secret of type kubernetes.io/dockerconfigjson. 76 | object: { 77 | apiVersion: "v1" 78 | kind: "Secret" 79 | type: "kubernetes.io/dockerconfigjson" 80 | metadata: { 81 | name: meta.name + suffix 82 | namespace: meta.namespace 83 | labels: meta.labels 84 | if meta.annotations != _|_ { 85 | annotations: meta.annotations 86 | } 87 | } 88 | stringData: { 89 | ".dockerconfigjson": #""" 90 | { 91 | "auths": { 92 | "\#(registry)": { 93 | "username": "\#(username)", 94 | "password": "\#(password)", 95 | "auth": "\#(auth)" 96 | } 97 | } 98 | } 99 | """# 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/types_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | package runtime 6 | 7 | // TypeMeta is shared by all top level objects. The proper way to use it is to inline it in your type, 8 | // like this: 9 | // 10 | // type MyAwesomeAPIObject struct { 11 | // runtime.TypeMeta `json:",inline"` 12 | // ... // other fields 13 | // } 14 | // 15 | // func (obj *MyAwesomeAPIObject) SetGroupVersionKind(gvk *metav1.GroupVersionKind) { metav1.UpdateTypeMeta(obj,gvk) }; GroupVersionKind() *GroupVersionKind 16 | // 17 | // TypeMeta is provided here for convenience. You may use it directly from this package or define 18 | // your own with the same fields. 19 | // 20 | // +k8s:deepcopy-gen=false 21 | // +protobuf=true 22 | // +k8s:openapi-gen=true 23 | #TypeMeta: { 24 | // +optional 25 | apiVersion?: string @go(APIVersion) @protobuf(1,bytes,opt) 26 | 27 | // +optional 28 | kind?: string @go(Kind) @protobuf(2,bytes,opt) 29 | } 30 | 31 | #ContentTypeJSON: "application/json" 32 | #ContentTypeYAML: "application/yaml" 33 | #ContentTypeProtobuf: "application/vnd.kubernetes.protobuf" 34 | 35 | // RawExtension is used to hold extensions in external versions. 36 | // 37 | // To use this, make a field which has RawExtension as its type in your external, versioned 38 | // struct, and Object in your internal struct. You also need to register your 39 | // various plugin types. 40 | // 41 | // // Internal package: 42 | // 43 | // type MyAPIObject struct { 44 | // runtime.TypeMeta `json:",inline"` 45 | // MyPlugin runtime.Object `json:"myPlugin"` 46 | // } 47 | // 48 | // type PluginA struct { 49 | // AOption string `json:"aOption"` 50 | // } 51 | // 52 | // // External package: 53 | // 54 | // type MyAPIObject struct { 55 | // runtime.TypeMeta `json:",inline"` 56 | // MyPlugin runtime.RawExtension `json:"myPlugin"` 57 | // } 58 | // 59 | // type PluginA struct { 60 | // AOption string `json:"aOption"` 61 | // } 62 | // 63 | // // On the wire, the JSON will look something like this: 64 | // 65 | // { 66 | // "kind":"MyAPIObject", 67 | // "apiVersion":"v1", 68 | // "myPlugin": { 69 | // "kind":"PluginA", 70 | // "aOption":"foo", 71 | // }, 72 | // } 73 | // 74 | // So what happens? Decode first uses json or yaml to unmarshal the serialized data into 75 | // your external MyAPIObject. That causes the raw JSON to be stored, but not unpacked. 76 | // The next step is to copy (using pkg/conversion) into the internal struct. The runtime 77 | // package's DefaultScheme has conversion functions installed which will unpack the 78 | // JSON stored in RawExtension, turning it into the correct object type, and storing it 79 | // in the Object. (TODO: In the case where the object is of an unknown type, a 80 | // runtime.Unknown object will be created and stored.) 81 | // 82 | // +k8s:deepcopy-gen=true 83 | // +protobuf=true 84 | // +k8s:openapi-gen=true 85 | #RawExtension: _ 86 | 87 | // Unknown allows api objects with unknown types to be passed-through. This can be used 88 | // to deal with the API objects from a plug-in. Unknown objects still have functioning 89 | // TypeMeta features-- kind, version, etc. 90 | // TODO: Make this object have easy access to field based accessors and settors for 91 | // metadata and field mutatation. 92 | // 93 | // +k8s:deepcopy-gen=true 94 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 95 | // +protobuf=true 96 | // +k8s:openapi-gen=true 97 | #Unknown: _ 98 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/core/v1/well_known_labels_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/core/v1 4 | 5 | package v1 6 | 7 | #LabelHostname: "kubernetes.io/hostname" 8 | 9 | // Label value is the network location of kube-apiserver stored as 10 | // Stored in APIServer Identity lease objects to view what address is used for peer proxy 11 | #AnnotationPeerAdvertiseAddress: "kubernetes.io/peer-advertise-address" 12 | #LabelTopologyZone: "topology.kubernetes.io/zone" 13 | #LabelTopologyRegion: "topology.kubernetes.io/region" 14 | 15 | // These label have been deprecated since 1.17, but will be supported for 16 | // the foreseeable future, to accommodate things like long-lived PVs that 17 | // use them. New users should prefer the "topology.kubernetes.io/*" 18 | // equivalents. 19 | #LabelFailureDomainBetaZone: "failure-domain.beta.kubernetes.io/zone" 20 | #LabelFailureDomainBetaRegion: "failure-domain.beta.kubernetes.io/region" 21 | 22 | // Retained for compat when vendored. Do not use these consts in new code. 23 | #LabelZoneFailureDomain: "failure-domain.beta.kubernetes.io/zone" 24 | #LabelZoneRegion: "failure-domain.beta.kubernetes.io/region" 25 | #LabelZoneFailureDomainStable: "topology.kubernetes.io/zone" 26 | #LabelZoneRegionStable: "topology.kubernetes.io/region" 27 | #LabelInstanceType: "beta.kubernetes.io/instance-type" 28 | #LabelInstanceTypeStable: "node.kubernetes.io/instance-type" 29 | #LabelOSStable: "kubernetes.io/os" 30 | #LabelArchStable: "kubernetes.io/arch" 31 | 32 | // LabelWindowsBuild is used on Windows nodes to specify the Windows build number starting with v1.17.0. 33 | // It's in the format MajorVersion.MinorVersion.BuildNumber (for ex: 10.0.17763) 34 | #LabelWindowsBuild: "node.kubernetes.io/windows-build" 35 | 36 | // LabelNamespaceSuffixKubelet is an allowed label namespace suffix kubelets can self-set ([*.]kubelet.kubernetes.io/*) 37 | #LabelNamespaceSuffixKubelet: "kubelet.kubernetes.io" 38 | 39 | // LabelNamespaceSuffixNode is an allowed label namespace suffix kubelets can self-set ([*.]node.kubernetes.io/*) 40 | #LabelNamespaceSuffixNode: "node.kubernetes.io" 41 | 42 | // LabelNamespaceNodeRestriction is a forbidden label namespace that kubelets may not self-set when the NodeRestriction admission plugin is enabled 43 | #LabelNamespaceNodeRestriction: "node-restriction.kubernetes.io" 44 | 45 | // IsHeadlessService is added by Controller to an Endpoint denoting if its parent 46 | // Service is Headless. The existence of this label can be used further by other 47 | // controllers and kube-proxy to check if the Endpoint objects should be replicated when 48 | // using Headless Services 49 | #IsHeadlessService: "service.kubernetes.io/headless" 50 | 51 | // LabelNodeExcludeBalancers specifies that the node should not be considered as a target 52 | // for external load-balancers which use nodes as a second hop (e.g. many cloud LBs which only 53 | // understand nodes). For services that use externalTrafficPolicy=Local, this may mean that 54 | // any backends on excluded nodes are not reachable by those external load-balancers. 55 | // Implementations of this exclusion may vary based on provider. 56 | #LabelNodeExcludeBalancers: "node.kubernetes.io/exclude-from-external-load-balancers" 57 | 58 | // LabelMetadataName is the label name which, in-tree, is used to automatically label namespaces, so they can be selected easily by tools which require definitive labels 59 | #LabelMetadataName: "kubernetes.io/metadata.name" 60 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/node/v1/types_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/node/v1 4 | 5 | package v1 6 | 7 | import ( 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | corev1 "k8s.io/api/core/v1" 10 | ) 11 | 12 | // RuntimeClass defines a class of container runtime supported in the cluster. 13 | // The RuntimeClass is used to determine which container runtime is used to run 14 | // all containers in a pod. RuntimeClasses are manually defined by a 15 | // user or cluster provisioner, and referenced in the PodSpec. The Kubelet is 16 | // responsible for resolving the RuntimeClassName reference before running the 17 | // pod. For more details, see 18 | // https://kubernetes.io/docs/concepts/containers/runtime-class/ 19 | #RuntimeClass: { 20 | metav1.#TypeMeta 21 | 22 | // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata 23 | // +optional 24 | metadata?: metav1.#ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt) 25 | 26 | // handler specifies the underlying runtime and configuration that the CRI 27 | // implementation will use to handle pods of this class. The possible values 28 | // are specific to the node & CRI configuration. It is assumed that all 29 | // handlers are available on every node, and handlers of the same name are 30 | // equivalent on every node. 31 | // For example, a handler called "runc" might specify that the runc OCI 32 | // runtime (using native Linux containers) will be used to run the containers 33 | // in a pod. 34 | // The Handler must be lowercase, conform to the DNS Label (RFC 1123) requirements, 35 | // and is immutable. 36 | handler: string @go(Handler) @protobuf(2,bytes,opt) 37 | 38 | // overhead represents the resource overhead associated with running a pod for a 39 | // given RuntimeClass. For more details, see 40 | // https://kubernetes.io/docs/concepts/scheduling-eviction/pod-overhead/ 41 | // +optional 42 | overhead?: null | #Overhead @go(Overhead,*Overhead) @protobuf(3,bytes,opt) 43 | 44 | // scheduling holds the scheduling constraints to ensure that pods running 45 | // with this RuntimeClass are scheduled to nodes that support it. 46 | // If scheduling is nil, this RuntimeClass is assumed to be supported by all 47 | // nodes. 48 | // +optional 49 | scheduling?: null | #Scheduling @go(Scheduling,*Scheduling) @protobuf(4,bytes,opt) 50 | } 51 | 52 | // Overhead structure represents the resource overhead associated with running a pod. 53 | #Overhead: { 54 | // podFixed represents the fixed resource overhead associated with running a pod. 55 | // +optional 56 | podFixed?: corev1.#ResourceList @go(PodFixed) @protobuf(1,bytes,opt,casttype=k8s.io/api/core/v1.ResourceList,castkey=k8s.io/api/core/v1.ResourceName,castvalue=k8s.io/apimachinery/pkg/api/resource.Quantity) 57 | } 58 | 59 | // Scheduling specifies the scheduling constraints for nodes supporting a 60 | // RuntimeClass. 61 | #Scheduling: { 62 | // nodeSelector lists labels that must be present on nodes that support this 63 | // RuntimeClass. Pods using this RuntimeClass can only be scheduled to a 64 | // node matched by this selector. The RuntimeClass nodeSelector is merged 65 | // with a pod's existing nodeSelector. Any conflicts will cause the pod to 66 | // be rejected in admission. 67 | // +optional 68 | // +mapType=atomic 69 | nodeSelector?: {[string]: string} @go(NodeSelector,map[string]string) @protobuf(1,bytes,opt) 70 | 71 | // tolerations are appended (excluding duplicates) to pods running with this 72 | // RuntimeClass during admission, effectively unioning the set of nodes 73 | // tolerated by the pod and the RuntimeClass. 74 | // +optional 75 | // +listType=atomic 76 | tolerations?: [...corev1.#Toleration] @go(Tolerations,[]corev1.Toleration) @protobuf(2,bytes,rep) 77 | } 78 | 79 | // RuntimeClassList is a list of RuntimeClass objects. 80 | #RuntimeClassList: { 81 | metav1.#TypeMeta 82 | 83 | // Standard list metadata. 84 | // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata 85 | // +optional 86 | metadata?: metav1.#ListMeta @go(ListMeta) @protobuf(1,bytes,opt) 87 | 88 | // items is a list of schema objects. 89 | items: [...#RuntimeClass] @go(Items,[]RuntimeClass) @protobuf(2,bytes,rep) 90 | } 91 | -------------------------------------------------------------------------------- /templates/config/component.cue: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | appsv1 "k8s.io/api/apps/v1" 5 | corev1 "k8s.io/api/core/v1" 6 | timoniv1 "timoni.sh/core/v1alpha1" 7 | ) 8 | 9 | #Component: { 10 | // group of affinity scheduling rules. 11 | affinity?: corev1.#Affinity 12 | // indicates whether a service account token should be automatically mounted. 13 | automountServiceAccountToken: *false | bool 14 | // is the security context for the container. 15 | containerSecurityContext: #ContainerSecurityContext 16 | // is the annotations for the deployment. 17 | deploymentAnnotations?: timoniv1.#Annotations 18 | // is the labels for the deployment. 19 | deploymentLabels?: timoniv1.#Labels 20 | // indicates whether information about services should be injected into pod's environment variables, matching the syntax of Docker links. 21 | enableServiceLinks: *false | bool 22 | // Additional command line flags to pass to cert-manager binaries. 23 | // To see all available flags run docker run quay.io/jetstack/cert-manager-: --help 24 | extraArgs?: [...string] 25 | // is a list of additional environment variables to pass to the container. 26 | extraEnvs?: [...corev1.#EnvVar] 27 | // is the container image to use. 28 | image!: timoniv1.#Image 29 | // is the liveness probe. 30 | livenessProbe: corev1.#Probe 31 | // is a selector which must be true for the pod to fit on a node. 32 | nodeSelector: timoniv1.#Labels 33 | // +nodoc 34 | nodeSelector: "kubernetes.io/os": "linux" 35 | // is the annotations for the pod. 36 | podAnnotations?: timoniv1.#Annotations 37 | // is the pod disruption budget. 38 | podDisruptionBudget: #PodDisruptionBudgetData 39 | // is the labels for the pod. 40 | podLabels?: timoniv1.#Labels 41 | // defines the proxy configuration to be used by the container. 42 | proxy?: #Proxy 43 | // is the readiness probe. 44 | readinessProbe: corev1.#Probe 45 | // is the number of desired replicas. 46 | replicas: *1 | uint16 & >0 47 | 48 | // is the resource requirements for the container. 49 | resources?: timoniv1.#ResourceRequirements & { 50 | requests?: timoniv1.#ResourceRequirement & { 51 | cpu: *"10m" | timoniv1.#CPUQuantity 52 | memory: *"32Mi" | timoniv1.#MemoryQuantity 53 | } 54 | } 55 | 56 | // is the security context for the container. 57 | securityContext: #SecurityContext 58 | serviceAccount: { 59 | // is the annotations for the service account. 60 | annotations?: timoniv1.#Annotations 61 | // is the labels for the service account. 62 | labels?: timoniv1.#Labels 63 | // indicates whether a service account token should be automatically mounted. 64 | automountServiceAccountToken: *false | bool 65 | } 66 | 67 | service: { 68 | // is the annotations for the service. 69 | annotations?: timoniv1.#Annotations 70 | // is the labels for the service. 71 | labels?: timoniv1.#Labels 72 | // is the type of the service. 73 | type: *corev1.#ServiceTypeClusterIP | corev1.#enumServiceType 74 | } 75 | 76 | // is the deployment strategy to use to replace existing pods with new ones. 77 | strategy?: appsv1.#DeploymentStrategy 78 | // is the tolerations for the pod. 79 | tolerations?: [...corev1.#Toleration] 80 | // is the topology spread constraints for the pod. 81 | topologySpreadConstraints?: [...corev1.#TopologySpreadConstraint] 82 | 83 | // is the volume mounts for the container. 84 | volumeMounts: [...corev1.#VolumeMount] | *[{ 85 | mountPath: "/var/run/secrets/kubernetes.io/serviceaccount" 86 | name: "serviceaccount-token" 87 | readOnly: true 88 | }] 89 | 90 | // is the volumes for the pod. 91 | volumes: [...corev1.#Volume] | *[{ 92 | name: "serviceaccount-token" 93 | projected: { 94 | defaultMode: 444 95 | sources: [{ 96 | serviceAccountToken: { 97 | expirationSeconds: 3607 98 | path: "token" 99 | } 100 | }, { 101 | configMap: { 102 | name: "kube-root-ca.crt" 103 | items: [{ 104 | key: "ca.crt" 105 | path: "ca.crt" 106 | }] 107 | } 108 | }, { 109 | downwardAPI: { 110 | items: [{ 111 | path: "namespace" 112 | fieldRef: { 113 | apiVersion: "v1" 114 | fieldPath: "metadata.namespace" 115 | } 116 | }] 117 | } 118 | }] 119 | } 120 | }] 121 | } 122 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/api/resource/quantity_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/api/resource 4 | 5 | package resource 6 | 7 | // Quantity is a fixed-point representation of a number. 8 | // It provides convenient marshaling/unmarshaling in JSON and YAML, 9 | // in addition to String() and AsInt64() accessors. 10 | // 11 | // The serialization format is: 12 | // 13 | // ``` 14 | // ::= 15 | // 16 | // (Note that may be empty, from the "" case in .) 17 | // 18 | // ::= 0 | 1 | ... | 9 19 | // ::= | 20 | // ::= | . | . | . 21 | // ::= "+" | "-" 22 | // ::= | 23 | // ::= | | 24 | // ::= Ki | Mi | Gi | Ti | Pi | Ei 25 | // 26 | // (International System of units; See: http://physics.nist.gov/cuu/Units/binary.html) 27 | // 28 | // ::= m | "" | k | M | G | T | P | E 29 | // 30 | // (Note that 1024 = 1Ki but 1000 = 1k; I didn't choose the capitalization.) 31 | // 32 | // ::= "e" | "E" 33 | // ``` 34 | // 35 | // No matter which of the three exponent forms is used, no quantity may represent 36 | // a number greater than 2^63-1 in magnitude, nor may it have more than 3 decimal 37 | // places. Numbers larger or more precise will be capped or rounded up. 38 | // (E.g.: 0.1m will rounded up to 1m.) 39 | // This may be extended in the future if we require larger or smaller quantities. 40 | // 41 | // When a Quantity is parsed from a string, it will remember the type of suffix 42 | // it had, and will use the same type again when it is serialized. 43 | // 44 | // Before serializing, Quantity will be put in "canonical form". 45 | // This means that Exponent/suffix will be adjusted up or down (with a 46 | // corresponding increase or decrease in Mantissa) such that: 47 | // 48 | // - No precision is lost 49 | // - No fractional digits will be emitted 50 | // - The exponent (or suffix) is as large as possible. 51 | // 52 | // The sign will be omitted unless the number is negative. 53 | // 54 | // Examples: 55 | // 56 | // - 1.5 will be serialized as "1500m" 57 | // - 1.5Gi will be serialized as "1536Mi" 58 | // 59 | // Note that the quantity will NEVER be internally represented by a 60 | // floating point number. That is the whole point of this exercise. 61 | // 62 | // Non-canonical values will still parse as long as they are well formed, 63 | // but will be re-emitted in their canonical form. (So always use canonical 64 | // form, or don't diff.) 65 | // 66 | // This format is intended to make it difficult to use these numbers without 67 | // writing some sort of special handling code in the hopes that that will 68 | // cause implementors to also use a fixed point implementation. 69 | // 70 | // +protobuf=true 71 | // +protobuf.embed=string 72 | // +protobuf.options.marshal=false 73 | // +protobuf.options.(gogoproto.goproto_stringer)=false 74 | // +k8s:deepcopy-gen=true 75 | // +k8s:openapi-gen=true 76 | #Quantity: _ 77 | 78 | // CanonicalValue allows a quantity amount to be converted to a string. 79 | #CanonicalValue: _ 80 | 81 | // Format lists the three possible formattings of a quantity. 82 | #Format: string // #enumFormat 83 | 84 | #enumFormat: 85 | #DecimalExponent | 86 | #BinarySI | 87 | #DecimalSI 88 | 89 | #DecimalExponent: #Format & "DecimalExponent" 90 | #BinarySI: #Format & "BinarySI" 91 | #DecimalSI: #Format & "DecimalSI" 92 | 93 | // splitREString is used to separate a number from its suffix; as such, 94 | // this is overly permissive, but that's OK-- it will be checked later. 95 | _#splitREString: "^([+-]?[0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$" 96 | 97 | _#int64QuantityExpectedBytes: 18 98 | 99 | // QuantityValue makes it possible to use a Quantity as value for a command 100 | // line parameter. 101 | // 102 | // +protobuf=true 103 | // +protobuf.embed=string 104 | // +protobuf.options.marshal=false 105 | // +protobuf.options.(gogoproto.goproto_stringer)=false 106 | // +k8s:deepcopy-gen=true 107 | #QuantityValue: _ 108 | -------------------------------------------------------------------------------- /templates/deployment.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | "strings" 5 | appsv1 "k8s.io/api/apps/v1" 6 | corev1 "k8s.io/api/core/v1" 7 | timoniv1 "timoni.sh/core/v1alpha1" 8 | 9 | cfg "timoni.sh/cert-manager/templates/config" 10 | ) 11 | 12 | #Deployment: appsv1.#Deployment & { 13 | #config: cfg.#Config 14 | #meta: timoniv1.#MetaComponent 15 | #component: string 16 | 17 | if #config[#component].deploymentLabels != _|_ { 18 | metadata: labels: #config[#component].deploymentLabels 19 | } 20 | 21 | if #config[#component].deploymentAnnotations != _|_ { 22 | metadata: annotations: #config[#component].deploymentAnnotations 23 | } 24 | 25 | apiVersion: "apps/v1" 26 | kind: "Deployment" 27 | metadata: #meta 28 | 29 | spec: appsv1.#DeploymentSpec & { 30 | selector: matchLabels: #meta.#LabelSelector 31 | replicas: #config[#component].replicas 32 | 33 | if #config[#component].strategy != _|_ { 34 | strategy: appsv1.#DeploymentStrategy & #config[#component].strategy 35 | } 36 | 37 | template: corev1.#PodTemplateSpec & { 38 | metadata: labels: #meta.labels 39 | 40 | if #config[#component].podLabels != _|_ { 41 | metadata: labels: #config[#component].podLabels 42 | } 43 | 44 | if #config[#component].podAnnotations != _|_ { 45 | metadata: annotations: #config[#component].podAnnotations 46 | } 47 | 48 | spec: corev1.#PodSpec & { 49 | containers: [...corev1.#Container] & [ 50 | { 51 | name: #meta.name 52 | image: #config[#component].image.reference 53 | imagePullPolicy: #config[#component].image.pullPolicy 54 | securityContext: #config[#component].containerSecurityContext 55 | 56 | if #config[#component].resources != _|_ { 57 | resources: #config[#component].resources 58 | } 59 | 60 | env: [ 61 | { 62 | name: "POD_NAMESPACE" 63 | valueFrom: fieldRef: fieldPath: "metadata.namespace" 64 | }, 65 | 66 | if #config[#component].extraEnvs != _|_ { 67 | for e in #config[#component].extraEnvs {e} 68 | }, 69 | ] 70 | }, 71 | ] 72 | serviceAccountName: #meta.name 73 | securityContext: #config[#component].securityContext 74 | nodeSelector: #config[#component].nodeSelector 75 | automountServiceAccountToken: #config[#component].automountServiceAccountToken 76 | 77 | if #config[#component].enableServiceLinks { 78 | enableServiceLinks: #config[#component].enableServiceLinks 79 | } 80 | 81 | if #config.priorityClassName != _|_ { 82 | priorityClassName: #config.priorityClassName 83 | } 84 | 85 | if #config[#component].affinity != _|_ { 86 | affinity: #config[#component].affinity 87 | } 88 | 89 | if #config[#component].tolerations != _|_ { 90 | tolerations: #config[#component].tolerations 91 | } 92 | 93 | if #config[#component].topologySpreadConstraints != _|_ { 94 | topologySpreadConstraints: #config[#component].topologySpreadConstraints 95 | } 96 | } 97 | } 98 | } 99 | } 100 | 101 | #ControllerDeployment: #Deployment & { 102 | #config: cfg.#Config 103 | #component: "controller" 104 | 105 | #meta: timoniv1.#MetaComponent & { 106 | #Meta: #config.metadata 107 | #Component: strings.ToLower(#component) 108 | } 109 | 110 | spec: #ControllerDeploymentSpec & { 111 | #main_config: #config 112 | #deployment_meta: #meta 113 | #deployment_monitoring?: #config.controller.monitoring 114 | } 115 | } 116 | 117 | #WebhookDeployment: #Deployment & { 118 | #config: cfg.#Config 119 | #component: "webhook" 120 | 121 | #meta: timoniv1.#MetaComponent & { 122 | #Meta: #config.metadata 123 | #Component: strings.ToLower(#component) 124 | } 125 | 126 | spec: #WebhookDeploymentSpec & { 127 | #main_config: #config 128 | #deployment_meta: #meta 129 | } 130 | } 131 | 132 | #CaInjectorrDeployment: #Deployment & { 133 | #config: cfg.#Config 134 | #component: "caInjector" 135 | 136 | #meta: timoniv1.#MetaComponent & { 137 | #Meta: #config.metadata 138 | #Component: strings.ToLower(#component) 139 | } 140 | 141 | spec: #CAInjectorDeploymentSpec & { 142 | #main_config: #config 143 | #deployment_meta: #meta 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /cue.mod/pkg/timoni.sh/core/v1alpha1/metadata.cue: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Stefan Prodan 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package v1alpha1 5 | 6 | import "strings" 7 | 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 | 21 | // Metadata defines the schema for Kubernetes object metadata. 22 | #Metadata: { 23 | // Version should be in the strict semver format. Is required when creating resources. 24 | #Version!: string & strings.MaxRunes(63) 25 | 26 | // Name must be unique within a namespace. Is required when creating resources. 27 | // Name is primarily intended for creation idempotence and configuration definition. 28 | // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names 29 | name!: #InstanceName 30 | 31 | // Namespace defines the space within which each name must be unique. 32 | // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces 33 | namespace!: #InstanceNamespace 34 | 35 | // Annotations is an unstructured key value map stored with a resource that may be 36 | // set to store and retrieve arbitrary metadata. 37 | // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations 38 | annotations?: #Annotations 39 | 40 | // Map of string keys and values that can be used to organize and categorize (scope and select) objects. 41 | // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels 42 | labels: #Labels 43 | 44 | // Standard Kubernetes labels: app name, version and managed-by. 45 | labels: { 46 | // +nodoc 47 | "\(#StdLabelName)": name 48 | // +nodoc 49 | "\(#StdLabelVersion)": #Version 50 | // +nodoc 51 | "\(#StdLabelManagedBy)": "timoni" 52 | } 53 | 54 | // LabelSelector selects Pods based on the app.kubernetes.io/name label. 55 | #LabelSelector: #Labels & { 56 | "\(#StdLabelName)": name 57 | } 58 | } 59 | 60 | // MetaComponent generates the Kubernetes object metadata for a module namespaced component. 61 | // The metadata.name is composed of the instance name and the component name. 62 | // The metadata.labels contain the app.kubernetes.io/component label. 63 | #MetaComponent: { 64 | // Meta is the Kubernetes object's metadata generated by Timoni. 65 | #Meta!: #Metadata 66 | 67 | // Component is the name of the component used 68 | // as a suffix for the generate object name. 69 | #Component!: string & strings.MaxRunes(30) 70 | 71 | name: #Meta.name + "-" + #Component 72 | namespace: #Meta.namespace 73 | 74 | labels: #Meta.labels 75 | // +nodoc 76 | labels: "\(#StdLabelComponent)": #Component 77 | 78 | annotations?: #Annotations 79 | if #Meta.annotations != _|_ { 80 | annotations: #Meta.annotations 81 | } 82 | 83 | // LabelSelector selects Pods based on the app.kubernetes.io/name 84 | // and app.kubernetes.io/component labels. 85 | #LabelSelector: #Labels & { 86 | "\(#StdLabelComponent)": #Component 87 | "\(#StdLabelName)": #Meta.name 88 | } 89 | } 90 | 91 | // MetaClusterComponent generates the Kubernetes object metadata for a module non-namespaced component. 92 | // The metadata.name is composed of the instance name and the component name. 93 | // The metadata.namespace is unset. 94 | // The metadata.labels contain the app.kubernetes.io/component label. 95 | #MetaClusterComponent: { 96 | // Meta is the Kubernetes object's metadata generated by Timoni. 97 | #Meta!: #Metadata 98 | 99 | // Component is the name of the component used 100 | // as a suffix for the generate object name. 101 | #Component!: string & strings.MaxRunes(30) 102 | 103 | name: #Meta.name + "-" + #Component 104 | 105 | labels: #Meta.labels 106 | // +nodoc 107 | labels: "\(#StdLabelComponent)": #Component 108 | 109 | annotations?: #Annotations 110 | if #Meta.annotations != _|_ { 111 | annotations: #Meta.annotations 112 | } 113 | 114 | // LabelSelector selects Pods based on the app.kubernetes.io/name 115 | // and app.kubernetes.io/component labels. 116 | #LabelSelector: #Labels & { 117 | "\(#StdLabelComponent)": #Component 118 | "\(#StdLabelName)": #Meta.name 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /cue.mod/gen/monitoring.coreos.com/podmonitor/v1/types_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by timoni. DO NOT EDIT. 2 | 3 | //timoni:generate timoni vendor crd -f https://github.com/prometheus-operator/prometheus-operator/releases/download/v0.68.0/stripped-down-crds.yaml 4 | 5 | package v1 6 | 7 | import "strings" 8 | 9 | #PodMonitor: { 10 | apiVersion: "monitoring.coreos.com/v1" 11 | kind: "PodMonitor" 12 | metadata!: { 13 | name!: strings.MaxRunes(253) & strings.MinRunes(1) & { 14 | string 15 | } 16 | namespace!: strings.MaxRunes(63) & strings.MinRunes(1) & { 17 | string 18 | } 19 | labels?: { 20 | [string]: string 21 | } 22 | annotations?: { 23 | [string]: string 24 | } 25 | } 26 | spec!: #PodMonitorSpec 27 | } 28 | #PodMonitorSpec: { 29 | attachMetadata?: { 30 | node?: bool 31 | } 32 | jobLabel?: string 33 | keepDroppedTargets?: int 34 | labelLimit?: int 35 | labelNameLengthLimit?: int 36 | labelValueLengthLimit?: int 37 | namespaceSelector?: { 38 | any?: bool 39 | matchNames?: [...string] 40 | } 41 | podMetricsEndpoints: [...{ 42 | authorization?: { 43 | credentials?: { 44 | key: string 45 | name?: string 46 | optional?: bool 47 | } 48 | type?: string 49 | } 50 | basicAuth?: { 51 | password?: { 52 | key: string 53 | name?: string 54 | optional?: bool 55 | } 56 | username?: { 57 | key: string 58 | name?: string 59 | optional?: bool 60 | } 61 | } 62 | bearerTokenSecret?: { 63 | key: string 64 | name?: string 65 | optional?: bool 66 | } 67 | enableHttp2?: bool 68 | filterRunning?: bool 69 | followRedirects?: bool 70 | honorLabels?: bool 71 | honorTimestamps?: bool 72 | interval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 73 | metricRelabelings?: [...{ 74 | action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace" 75 | modulus?: int 76 | regex?: string 77 | replacement?: string 78 | separator?: string 79 | sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"] 80 | targetLabel?: string 81 | }] 82 | oauth2?: { 83 | clientId: { 84 | configMap?: { 85 | key: string 86 | name?: string 87 | optional?: bool 88 | } 89 | secret?: { 90 | key: string 91 | name?: string 92 | optional?: bool 93 | } 94 | } 95 | clientSecret: { 96 | key: string 97 | name?: string 98 | optional?: bool 99 | } 100 | endpointParams?: { 101 | [string]: string 102 | } 103 | scopes?: [...string] 104 | tokenUrl: strings.MinRunes(1) 105 | } 106 | params?: { 107 | [string]: [...string] 108 | } 109 | path?: string 110 | port?: string 111 | proxyUrl?: string 112 | relabelings?: [...{ 113 | action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace" 114 | modulus?: int 115 | regex?: string 116 | replacement?: string 117 | separator?: string 118 | sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"] 119 | targetLabel?: string 120 | }] 121 | scheme?: "http" | "https" 122 | scrapeTimeout?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 123 | targetPort?: (int | string) & { 124 | string 125 | } 126 | tlsConfig?: { 127 | ca?: { 128 | configMap?: { 129 | key: string 130 | name?: string 131 | optional?: bool 132 | } 133 | secret?: { 134 | key: string 135 | name?: string 136 | optional?: bool 137 | } 138 | } 139 | cert?: { 140 | configMap?: { 141 | key: string 142 | name?: string 143 | optional?: bool 144 | } 145 | secret?: { 146 | key: string 147 | name?: string 148 | optional?: bool 149 | } 150 | } 151 | insecureSkipVerify?: bool 152 | keySecret?: { 153 | key: string 154 | name?: string 155 | optional?: bool 156 | } 157 | serverName?: string 158 | } 159 | }] 160 | podTargetLabels?: [...string] 161 | sampleLimit?: int 162 | selector: { 163 | matchExpressions?: [...{ 164 | key: string 165 | operator: string 166 | values?: [...string] 167 | }] 168 | matchLabels?: { 169 | [string]: string 170 | } 171 | } 172 | targetLimit?: int 173 | } 174 | -------------------------------------------------------------------------------- /cue.mod/gen/monitoring.coreos.com/servicemonitor/v1/types_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by timoni. DO NOT EDIT. 2 | 3 | //timoni:generate timoni vendor crd -f https://github.com/prometheus-operator/prometheus-operator/releases/download/v0.68.0/stripped-down-crds.yaml 4 | 5 | package v1 6 | 7 | import "strings" 8 | 9 | #ServiceMonitor: { 10 | apiVersion: "monitoring.coreos.com/v1" 11 | kind: "ServiceMonitor" 12 | metadata!: { 13 | name!: strings.MaxRunes(253) & strings.MinRunes(1) & { 14 | string 15 | } 16 | namespace!: strings.MaxRunes(63) & strings.MinRunes(1) & { 17 | string 18 | } 19 | labels?: { 20 | [string]: string 21 | } 22 | annotations?: { 23 | [string]: string 24 | } 25 | } 26 | spec!: #ServiceMonitorSpec 27 | } 28 | #ServiceMonitorSpec: { 29 | attachMetadata?: { 30 | node?: bool 31 | } 32 | endpoints: [...{ 33 | authorization?: { 34 | credentials?: { 35 | key: string 36 | name?: string 37 | optional?: bool 38 | } 39 | type?: string 40 | } 41 | basicAuth?: { 42 | password?: { 43 | key: string 44 | name?: string 45 | optional?: bool 46 | } 47 | username?: { 48 | key: string 49 | name?: string 50 | optional?: bool 51 | } 52 | } 53 | bearerTokenFile?: string 54 | bearerTokenSecret?: { 55 | key: string 56 | name?: string 57 | optional?: bool 58 | } 59 | enableHttp2?: bool 60 | filterRunning?: bool 61 | followRedirects?: bool 62 | honorLabels?: bool 63 | honorTimestamps?: bool 64 | interval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 65 | metricRelabelings?: [...{ 66 | action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace" 67 | modulus?: int 68 | regex?: string 69 | replacement?: string 70 | separator?: string 71 | sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"] 72 | targetLabel?: string 73 | }] 74 | oauth2?: { 75 | clientId: { 76 | configMap?: { 77 | key: string 78 | name?: string 79 | optional?: bool 80 | } 81 | secret?: { 82 | key: string 83 | name?: string 84 | optional?: bool 85 | } 86 | } 87 | clientSecret: { 88 | key: string 89 | name?: string 90 | optional?: bool 91 | } 92 | endpointParams?: { 93 | [string]: string 94 | } 95 | scopes?: [...string] 96 | tokenUrl: strings.MinRunes(1) 97 | } 98 | params?: { 99 | [string]: [...string] 100 | } 101 | path?: string 102 | port?: string 103 | proxyUrl?: string 104 | relabelings?: [...{ 105 | action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace" 106 | modulus?: int 107 | regex?: string 108 | replacement?: string 109 | separator?: string 110 | sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"] 111 | targetLabel?: string 112 | }] 113 | scheme?: "http" | "https" 114 | scrapeTimeout?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 115 | targetPort?: (int | string) & { 116 | string 117 | } 118 | tlsConfig?: { 119 | ca?: { 120 | configMap?: { 121 | key: string 122 | name?: string 123 | optional?: bool 124 | } 125 | secret?: { 126 | key: string 127 | name?: string 128 | optional?: bool 129 | } 130 | } 131 | caFile?: string 132 | cert?: { 133 | configMap?: { 134 | key: string 135 | name?: string 136 | optional?: bool 137 | } 138 | secret?: { 139 | key: string 140 | name?: string 141 | optional?: bool 142 | } 143 | } 144 | certFile?: string 145 | insecureSkipVerify?: bool 146 | keyFile?: string 147 | keySecret?: { 148 | key: string 149 | name?: string 150 | optional?: bool 151 | } 152 | serverName?: string 153 | } 154 | }] 155 | jobLabel?: string 156 | keepDroppedTargets?: int 157 | labelLimit?: int 158 | labelNameLengthLimit?: int 159 | labelValueLengthLimit?: int 160 | namespaceSelector?: { 161 | any?: bool 162 | matchNames?: [...string] 163 | } 164 | podTargetLabels?: [...string] 165 | sampleLimit?: int 166 | selector: { 167 | matchExpressions?: [...{ 168 | key: string 169 | operator: string 170 | values?: [...string] 171 | }] 172 | matchLabels?: { 173 | [string]: string 174 | } 175 | } 176 | targetLabels?: [...string] 177 | targetLimit?: int 178 | } 179 | -------------------------------------------------------------------------------- /templates/deploymentSpecWebhook.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | appsv1 "k8s.io/api/apps/v1" 5 | corev1 "k8s.io/api/core/v1" 6 | timoniv1 "timoni.sh/core/v1alpha1" 7 | 8 | cfg "timoni.sh/cert-manager/templates/config" 9 | ) 10 | 11 | #WebhookDeploymentSpec: appsv1.#DeploymentSpec & { 12 | #main_config: cfg.#Config 13 | #deployment_meta: timoniv1.#MetaComponent 14 | 15 | selector: matchLabels: #deployment_meta.#LabelSelector 16 | 17 | template: corev1.#PodTemplateSpec & { 18 | spec: corev1.#PodSpec & { 19 | if #main_config.webhook.hostNetwork != false { 20 | hostNetwork: true 21 | dnsPolicy: "ClusterFirstWithHostNet" 22 | } 23 | 24 | containers: [...corev1.#Container] & [ 25 | { 26 | args: [ 27 | "--v=\(#main_config.logLevel)", 28 | 29 | if #main_config.webhook.config != _|_ { 30 | "--secure-port=\(#main_config.webhook.config.securePort)" 31 | }, 32 | 33 | if #main_config.webhook.config == _|_ { 34 | "--secure-port=\(#main_config.webhook.securePort)" 35 | }, 36 | 37 | if #main_config.webhook.config != _|_ { 38 | "--config=/var/cert-manager/config/config.yaml" 39 | }, 40 | 41 | if #main_config.webhook.featureGates != _|_ { 42 | "--feature-gates=\(#deployment_meta.webhook.featureGates)" 43 | }, 44 | 45 | if #main_config.webhook.config.tlsConfig == _|_ || (#main_config.webhook.config.tlsConfig.dynamic == _|_ && #main_config.webhook.config.tlsConfig.filesystem == _|_) { 46 | "--dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE)" 47 | }, 48 | 49 | if #main_config.webhook.config.tlsConfig == _|_ || (#main_config.webhook.config.tlsConfig.dynamic == _|_ && #main_config.webhook.config.tlsConfig.filesystem == _|_) { 50 | "--dynamic-serving-ca-secret-name=\(#deployment_meta.name)-ca" 51 | }, 52 | 53 | if #main_config.webhook.config.tlsConfig == _|_ || (#main_config.webhook.config.tlsConfig.dynamic == _|_ && #main_config.webhook.config.tlsConfig.filesystem == _|_) { 54 | "--dynamic-serving-dns-names=\(#deployment_meta.name)" 55 | }, 56 | 57 | if #main_config.webhook.config.tlsConfig == _|_ || (#main_config.webhook.config.tlsConfig.dynamic == _|_ && #main_config.webhook.config.tlsConfig.filesystem == _|_) { 58 | "--dynamic-serving-dns-names=\(#deployment_meta.name).$(POD_NAMESPACE)" 59 | }, 60 | 61 | if #main_config.webhook.config.tlsConfig == _|_ || (#main_config.webhook.config.tlsConfig.dynamic == _|_ && #main_config.webhook.config.tlsConfig.filesystem == _|_) { 62 | "--dynamic-serving-dns-names=\(#deployment_meta.name).$(POD_NAMESPACE).svc" 63 | }, 64 | 65 | if (#main_config.webhook.config.tlsConfig == _|_ || (#main_config.webhook.config.tlsConfig.dynamic == _|_ && #main_config.webhook.config.tlsConfig.filesystem == _|_)) && #main_config.webhook.url.host != _|_ { 66 | "--dynamic-serving-dns-names=\(#main_config.webhook.url.host)" 67 | }, 68 | 69 | if #main_config.webhook.extraArgs != _|_ { 70 | for a in #main_config.webhook.extraArgs {a} 71 | }, 72 | ] 73 | 74 | ports: [ 75 | { 76 | name: "https" 77 | protocol: "TCP" 78 | if #main_config.webhook.config != _|_ { 79 | containerPort: #main_config.webhook.config.securePort 80 | } 81 | if #main_config.webhook.config == _|_ { 82 | containerPort: #main_config.webhook.securePort 83 | } 84 | }, 85 | { 86 | name: "healthcheck" 87 | protocol: "TCP" 88 | containerPort: *6080 | #main_config.webhook.config.healthzPort 89 | }, 90 | ] 91 | 92 | livenessProbe: #main_config.webhook.livenessProbe & { 93 | httpGet: { 94 | port: "healthcheck" 95 | path: "/livez" 96 | scheme: "HTTP" 97 | } 98 | initialDelaySeconds: *60 | int 99 | periodSeconds: *10 | int 100 | timeoutSeconds: *1 | int 101 | successThreshold: *1 | int 102 | failureThreshold: *3 | int 103 | } 104 | 105 | readinessProbe: #main_config.webhook.readinessProbe & { 106 | httpGet: { 107 | port: "healthcheck" 108 | path: "/healthz" 109 | scheme: "HTTP" 110 | } 111 | initialDelaySeconds: *5 | int 112 | periodSeconds: *5 | int 113 | timeoutSeconds: *1 | int 114 | successThreshold: *1 | int 115 | failureThreshold: *3 | int 116 | } 117 | 118 | volumeMounts: [ 119 | for k, v in #main_config.webhook.volumeMounts {v}, 120 | if #main_config.webhook.config != _|_ { 121 | { 122 | name: "config" 123 | mountPath: "/var/cert-manager/config" 124 | } 125 | }, 126 | ] 127 | }, 128 | ] 129 | 130 | volumes: [ 131 | for k, v in #main_config.webhook.volumes {v}, 132 | if #main_config.webhook.config != _|_ { 133 | { 134 | name: "config" 135 | configMap: name: #deployment_meta.name 136 | } 137 | }, 138 | ] 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /cue.mod/gen/monitoring.coreos.com/probe/v1/types_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by timoni. DO NOT EDIT. 2 | 3 | //timoni:generate timoni vendor crd -f https://github.com/prometheus-operator/prometheus-operator/releases/download/v0.68.0/stripped-down-crds.yaml 4 | 5 | package v1 6 | 7 | import "strings" 8 | 9 | #Probe: { 10 | apiVersion: "monitoring.coreos.com/v1" 11 | kind: "Probe" 12 | metadata!: { 13 | name!: strings.MaxRunes(253) & strings.MinRunes(1) & { 14 | string 15 | } 16 | namespace!: strings.MaxRunes(63) & strings.MinRunes(1) & { 17 | string 18 | } 19 | labels?: { 20 | [string]: string 21 | } 22 | annotations?: { 23 | [string]: string 24 | } 25 | } 26 | spec!: #ProbeSpec 27 | } 28 | #ProbeSpec: { 29 | authorization?: { 30 | credentials?: { 31 | key: string 32 | name?: string 33 | optional?: bool 34 | } 35 | type?: string 36 | } 37 | basicAuth?: { 38 | password?: { 39 | key: string 40 | name?: string 41 | optional?: bool 42 | } 43 | username?: { 44 | key: string 45 | name?: string 46 | optional?: bool 47 | } 48 | } 49 | bearerTokenSecret?: { 50 | key: string 51 | name?: string 52 | optional?: bool 53 | } 54 | interval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 55 | jobName?: string 56 | keepDroppedTargets?: int 57 | labelLimit?: int 58 | labelNameLengthLimit?: int 59 | labelValueLengthLimit?: int 60 | metricRelabelings?: [...{ 61 | action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace" 62 | modulus?: int 63 | regex?: string 64 | replacement?: string 65 | separator?: string 66 | sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"] 67 | targetLabel?: string 68 | }] 69 | module?: string 70 | oauth2?: { 71 | clientId: { 72 | configMap?: { 73 | key: string 74 | name?: string 75 | optional?: bool 76 | } 77 | secret?: { 78 | key: string 79 | name?: string 80 | optional?: bool 81 | } 82 | } 83 | clientSecret: { 84 | key: string 85 | name?: string 86 | optional?: bool 87 | } 88 | endpointParams?: { 89 | [string]: string 90 | } 91 | scopes?: [...string] 92 | tokenUrl: strings.MinRunes(1) 93 | } 94 | prober?: { 95 | path?: string | *"/probe" 96 | proxyUrl?: string 97 | scheme?: "http" | "https" 98 | url: string 99 | } 100 | sampleLimit?: int 101 | scrapeTimeout?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 102 | targetLimit?: int 103 | targets?: { 104 | ingress?: { 105 | namespaceSelector?: { 106 | any?: bool 107 | matchNames?: [...string] 108 | } 109 | relabelingConfigs?: [...{ 110 | action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace" 111 | modulus?: int 112 | regex?: string 113 | replacement?: string 114 | separator?: string 115 | sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"] 116 | targetLabel?: string 117 | }] 118 | selector?: { 119 | matchExpressions?: [...{ 120 | key: string 121 | operator: string 122 | values?: [...string] 123 | }] 124 | matchLabels?: { 125 | [string]: string 126 | } 127 | } 128 | } 129 | staticConfig?: { 130 | labels?: { 131 | [string]: string 132 | } 133 | relabelingConfigs?: [...{ 134 | action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace" 135 | modulus?: int 136 | regex?: string 137 | replacement?: string 138 | separator?: string 139 | sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"] 140 | targetLabel?: string 141 | }] 142 | static?: [...string] 143 | } 144 | } 145 | tlsConfig?: { 146 | ca?: { 147 | configMap?: { 148 | key: string 149 | name?: string 150 | optional?: bool 151 | } 152 | secret?: { 153 | key: string 154 | name?: string 155 | optional?: bool 156 | } 157 | } 158 | cert?: { 159 | configMap?: { 160 | key: string 161 | name?: string 162 | optional?: bool 163 | } 164 | secret?: { 165 | key: string 166 | name?: string 167 | optional?: bool 168 | } 169 | } 170 | insecureSkipVerify?: bool 171 | keySecret?: { 172 | key: string 173 | name?: string 174 | optional?: bool 175 | } 176 | serverName?: string 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Cert-Manager Distribution 2 | 3 | .ONESHELL: 4 | .SHELLFLAGS += -e 5 | 6 | ORG:="nalum" 7 | REPO:="cert-manager-bundle" 8 | CERT_MANAGER_VERSION:=1.13.2 9 | MV:=1.13.2 10 | KV:=1.29.0 11 | NAME:="cert-manager" 12 | NAMESPACE:="cert-manager" 13 | 14 | .PHONY: help 15 | help: ## Display this help menu 16 | @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) 17 | 18 | .PHONY: tools 19 | tools: ## Install cue, kind, kubectl, Timoni and FLux CLIs 20 | brew bundle 21 | 22 | .PHONY: fmt 23 | fmt: ## Format all CUE definitions 24 | @cue fmt ./bundles/... 25 | @cue fmt ./... 26 | 27 | .PHONY: gen 28 | gen: ## Print the CUE generated objects 29 | @cue cmd -t name=$(NAME) -t namespace=$(NAMESPACE) -t mv=v$(MV) -t kv=$(KV) build 30 | 31 | .PHONY: vet-debug 32 | vet-debug: 33 | @timoni mod vet --debug --namespace $(NAMESPACE) --name $(NAME) 34 | 35 | .PHONY: vet 36 | vet: 37 | @timoni mod vet --namespace $(NAMESPACE) --name $(NAME) 38 | 39 | .PHONY: ls 40 | ls: ## List the CUE generated objects 41 | @cue cmd -t name=$(NAME) -t namespace=$(NAMESPACE) -t mv=v$(MV) -t kv=$(KV) ls 42 | 43 | .PHONY: gen-debug-files 44 | gen-debug-files: ## Generate resources and write to files 45 | @mkdir -p output 46 | @timoni -n $(NAMESPACE) build $(NAME) ./ -f ./debug_values.cue > all.yaml 47 | @yq --yaml-output '. | select(.kind == "ClusterRole")' all.yaml > output/ClusterRole.yaml 48 | @yq --yaml-output '. | select(.kind == "ClusterRoleBinding")' all.yaml > output/ClusterRoleBinding.yaml 49 | @yq --yaml-output '. | select(.kind == "ConfigMap")' all.yaml > output/ConfigMap.yaml 50 | @yq --yaml-output '. | select(.kind == "CustomResourceDefinition")' all.yaml > output/CustomResourceDefinition.yaml 51 | @yq --yaml-output '. | select(.kind == "Deployment")' all.yaml > output/Deployment.yaml 52 | @yq --yaml-output '. | select(.kind == "Job")' all.yaml > output/Job.yaml 53 | @yq --yaml-output '. | select(.kind == "MutatingWebhookConfiguration")' all.yaml > output/MutatingWebhookConfiguration.yaml 54 | @yq --yaml-output '. | select(.kind == "Namespace")' all.yaml > output/Namespace.yaml 55 | @yq --yaml-output '. | select(.kind == "NetworkPolicy")' all.yaml > output/NetworkPolicy.yaml 56 | @yq --yaml-output '. | select(.kind == "PodDisruptionBudget")' all.yaml > output/PodDisruptionBudget.yaml 57 | @yq --yaml-output '. | select(.kind == "PodMonitor")' all.yaml > output/PodMonitor.yaml 58 | @yq --yaml-output '. | select(.kind == "Role")' all.yaml > output/Role.yaml 59 | @yq --yaml-output '. | select(.kind == "RoleBinding")' all.yaml > output/RoleBinding.yaml 60 | @yq --yaml-output '. | select(.kind == "Service")' all.yaml > output/Service.yaml 61 | @yq --yaml-output '. | select(.kind == "ServiceAccount")' all.yaml > output/ServiceAccount.yaml 62 | @yq --yaml-output '. | select(.kind == "ServiceMonitor")' all.yaml > output/ServiceMonitor.yaml 63 | @yq --yaml-output '. | select(.kind == "ValidatingWebhookConfiguration")' all.yaml > output/ValidatingWebhookConfiguration.yaml 64 | @rm all.yaml 65 | 66 | .PHONY: gen-files 67 | gen-files: ## Generate resources and write to files 68 | @mkdir -p output 69 | @timoni -n $(NAMESPACE) build $(NAME) ./ > all.yaml 70 | @yq --yaml-output '. | select(.kind == "ClusterRole")' all.yaml > output/ClusterRole.yaml 71 | @yq --yaml-output '. | select(.kind == "ClusterRoleBinding")' all.yaml > output/ClusterRoleBinding.yaml 72 | @yq --yaml-output '. | select(.kind == "ConfigMap")' all.yaml > output/ConfigMap.yaml 73 | @yq --yaml-output '. | select(.kind == "CustomResourceDefinition")' all.yaml > output/CustomResourceDefinition.yaml 74 | @yq --yaml-output '. | select(.kind == "Deployment")' all.yaml > output/Deployment.yaml 75 | @yq --yaml-output '. | select(.kind == "Job")' all.yaml > output/Job.yaml 76 | @yq --yaml-output '. | select(.kind == "MutatingWebhookConfiguration")' all.yaml > output/MutatingWebhookConfiguration.yaml 77 | @yq --yaml-output '. | select(.kind == "Namespace")' all.yaml > output/Namespace.yaml 78 | @yq --yaml-output '. | select(.kind == "NetworkPolicy")' all.yaml > output/NetworkPolicy.yaml 79 | @yq --yaml-output '. | select(.kind == "PodDisruptionBudget")' all.yaml > output/PodDisruptionBudget.yaml 80 | @yq --yaml-output '. | select(.kind == "PodMonitor")' all.yaml > output/PodMonitor.yaml 81 | @yq --yaml-output '. | select(.kind == "Role")' all.yaml > output/Role.yaml 82 | @yq --yaml-output '. | select(.kind == "RoleBinding")' all.yaml > output/RoleBinding.yaml 83 | @yq --yaml-output '. | select(.kind == "Service")' all.yaml > output/Service.yaml 84 | @yq --yaml-output '. | select(.kind == "ServiceAccount")' all.yaml > output/ServiceAccount.yaml 85 | @yq --yaml-output '. | select(.kind == "ServiceMonitor")' all.yaml > output/ServiceMonitor.yaml 86 | @yq --yaml-output '. | select(.kind == "ValidatingWebhookConfiguration")' all.yaml > output/ValidatingWebhookConfiguration.yaml 87 | @rm all.yaml 88 | 89 | .PHONY: import-crds 90 | import-crds: ## Update Cert-Manager API CUE definitions 91 | @cd ./templates 92 | @curl -OLJ https://github.com/cert-manager/cert-manager/releases/download/v$(CERT_MANAGER_VERSION)/cert-manager.crds.yaml 93 | @yq --yaml-output 'del(.metadata.labels["app.kubernetes.io/name"], .metadata.labels["app.kubernetes.io/instance"], .metadata.labels["app.kubernetes.io/version"])' cert-manager.crds.yaml > crds.yaml 94 | @cue import -f -o crds.cue -l 'strings.ToLower(kind)' -l 'metadata.name' -p templates crds.yaml 95 | @rm *crds.yaml 96 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/events/v1/types_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/events/v1 4 | 5 | package v1 6 | 7 | import ( 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | corev1 "k8s.io/api/core/v1" 10 | ) 11 | 12 | // Event is a report of an event somewhere in the cluster. It generally denotes some state change in the system. 13 | // Events have a limited retention time and triggers and messages may evolve 14 | // with time. Event consumers should not rely on the timing of an event 15 | // with a given Reason reflecting a consistent underlying trigger, or the 16 | // continued existence of events with that Reason. Events should be 17 | // treated as informative, best-effort, supplemental data. 18 | #Event: { 19 | metav1.#TypeMeta 20 | 21 | // Standard object's metadata. 22 | // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata 23 | // +optional 24 | metadata?: metav1.#ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt) 25 | 26 | // eventTime is the time when this Event was first observed. It is required. 27 | eventTime: metav1.#MicroTime @go(EventTime) @protobuf(2,bytes,opt) 28 | 29 | // series is data about the Event series this event represents or nil if it's a singleton Event. 30 | // +optional 31 | series?: null | #EventSeries @go(Series,*EventSeries) @protobuf(3,bytes,opt) 32 | 33 | // reportingController is the name of the controller that emitted this Event, e.g. `kubernetes.io/kubelet`. 34 | // This field cannot be empty for new Events. 35 | reportingController?: string @go(ReportingController) @protobuf(4,bytes,opt) 36 | 37 | // reportingInstance is the ID of the controller instance, e.g. `kubelet-xyzf`. 38 | // This field cannot be empty for new Events and it can have at most 128 characters. 39 | reportingInstance?: string @go(ReportingInstance) @protobuf(5,bytes,opt) 40 | 41 | // action is what action was taken/failed regarding to the regarding object. It is machine-readable. 42 | // This field cannot be empty for new Events and it can have at most 128 characters. 43 | action?: string @go(Action) @protobuf(6,bytes) 44 | 45 | // reason is why the action was taken. It is human-readable. 46 | // This field cannot be empty for new Events and it can have at most 128 characters. 47 | reason?: string @go(Reason) @protobuf(7,bytes) 48 | 49 | // regarding contains the object this Event is about. In most cases it's an Object reporting controller 50 | // implements, e.g. ReplicaSetController implements ReplicaSets and this event is emitted because 51 | // it acts on some changes in a ReplicaSet object. 52 | // +optional 53 | regarding?: corev1.#ObjectReference @go(Regarding) @protobuf(8,bytes,opt) 54 | 55 | // related is the optional secondary object for more complex actions. E.g. when regarding object triggers 56 | // a creation or deletion of related object. 57 | // +optional 58 | related?: null | corev1.#ObjectReference @go(Related,*corev1.ObjectReference) @protobuf(9,bytes,opt) 59 | 60 | // note is a human-readable description of the status of this operation. 61 | // Maximal length of the note is 1kB, but libraries should be prepared to 62 | // handle values up to 64kB. 63 | // +optional 64 | note?: string @go(Note) @protobuf(10,bytes,opt) 65 | 66 | // type is the type of this event (Normal, Warning), new types could be added in the future. 67 | // It is machine-readable. 68 | // This field cannot be empty for new Events. 69 | type?: string @go(Type) @protobuf(11,bytes,opt) 70 | 71 | // deprecatedSource is the deprecated field assuring backward compatibility with core.v1 Event type. 72 | // +optional 73 | deprecatedSource?: corev1.#EventSource @go(DeprecatedSource) @protobuf(12,bytes,opt) 74 | 75 | // deprecatedFirstTimestamp is the deprecated field assuring backward compatibility with core.v1 Event type. 76 | // +optional 77 | deprecatedFirstTimestamp?: metav1.#Time @go(DeprecatedFirstTimestamp) @protobuf(13,bytes,opt) 78 | 79 | // deprecatedLastTimestamp is the deprecated field assuring backward compatibility with core.v1 Event type. 80 | // +optional 81 | deprecatedLastTimestamp?: metav1.#Time @go(DeprecatedLastTimestamp) @protobuf(14,bytes,opt) 82 | 83 | // deprecatedCount is the deprecated field assuring backward compatibility with core.v1 Event type. 84 | // +optional 85 | deprecatedCount?: int32 @go(DeprecatedCount) @protobuf(15,varint,opt) 86 | } 87 | 88 | // EventSeries contain information on series of events, i.e. thing that was/is happening 89 | // continuously for some time. How often to update the EventSeries is up to the event reporters. 90 | // The default event reporter in "k8s.io/client-go/tools/events/event_broadcaster.go" shows 91 | // how this struct is updated on heartbeats and can guide customized reporter implementations. 92 | #EventSeries: { 93 | // count is the number of occurrences in this series up to the last heartbeat time. 94 | count: int32 @go(Count) @protobuf(1,varint,opt) 95 | 96 | // lastObservedTime is the time when last Event from the series was seen before last heartbeat. 97 | lastObservedTime: metav1.#MicroTime @go(LastObservedTime) @protobuf(2,bytes,opt) 98 | } 99 | 100 | // EventList is a list of Event objects. 101 | #EventList: { 102 | metav1.#TypeMeta 103 | 104 | // Standard list metadata. 105 | // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata 106 | // +optional 107 | metadata?: metav1.#ListMeta @go(ListMeta) @protobuf(1,bytes,opt) 108 | 109 | // items is a list of schema objects. 110 | items: [...#Event] @go(Items,[]Event) @protobuf(2,bytes,rep) 111 | } 112 | -------------------------------------------------------------------------------- /templates/deploymentSpecController.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | appsv1 "k8s.io/api/apps/v1" 5 | corev1 "k8s.io/api/core/v1" 6 | timoniv1 "timoni.sh/core/v1alpha1" 7 | 8 | cfg "timoni.sh/cert-manager/templates/config" 9 | ) 10 | 11 | #ControllerDeploymentSpec: appsv1.#DeploymentSpec & { 12 | #main_config: cfg.#Config 13 | #deployment_meta: timoniv1.#MetaComponent 14 | #deployment_monitoring: cfg.#Monitoring 15 | 16 | selector: matchLabels: #deployment_meta.#LabelSelector 17 | 18 | template: corev1.#PodTemplateSpec & { 19 | if #deployment_monitoring.enabled && #deployment_monitoring.type == "Annotations" { 20 | metadata: annotations: "prometheus.io/path": "/metrics" 21 | metadata: annotations: "prometheus.io/scrape": "true" 22 | metadata: annotations: "prometheus.io/port": "9402" 23 | } 24 | 25 | spec: corev1.#PodSpec & { 26 | volumes: [ 27 | for k, v in #main_config.controller.volumes {v}, 28 | 29 | if #main_config.controller.config != _|_ { 30 | { 31 | name: "config" 32 | configMap: name: #deployment_meta.name 33 | } 34 | }, 35 | ] 36 | 37 | dnsPolicy: #main_config.controller.podDNSPolicy 38 | 39 | if #main_config.controller.podDNSConfig != _|_ { 40 | dnsConfig: #main_config.controller.podDNSConfig 41 | } 42 | 43 | containers: [...corev1.#Container] & [ 44 | { 45 | volumeMounts: [ 46 | for k, v in #main_config.controller.volumeMounts {v}, 47 | 48 | if #main_config.controller.config != _|_ { 49 | name: "config" 50 | mountPath: "/var/cert-manager/config" 51 | }, 52 | ] 53 | 54 | ports: [{ 55 | containerPort: 9402 56 | name: "http-metrics" 57 | protocol: "TCP" 58 | }, { 59 | containerPort: 9403 60 | name: "http-healthz" 61 | protocol: "TCP" 62 | }] 63 | 64 | args: [ 65 | "--v=\(#main_config.logLevel)", 66 | "--leader-election-namespace=\(#main_config.leaderElection.namespace)", 67 | "--acme-http01-solver-image=\(#main_config.acmeSolver.image.reference)", 68 | "--max-concurrent-challenges=\(#main_config.controller.maxConcurrentChallenges)", 69 | 70 | if #main_config.controller.config != _|_ { 71 | "--config=/var/cert-manager/config/config.yaml" 72 | }, 73 | 74 | if #main_config.controller.clusterResourceNamespace != _|_ { 75 | "--cluster-resource-namespace=\(#main_config.controller.clusterResourceNamespace)" 76 | }, 77 | 78 | if #main_config.controller.clusterResourceNamespace == _|_ { 79 | "--cluster-resource-namespace=$(POD_NAMESPACE)" 80 | }, 81 | 82 | if #main_config.leaderElection.leaseDuration != _|_ { 83 | "--leader-election-lease-duration=\(#main_config.leaderElection.leaseDuration)" 84 | }, 85 | 86 | if #main_config.leaderElection.renewDeadline != _|_ { 87 | "--leader-election-renew-deadline=\(#main_config.leaderElection.renewDeadline)" 88 | }, 89 | 90 | if #main_config.leaderElection.retryPeriod != _|_ { 91 | "--leader-election-retry-period=\(#main_config.leaderElection.retryPeriod)" 92 | }, 93 | 94 | if #main_config.controller.ingressShim != _|_ && #main_config.controller.ingressShim.defaultIssuerName != _|_ { 95 | "--default-issuer-name=\(#main_config.controller.ingressShim.defaultIssuerName)" 96 | }, 97 | 98 | if #main_config.controller.ingressShim != _|_ && #main_config.controller.ingressShim.defaultIssuerKind != _|_ { 99 | "--default-issuer-kind=\(#main_config.controller.ingressShim.defaultIssuerKind)" 100 | }, 101 | 102 | if #main_config.controller.ingressShim != _|_ && #main_config.controller.ingressShim.defaultIssuerGroup != _|_ { 103 | "--default-issuer-group=\(#main_config.controller.ingressShim.defaultIssuerGroup)" 104 | }, 105 | 106 | if #main_config.controller.featureGates != _|_ { 107 | "--feature-gates=\(#main_config.controller.featureGates)" 108 | }, 109 | 110 | if #main_config.controller.enableCertificateOwnerRef { 111 | "--enable-certificate-owner-ref=true" 112 | }, 113 | 114 | if #main_config.controller.dns01RecursiveNameserversOnly { 115 | "--dns01-recursive-nameservers-only=true" 116 | }, 117 | 118 | if #main_config.controller.dns01RecursiveNameservers != _|_ { 119 | "--dns01-recursive-nameservers=\(#main_config.controller.dns01RecursiveNameservers)" 120 | }, 121 | 122 | if #main_config.controller.extraArgs != _|_ { 123 | for a in #main_config.controller.extraArgs {a} 124 | }, 125 | ] 126 | 127 | if #main_config.controller.proxy != _|_ { 128 | env: [ 129 | if #main_config.controller.proxy.httpProxy != _|_ { 130 | { 131 | name: "HTTP_PROXY" 132 | value: #main_config.controller.proxy.httpProxy 133 | } 134 | }, 135 | if #main_config.controller.proxy.httpsProxy != _|_ { 136 | { 137 | name: "HTTPS_PROXY" 138 | value: #main_config.controller.proxy.httpsProxy 139 | } 140 | }, 141 | if #main_config.controller.proxy.noProxy != _|_ { 142 | { 143 | name: "NO_PROXY" 144 | value: #main_config.controller.proxy.noProxy 145 | } 146 | }, 147 | ] 148 | } 149 | 150 | livenessProbe: #main_config.controller.livenessProbe & { 151 | httpGet: { 152 | port: "http-healthz" 153 | path: "/livez" 154 | scheme: "HTTP" 155 | } 156 | initialDelaySeconds: *10 | int 157 | periodSeconds: *10 | int 158 | timeoutSeconds: *15 | int 159 | successThreshold: *1 | int 160 | failureThreshold: *8 | int 161 | } 162 | }, 163 | ] 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /templates/config/config.cue: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | corev1 "k8s.io/api/core/v1" 5 | timoniv1 "timoni.sh/core/v1alpha1" 6 | ) 7 | 8 | // Config defines the schema and defaults for the Instance values. 9 | #Config: { 10 | // The kubeVersion is a required field, set at apply-time 11 | // via timoni.cue by querying the user's Kubernetes API. 12 | // +nodoc 13 | kubeVersion!: string 14 | // Using the kubeVersion you can enforce a minimum Kubernetes minor version. 15 | // By default, the minimum Kubernetes version is set to 1.20. 16 | // +nodoc 17 | clusterVersion: timoniv1.#SemVer & {#Version: kubeVersion, #Minimum: "1.27.0"} 18 | 19 | // The moduleVersion is set from the user-supplied module version. 20 | // This field is used for the `app.kubernetes.io/version` label. 21 | // +nodoc 22 | moduleVersion!: string 23 | 24 | // Metadata (common to all resources) 25 | metadata: timoniv1.#Metadata & {#Version: moduleVersion} 26 | // +nodoc 27 | metadata: labels: (timoniv1.#StdLabelPartOf): "cert-manager" 28 | 29 | // Reference to one or more secrets to be used when pulling images 30 | // ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ 31 | imagePullSecrets?: [...corev1.#LocalObjectReference] 32 | 33 | // Optional priority class to be used for the cert-manager pods 34 | priorityClassName?: string 35 | 36 | // Logging verbosity 37 | logLevel: *2 | int & >=0 & <=6 38 | 39 | // Setup the Cluster RBAC roles and bindings 40 | rbac: { 41 | // Create the roles and bindings for cert-manager 42 | enabled: *true | false 43 | // Aggregate ClusterRoles to Kubernetes default user-facing roles. Ref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles 44 | aggregateClusterRoles: *true | false 45 | } 46 | 47 | podSecurityAdmission: { 48 | // Set the PodSecurity admission controller mode for the namespace 49 | mode: "audit" | "warn" | *"enforce" 50 | // Set the PodSecurity admission controller level for the namespace 51 | level: "privileged" | "baseline" | *"restricted" 52 | } 53 | 54 | highAvailability: { 55 | // Enable high availability features 56 | enabled: *false | true 57 | } 58 | 59 | leaderElection: { 60 | // Override the namespace used for the leader election lease 61 | namespace: *"kube-system" | string 62 | // The duration that non-leader candidates will wait after observing a 63 | // leadership renewal until attempting to acquire leadership of a led but 64 | // unrenewed leader slot. This is effectively the maximum duration that a 65 | // leader can be stopped before it is replaced by another candidate. 66 | leaseDuration?: #Duration 67 | // The interval between attempts by the acting master to renew a leadership 68 | // slot before it stops leading. This must be less than or equal to the 69 | // lease duration. 70 | renewDeadline?: #Duration 71 | // The duration the clients should wait between attempting acquisition and 72 | // renewal of a leadership. 73 | retryPeriod?: #Duration 74 | } 75 | 76 | controller: #Controller & { 77 | monitoring: #Monitoring & { 78 | namespace: *metadata.namespace | string 79 | } 80 | 81 | if highAvailability.enabled { 82 | replicas: *2 | uint16 & >2 83 | } 84 | 85 | podDisruptionBudget: enabled: *highAvailability.enabled | bool 86 | } 87 | webhook: #Webhook & { 88 | if highAvailability.enabled { 89 | replicas: *3 | uint16 & >3 90 | } 91 | 92 | podDisruptionBudget: enabled: *highAvailability.enabled | bool 93 | } 94 | caInjector: #CAInjector & { 95 | if highAvailability.enabled { 96 | replicas: *2 | uint16 & >2 97 | } 98 | 99 | podDisruptionBudget: enabled: *highAvailability.enabled | bool 100 | } 101 | 102 | acmeSolver: #ACMESolver 103 | 104 | test: { 105 | // Enable startupAPICheck to verify the cert-manager API is available 106 | enabled: *true | false 107 | startupAPICheck: #StartupAPICheck 108 | } 109 | } 110 | 111 | #Duration: string & =~"^[+-]?((\\d+h)?(\\d+m)?(\\d+s)?(\\d+ms)?(\\d+(us|µs))?(\\d+ns)?)$" 112 | #Percent: string & =~"^(100|[1-9][0-9]?)%$" 113 | #PdbValue: (int & >=0) | #Percent 114 | 115 | #Monitoring: { 116 | // Enable Prometheus monitoring for the cert-manager controller to use with the Prometheus Operator. 117 | enabled: *false | true 118 | // The namespace to create the Monitor in 119 | namespace: string 120 | // The type of monitoring to enable, can be one of "ServiceMonitor", "PodMonitor" or "Annotations" 121 | // If ServiceMonitor is used a Service will also be created 122 | type: "ServiceMonitor" | "PodMonitor" | *"Annotations" 123 | // Specifies the `prometheus` label on the created PodMonitor/ServiceMonitor, this is 124 | // used when different Prometheus instances have label selectors matching 125 | // different PodMonitor/ServiceMonitor. 126 | prometheusInstance: *"default" | string 127 | // The target port to set on the Monitor, should match the port that 128 | // cert-manager controller is listening on for metrics 129 | targetPort: *"http-metrics" | int | string 130 | // The path to scrape for metrics 131 | path: *"/metrics" | string 132 | // The interval to scrape metrics 133 | interval: *"60s" | #Duration 134 | // The timeout before a metrics scrape fails 135 | scrapeTimeout: *"30s" | #Duration 136 | // Additional labels to add to the PodMonitor 137 | labels?: timoniv1.#Labels 138 | // Additional annotations to add to the PodMonitor 139 | annotations?: timoniv1.#Annotations 140 | // Keep labels from scraped data, overriding server-side labels. 141 | honorLabels: *false | true 142 | // EndpointAdditionalProperties allows setting additional properties on the 143 | // endpoint such as relabelings, metricRelabelings etc. 144 | // 145 | // For example: 146 | // endpointAdditionalProperties: 147 | // relabelings: 148 | // - action: replace 149 | // sourceLabels: 150 | // - __meta_kubernetes_pod_node_name 151 | // targetLabel: instance 152 | endpointAdditionalProperties?: {[string]: string} 153 | } 154 | 155 | #Proxy: { 156 | // What domains should be proxied through the http proxy 157 | httpProxy!: string 158 | // What domains should be proxied through the https proxy 159 | httpsProxy!: string 160 | // What domains should not be proxied 161 | noProxy!: string 162 | } 163 | 164 | #SecurityContext: { 165 | runAsNonRoot: *true | false 166 | seccompProfile: type: *"RuntimeDefault" | string 167 | } 168 | 169 | #ContainerSecurityContext: corev1.#SecurityContext & { 170 | allowPrivilegeEscalation: *false | true 171 | readOnlyRootFilesystem: *true | false 172 | runAsNonRoot: *true | false 173 | capabilities: corev1.#Capabilities & { 174 | drop: *["ALL"] | null | [...string] 175 | } 176 | } 177 | 178 | #OneOfPDB: *{minAvailable?: #PdbValue} | {maxUnavailable?: #PdbValue} 179 | 180 | #PodDisruptionBudgetData: { 181 | enabled: bool 182 | #OneOfPDB 183 | } 184 | -------------------------------------------------------------------------------- /templates/config/components.cue: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | corev1 "k8s.io/api/core/v1" 5 | networkingv1 "k8s.io/api/networking/v1" 6 | timoniv1 "timoni.sh/core/v1alpha1" 7 | ) 8 | 9 | #Controller: { 10 | #Component 11 | 12 | // Override the namespace used to store DNS provider credentials etc. for ClusterIssuer 13 | // resources. By default, the same namespace as cert-manager is deployed within is 14 | // used. This namespace will not be automatically created by the Helm chart. 15 | clusterResourceNamespace?: string 16 | // Comma separated string with host and port of the recursive nameservers cert-manager should query 17 | dns01RecursiveNameservers?: string 18 | // Forces cert-manager to only use the recursive nameservers for verification. 19 | // Enabling this option could cause the DNS01 self check to take longer due to caching performed by the recursive nameservers 20 | dns01RecursiveNameserversOnly: *false | true 21 | // When this flag is enabled, secrets will be automatically removed when the certificate resource is deleted 22 | enableCertificateOwnerRef: *false | true 23 | // Comma separated list of feature gates that should be enabled on the controller pod. 24 | featureGates?: string 25 | // The maximum number of challenges that can be scheduled as 'processing' at once 26 | maxConcurrentChallenges: *60 | int 27 | // Optional DNS settings, useful if you have a public and private DNS zone for 28 | // the same domain on Route 53. What follows is an example of ensuring 29 | // cert-manager can access an ingress or DNS TXT records at all times. 30 | // NOTE: This requires Kubernetes 1.10 or `CustomPodDNS` feature gate enabled for 31 | // the cluster to work. 32 | podDNSConfig?: corev1.#PodDNSConfig 33 | podDNSPolicy: *"ClusterFirst" | "Default" | "ClusterFirstWithHostNet" | "None" 34 | monitoring: #Monitoring 35 | 36 | // Used to configure options for the controller pod. 37 | // This allows setting options that'd usually be provided via flags. 38 | // An APIVersion and Kind must be specified in your values.yaml file. 39 | // Flags will override options that are set here. 40 | config?: {// TODO: Grab this from the Cert Manager repo instead of defining here 41 | apiVersion: *"controller.config.cert-manager.io/v1alpha1" | string 42 | kind: *"ControllerConfiguration" | string 43 | logging: { 44 | verbosity: *2 | int & >=0 & <=6 45 | format: *"text" | string 46 | } 47 | leaderElectionConfig: namespace: *"kube-system" | string 48 | kubernetesAPIQPS: *9000 | int 49 | kubernetesAPIBurst: *9000 | int 50 | numberOfConcurrentWorkers: *200 | int 51 | featureGates?: { 52 | AdditionalCertificateOutputFormats: *true | false 53 | ExperimentalCertificateSigningRequestControllers: *true | false 54 | ExperimentalGatewayAPISupport: *true | false 55 | ServerSideApply: *true | false 56 | LiteralCertificateSubject: *true | false 57 | UseCertificateRequestBasicConstraints: *true | false 58 | } 59 | } 60 | 61 | ingressShim?: { 62 | // is the default issuer to use when an Ingress does not specify one 63 | defaultIssuerName?: string 64 | // is the default issuer kind to use when an Ingress does not specify one 65 | defaultIssuerKind?: *"ClusterIssuer" | "Issuer" 66 | // is the default issuer group to use when an Ingress does not specify one 67 | defaultIssuerGroup?: string 68 | } 69 | } 70 | 71 | #Webhook: { 72 | #Component 73 | 74 | // is a comma separated list of feature gates to enable. 75 | featureGates?: string 76 | // enalbes host networking for the webhook pod. 77 | hostNetwork: *false | true 78 | // is the IP address to bind to when running the webhook pod. 79 | loadBalancerIP?: string 80 | // is a map of annotations to add to the mutating webhook configuration. 81 | mutatingWebhookConfigurationAnnotations?: timoniv1.#Annotations 82 | // set the port that the webhook should listen on for requests. 83 | securePort: *10250 | int 84 | // number of seconds to wait before timing out a request to the webhook. 85 | timeoutSeconds: *10 | int 86 | // is a map of annotations to add to the validating webhook configuration. 87 | validatingWebhookConfigurationAnnotations?: timoniv1.#Annotations 88 | // are the arguments to pass to the webhook pod. 89 | args: [...string] 90 | 91 | // is a map of network policy rules to apply to the webhook pod. 92 | networkPolicy: networkingv1.#NetworkPolicySpec | *{ 93 | ingress: [{from: [{ipBlock: cidr: "0.0.0.0/0"}]}] 94 | egress: [ 95 | { 96 | ports: [ 97 | {port: 80, protocol: "TCP"}, 98 | {port: 443, protocol: "TCP"}, 99 | {port: 53, protocol: "TCP"}, 100 | {port: 53, protocol: "UDP"}, 101 | {port: 6443, protocol: "TCP"}, 102 | ] 103 | to: [{ipBlock: cidr: "0.0.0.0/0"}] 104 | }, 105 | ] 106 | } 107 | 108 | // Used to configure options for the webhook pod. 109 | // This allows setting options that'd usually be provided via flags. 110 | // An APIVersion and Kind must be specified in your values.yaml file. 111 | // Flags will override options that are set here. 112 | config?: { 113 | apiVersion: *"webhook.config.cert-manager.io/v1alpha1" | string 114 | kind: *"WebhookConfiguration" | string 115 | // The port that the webhook should listen on for requests. 116 | // In GKE private clusters, by default kubernetes apiservers are allowed to 117 | // talk to the cluster nodes only on 443 and 10250. so configuring 118 | // securePort: 10250, will work out of the box without needing to add firewall 119 | // rules or requiring NET_BIND_SERVICE capabilities to bind port numbers <1000. 120 | // This should be uncommented and set as a default by the chart once we graduate 121 | // the apiVersion of WebhookConfiguration past v1alpha1. 122 | securePort: *10250 | int 123 | } 124 | 125 | url: { 126 | // Overrides the mutating webhook and validating webhook so they reach the webhook 127 | // service using the `host` field instead of a service. 128 | host?: string 129 | } 130 | } 131 | 132 | #CAInjector: { 133 | #Component 134 | 135 | // configures the CAInjector with a custom configmap. 136 | config?: {[string]: string} 137 | } 138 | 139 | #StartupAPICheck: { 140 | #Component 141 | 142 | // Additional command line flags to pass to startupapicheck binary. 143 | // To see all available flags run docker run quay.io/jetstack/cert-manager-ctl: --help 144 | // 145 | // We enable verbose logging by default so that if startupapicheck fails, users 146 | // can know what exactly caused the failure. Verbose logs include details of 147 | // the webhook URL, IP address and TCP connect errors for example. 148 | extraArgs: [...string] | *[ 149 | "-v", 150 | ] 151 | podDisruptionBudget: enabled: false 152 | // is the number of retries before considering a Job as failed. 153 | backoffLimit: *4 | int 154 | // is a map of annotations to add to the job. 155 | jobAnnotations?: timoniv1.#Annotations 156 | // Timeout for 'kubectl check api' command 157 | timeout: *"1m" | #Duration 158 | } 159 | 160 | #ACMESolver: { 161 | image!: timoniv1.#Image 162 | } 163 | -------------------------------------------------------------------------------- /templates/instance.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | cfg "timoni.sh/cert-manager/templates/config" 5 | ) 6 | 7 | // Instance takes the config values and outputs the Kubernetes objects. 8 | #Instance: { 9 | config: cfg.#Config 10 | 11 | objects: { 12 | for name, crd in customresourcedefinition { 13 | "\(name)": crd 14 | "\(name)": metadata: labels: config.metadata.labels 15 | if config.metadata.annotations != _|_ { 16 | "\(name)": metadata: annotations: config.metadata.annotations 17 | } 18 | } 19 | } 20 | 21 | objects: { 22 | namespace: #Namespace & {#config: config} 23 | controllerDeployment: #ControllerDeployment & {#config: config} 24 | webhookDeployment: #WebhookDeployment & {#config: config} 25 | webhookMutatingWebhook: #MutatingWebhook & {#config: config} 26 | webhookValidatingWebhook: #ValidatingWebhook & {#config: config} 27 | webhookService: #ServiceWebhook & {#config: config} 28 | } 29 | 30 | if config.caInjector != _|_ { 31 | if config.caInjector.podDisruptionBudget.enabled { 32 | objects: caInjectorPodDisruptionBudget: #PodDisruptionBudget & { 33 | #config: config 34 | #component: "caInjector" 35 | } 36 | } 37 | 38 | if config.rbac.enabled { 39 | objects: { 40 | caInjectorClusterRole: #CaInjectorClusterRole & { 41 | #config: config 42 | #component: "caInjector" 43 | } 44 | caInjectorClusterRoleBinding: #ClusterRoleBinding & { 45 | #config: config 46 | #component: "caInjector" 47 | } 48 | caInjectorRole: #CaInjectorRole & {#config: config} 49 | caInjectorRoleBinding: #CaInjectorRoleBinding & {#config: config} 50 | } 51 | } 52 | 53 | objects: caInjectorServiceAccount: #ServiceAccount & { 54 | #config: config 55 | #component: "caInjector" 56 | } 57 | 58 | objects: caInjectorDeployment: #CaInjectorrDeployment & {#config: config} 59 | } 60 | 61 | if config.controller.config != _|_ { 62 | objects: controllerConfigMap: #ConfigMap & { 63 | #config: config 64 | #component: "controller" 65 | } 66 | } 67 | 68 | if config.webhook.networkPolicy != _|_ { 69 | objects: { 70 | webhookNetworkPolicyEgress: #NetworkPolicyAllowEgress & { 71 | #config: config 72 | #component: "webhook" 73 | } 74 | webhookNetworkPolicyIngress: 75 | #NetworkPolicyAllowIngress & { 76 | #config: config 77 | #component: "webhook" 78 | } 79 | } 80 | } 81 | 82 | if config.controller.podDisruptionBudget.enabled { 83 | objects: controllerPodDisruptionBudget: #PodDisruptionBudget & { 84 | #config: config 85 | #component: "controller" 86 | } 87 | } 88 | 89 | if config.rbac.enabled { 90 | objects: { 91 | controllerRole: #ControllerRole & {#config: config} 92 | controllerRoleBinding: #ControllerRoleBinding & {#config: config} 93 | 94 | if config.rbac.aggregateClusterRoles { 95 | controllerClusterViewClusterRole: #ControllerClusterViewClusterRole & { 96 | #config: config 97 | } 98 | } 99 | controllerViewClusterRole: #ControllerViewClusterRole & {#config: config} 100 | controllerEditClusterRole: #ControllerEditClusterRole & {#config: config} 101 | controllerIssuersClusterRole: #ControllerIssuersClusterRole & {#config: config} 102 | controllerClusterIssuersClusterRole: #ControllerClusterIssuersClusterRole & {#config: config} 103 | controllerCertificatesClusterRole: #ControllerCertificatesClusterRole & {#config: config} 104 | controllerOrdersClusterRole: #ControllerOrdersClusterRole & {#config: config} 105 | controllerChallengesClusterRole: #ControllerChallengesClusterRole & {#config: config} 106 | controllerIngressShimClusterRole: #ControllerIngressShimClusterRole & {#config: config} 107 | controllerApproveClusterRole: #ControllerApproveClusterRole & {#config: config} 108 | controllerCertificateSigningRequestsClusterRole: #ControllerCertificateSigningRequestsClusterRole & {#config: config} 109 | 110 | controllerIssuersClusterRoleBinding: #ClusterRoleBinding & { 111 | #config: config 112 | #component: "controller" 113 | #role: "issuers" 114 | } 115 | controllerClusterIssuersClusterRoleBinding: #ClusterRoleBinding & { 116 | #config: config 117 | #component: "controller" 118 | #role: "clusterissuers" 119 | } 120 | controllerCertificatesClusterRoleBinding: #ClusterRoleBinding & { 121 | #config: config 122 | #component: "controller" 123 | #role: "certificates" 124 | } 125 | controllerOrdersClusterRoleBinding: #ClusterRoleBinding & { 126 | #config: config 127 | #component: "controller" 128 | #role: "orders" 129 | } 130 | controllerChallengesClusterRoleBinding: #ClusterRoleBinding & { 131 | #config: config 132 | #component: "controller" 133 | #role: "challenges" 134 | } 135 | controllerIngressShimClusterRoleBinding: #ClusterRoleBinding & { 136 | #config: config 137 | #component: "controller" 138 | #role: "ingress-shim" 139 | } 140 | controllerApproveClusterRoleBinding: #ClusterRoleBinding & { 141 | #config: config 142 | #component: "controller" 143 | #role: "approve:cert-manager-io" 144 | } 145 | controllerCertificateSigningRequestsClusterRoleBinding: #ClusterRoleBinding & { 146 | #config: config 147 | #component: "controller" 148 | #role: "certificatesigningrequests" 149 | } 150 | 151 | webhookRole: #WebhookRole & {#config: config} 152 | webhookRoleBinding: #WebhookRoleBinding & {#config: config} 153 | webhookClusterRole: #ClusterWebhookClusterRole & {#config: config} 154 | webhookClusterRoleBinding: #ClusterRoleBinding & { 155 | #config: config 156 | #component: "webhook" 157 | #role: "subjectaccessreviews" 158 | } 159 | } 160 | } 161 | 162 | if config.controller.monitoring.enabled { 163 | if config.controller.monitoring.type == "ServiceMonitor" { 164 | objects: { 165 | service: #ServiceController & {#config: config} 166 | serviceMonitor: #ServiceMonitor & { 167 | #config: config 168 | #component: "controller" 169 | } 170 | } 171 | } 172 | 173 | if config.controller.monitoring.type == "PodMonitor" { 174 | objects: podMonitor: #PodMonitor & { 175 | #config: config 176 | #component: "controller" 177 | } 178 | } 179 | } 180 | 181 | objects: controllerServiceAccount: #ServiceAccount & { 182 | #config: config 183 | #component: "controller" 184 | } 185 | 186 | if config.webhook.config != _|_ { 187 | objects: webhookConfigMap: #ConfigMap & { 188 | #config: config 189 | #component: "webhook" 190 | } 191 | } 192 | 193 | if config.webhook.podDisruptionBudget.enabled { 194 | objects: webhookPodDisruptionBudget: #PodDisruptionBudget & { 195 | #config: config 196 | #component: "webhook" 197 | } 198 | } 199 | 200 | objects: webhookServiceAccount: #ServiceAccount & { 201 | #config: config 202 | #component: "webhook" 203 | } 204 | 205 | if config.test != _|_ { 206 | tests: startupAPICheckJob: #StartupAPICheckJob & {#config: config} 207 | 208 | if config.rbac.enabled { 209 | tests: { 210 | startupAPICheckRole: #StartupApiCheckRole & {#config: config} 211 | startupAPICheckRoleBinding: #StartupApiCheckRoleBinding & {#config: config} 212 | } 213 | } 214 | 215 | tests: startupAPICheckServiceAccount: #TestServiceAccount & { 216 | #config: config 217 | #component: "startupAPICheck" 218 | } 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/apimachinery/pkg/runtime/interfaces_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/apimachinery/pkg/runtime 4 | 5 | package runtime 6 | 7 | // APIVersionInternal may be used if you are registering a type that should not 8 | // be considered stable or serialized - it is a convention only and has no 9 | // special behavior in this package. 10 | #APIVersionInternal: "__internal" 11 | 12 | // GroupVersioner refines a set of possible conversion targets into a single option. 13 | #GroupVersioner: _ 14 | 15 | // Identifier represents an identifier. 16 | // Identitier of two different objects should be equal if and only if for every 17 | // input the output they produce is exactly the same. 18 | #Identifier: string // #enumIdentifier 19 | 20 | #enumIdentifier: 21 | _#noopEncoderIdentifier 22 | 23 | // Encoder writes objects to a serialized form 24 | #Encoder: _ 25 | 26 | // MemoryAllocator is responsible for allocating memory. 27 | // By encapsulating memory allocation into its own interface, we can reuse the memory 28 | // across many operations in places we know it can significantly improve the performance. 29 | #MemoryAllocator: _ 30 | 31 | // EncoderWithAllocator serializes objects in a way that allows callers to manage any additional memory allocations. 32 | #EncoderWithAllocator: _ 33 | 34 | // Decoder attempts to load an object from data. 35 | #Decoder: _ 36 | 37 | // Serializer is the core interface for transforming objects into a serialized format and back. 38 | // Implementations may choose to perform conversion of the object, but no assumptions should be made. 39 | #Serializer: _ 40 | 41 | // Codec is a Serializer that deals with the details of versioning objects. It offers the same 42 | // interface as Serializer, so this is a marker to consumers that care about the version of the objects 43 | // they receive. 44 | #Codec: #Serializer 45 | 46 | // ParameterCodec defines methods for serializing and deserializing API objects to url.Values and 47 | // performing any necessary conversion. Unlike the normal Codec, query parameters are not self describing 48 | // and the desired version must be specified. 49 | #ParameterCodec: _ 50 | 51 | // Framer is a factory for creating readers and writers that obey a particular framing pattern. 52 | #Framer: _ 53 | 54 | // SerializerInfo contains information about a specific serialization format 55 | #SerializerInfo: { 56 | // MediaType is the value that represents this serializer over the wire. 57 | MediaType: string 58 | 59 | // MediaTypeType is the first part of the MediaType ("application" in "application/json"). 60 | MediaTypeType: string 61 | 62 | // MediaTypeSubType is the second part of the MediaType ("json" in "application/json"). 63 | MediaTypeSubType: string 64 | 65 | // EncodesAsText indicates this serializer can be encoded to UTF-8 safely. 66 | EncodesAsText: bool 67 | 68 | // Serializer is the individual object serializer for this media type. 69 | Serializer: #Serializer 70 | 71 | // PrettySerializer, if set, can serialize this object in a form biased towards 72 | // readability. 73 | PrettySerializer: #Serializer 74 | 75 | // StrictSerializer, if set, deserializes this object strictly, 76 | // erring on unknown fields. 77 | StrictSerializer: #Serializer 78 | 79 | // StreamSerializer, if set, describes the streaming serialization format 80 | // for this media type. 81 | StreamSerializer?: null | #StreamSerializerInfo @go(,*StreamSerializerInfo) 82 | } 83 | 84 | // StreamSerializerInfo contains information about a specific stream serialization format 85 | #StreamSerializerInfo: { 86 | // EncodesAsText indicates this serializer can be encoded to UTF-8 safely. 87 | EncodesAsText: bool 88 | 89 | // Serializer is the top level object serializer for this type when streaming 90 | Serializer: #Serializer 91 | 92 | // Framer is the factory for retrieving streams that separate objects on the wire 93 | Framer: #Framer 94 | } 95 | 96 | // NegotiatedSerializer is an interface used for obtaining encoders, decoders, and serializers 97 | // for multiple supported media types. This would commonly be accepted by a server component 98 | // that performs HTTP content negotiation to accept multiple formats. 99 | #NegotiatedSerializer: _ 100 | 101 | // ClientNegotiator handles turning an HTTP content type into the appropriate encoder. 102 | // Use NewClientNegotiator or NewVersionedClientNegotiator to create this interface from 103 | // a NegotiatedSerializer. 104 | #ClientNegotiator: _ 105 | 106 | // StorageSerializer is an interface used for obtaining encoders, decoders, and serializers 107 | // that can read and write data at rest. This would commonly be used by client tools that must 108 | // read files, or server side storage interfaces that persist restful objects. 109 | #StorageSerializer: _ 110 | 111 | // NestedObjectEncoder is an optional interface that objects may implement to be given 112 | // an opportunity to encode any nested Objects / RawExtensions during serialization. 113 | #NestedObjectEncoder: _ 114 | 115 | // NestedObjectDecoder is an optional interface that objects may implement to be given 116 | // an opportunity to decode any nested Objects / RawExtensions during serialization. 117 | // It is possible for DecodeNestedObjects to return a non-nil error but for the decoding 118 | // to have succeeded in the case of strict decoding errors (e.g. unknown/duplicate fields). 119 | // As such it is important for callers of DecodeNestedObjects to check to confirm whether 120 | // an error is a runtime.StrictDecodingError before short circuiting. 121 | // Similarly, implementations of DecodeNestedObjects should ensure that a runtime.StrictDecodingError 122 | // is only returned when the rest of decoding has succeeded. 123 | #NestedObjectDecoder: _ 124 | 125 | #ObjectDefaulter: _ 126 | 127 | #ObjectVersioner: _ 128 | 129 | // ObjectConvertor converts an object to a different version. 130 | #ObjectConvertor: _ 131 | 132 | // ObjectTyper contains methods for extracting the APIVersion and Kind 133 | // of objects. 134 | #ObjectTyper: _ 135 | 136 | // ObjectCreater contains methods for instantiating an object by kind and version. 137 | #ObjectCreater: _ 138 | 139 | // EquivalentResourceMapper provides information about resources that address the same underlying data as a specified resource 140 | #EquivalentResourceMapper: _ 141 | 142 | // EquivalentResourceRegistry provides an EquivalentResourceMapper interface, 143 | // and allows registering known resource[/subresource] -> kind 144 | #EquivalentResourceRegistry: _ 145 | 146 | // ResourceVersioner provides methods for setting and retrieving 147 | // the resource version from an API object. 148 | #ResourceVersioner: _ 149 | 150 | // Namer provides methods for retrieving name and namespace of an API object. 151 | #Namer: _ 152 | 153 | // Object interface must be supported by all API types registered with Scheme. Since objects in a scheme are 154 | // expected to be serialized to the wire, the interface an Object must provide to the Scheme allows 155 | // serializers to set the kind, version, and group the object is represented as. An Object may choose 156 | // to return a no-op ObjectKindAccessor in cases where it is not expected to be serialized. 157 | #Object: _ 158 | 159 | // CacheableObject allows an object to cache its different serializations 160 | // to avoid performing the same serialization multiple times. 161 | #CacheableObject: _ 162 | 163 | // Unstructured objects store values as map[string]interface{}, with only values that can be serialized 164 | // to JSON allowed. 165 | #Unstructured: _ 166 | -------------------------------------------------------------------------------- /cue.mod/gen/monitoring.coreos.com/scrapeconfig/v1alpha1/types_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by timoni. DO NOT EDIT. 2 | 3 | //timoni:generate timoni vendor crd -f https://github.com/prometheus-operator/prometheus-operator/releases/download/v0.68.0/stripped-down-crds.yaml 4 | 5 | package v1alpha1 6 | 7 | import "strings" 8 | 9 | #ScrapeConfig: { 10 | apiVersion: "monitoring.coreos.com/v1alpha1" 11 | kind: "ScrapeConfig" 12 | metadata!: { 13 | name!: strings.MaxRunes(253) & strings.MinRunes(1) & { 14 | string 15 | } 16 | namespace!: strings.MaxRunes(63) & strings.MinRunes(1) & { 17 | string 18 | } 19 | labels?: { 20 | [string]: string 21 | } 22 | annotations?: { 23 | [string]: string 24 | } 25 | } 26 | spec!: #ScrapeConfigSpec 27 | } 28 | #ScrapeConfigSpec: { 29 | authorization?: { 30 | credentials?: { 31 | key: string 32 | name?: string 33 | optional?: bool 34 | } 35 | type?: string 36 | } 37 | basicAuth?: { 38 | password?: { 39 | key: string 40 | name?: string 41 | optional?: bool 42 | } 43 | username?: { 44 | key: string 45 | name?: string 46 | optional?: bool 47 | } 48 | } 49 | consulSDConfigs?: [...{ 50 | allow_stale?: bool 51 | authorization?: { 52 | credentials?: { 53 | key: string 54 | name?: string 55 | optional?: bool 56 | } 57 | type?: string 58 | } 59 | basicAuth?: { 60 | password?: { 61 | key: string 62 | name?: string 63 | optional?: bool 64 | } 65 | username?: { 66 | key: string 67 | name?: string 68 | optional?: bool 69 | } 70 | } 71 | datacenter?: string 72 | enable_http2?: bool 73 | follow_redirects?: bool 74 | namespace?: string 75 | no_proxy?: string 76 | node_meta?: { 77 | [string]: string 78 | } 79 | oauth2?: { 80 | clientId: { 81 | configMap?: { 82 | key: string 83 | name?: string 84 | optional?: bool 85 | } 86 | secret?: { 87 | key: string 88 | name?: string 89 | optional?: bool 90 | } 91 | } 92 | clientSecret: { 93 | key: string 94 | name?: string 95 | optional?: bool 96 | } 97 | endpointParams?: { 98 | [string]: string 99 | } 100 | scopes?: [...string] 101 | tokenUrl: strings.MinRunes(1) 102 | } 103 | partition?: string 104 | proxy_connect_header?: { 105 | [string]: { 106 | key: string 107 | name?: string 108 | optional?: bool 109 | } 110 | } 111 | proxy_from_environment?: bool 112 | proxy_url?: string 113 | refresh_interval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 114 | scheme?: "HTTP" | "HTTPS" 115 | server: strings.MinRunes(1) 116 | services?: [...string] 117 | tag_separator?: string 118 | tags?: [...string] 119 | tlsConfig?: { 120 | ca?: { 121 | configMap?: { 122 | key: string 123 | name?: string 124 | optional?: bool 125 | } 126 | secret?: { 127 | key: string 128 | name?: string 129 | optional?: bool 130 | } 131 | } 132 | cert?: { 133 | configMap?: { 134 | key: string 135 | name?: string 136 | optional?: bool 137 | } 138 | secret?: { 139 | key: string 140 | name?: string 141 | optional?: bool 142 | } 143 | } 144 | insecureSkipVerify?: bool 145 | keySecret?: { 146 | key: string 147 | name?: string 148 | optional?: bool 149 | } 150 | serverName?: string 151 | } 152 | tokenRef?: { 153 | key: string 154 | name?: string 155 | optional?: bool 156 | } 157 | }] 158 | dnsSDConfigs?: [...{ 159 | names: [...string] & [_, ...] 160 | port?: int 161 | refreshInterval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 162 | type?: "SRV" | "A" | "AAAA" | "MX" 163 | }] 164 | fileSDConfigs?: [...{ 165 | files: [...=~"^[^*]*(\\*[^/]*)?\\.(json|yml|yaml|JSON|YML|YAML)$"] & [_, ...] 166 | refreshInterval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 167 | }] 168 | honorLabels?: bool 169 | honorTimestamps?: bool 170 | httpSDConfigs?: [...{ 171 | authorization?: { 172 | credentials?: { 173 | key: string 174 | name?: string 175 | optional?: bool 176 | } 177 | type?: string 178 | } 179 | basicAuth?: { 180 | password?: { 181 | key: string 182 | name?: string 183 | optional?: bool 184 | } 185 | username?: { 186 | key: string 187 | name?: string 188 | optional?: bool 189 | } 190 | } 191 | refreshInterval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 192 | tlsConfig?: { 193 | ca?: { 194 | configMap?: { 195 | key: string 196 | name?: string 197 | optional?: bool 198 | } 199 | secret?: { 200 | key: string 201 | name?: string 202 | optional?: bool 203 | } 204 | } 205 | cert?: { 206 | configMap?: { 207 | key: string 208 | name?: string 209 | optional?: bool 210 | } 211 | secret?: { 212 | key: string 213 | name?: string 214 | optional?: bool 215 | } 216 | } 217 | insecureSkipVerify?: bool 218 | keySecret?: { 219 | key: string 220 | name?: string 221 | optional?: bool 222 | } 223 | serverName?: string 224 | } 225 | url: strings.MinRunes(1) & { 226 | =~"^http(s)?://.+$" 227 | } 228 | }] 229 | keepDroppedTargets?: int 230 | kubernetesSDConfigs?: [...{ 231 | role: "Node" 232 | }] 233 | labelLimit?: int 234 | labelNameLengthLimit?: int 235 | labelValueLengthLimit?: int 236 | metricRelabelings?: [...{ 237 | action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace" 238 | modulus?: int 239 | regex?: string 240 | replacement?: string 241 | separator?: string 242 | sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"] 243 | targetLabel?: string 244 | }] 245 | metricsPath?: string 246 | params?: { 247 | [string]: [...string] 248 | } 249 | relabelings?: [...{ 250 | action?: "replace" | "Replace" | "keep" | "Keep" | "drop" | "Drop" | "hashmod" | "HashMod" | "labelmap" | "LabelMap" | "labeldrop" | "LabelDrop" | "labelkeep" | "LabelKeep" | "lowercase" | "Lowercase" | "uppercase" | "Uppercase" | "keepequal" | "KeepEqual" | "dropequal" | "DropEqual" | *"replace" 251 | modulus?: int 252 | regex?: string 253 | replacement?: string 254 | separator?: string 255 | sourceLabels?: [...=~"^[a-zA-Z_][a-zA-Z0-9_]*$"] 256 | targetLabel?: string 257 | }] 258 | sampleLimit?: int 259 | scheme?: "HTTP" | "HTTPS" 260 | scrapeInterval?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 261 | scrapeTimeout?: =~"^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" 262 | staticConfigs?: [...{ 263 | labels?: { 264 | [string]: string 265 | } 266 | targets?: [...string] 267 | }] 268 | targetLimit?: int 269 | tlsConfig?: { 270 | ca?: { 271 | configMap?: { 272 | key: string 273 | name?: string 274 | optional?: bool 275 | } 276 | secret?: { 277 | key: string 278 | name?: string 279 | optional?: bool 280 | } 281 | } 282 | cert?: { 283 | configMap?: { 284 | key: string 285 | name?: string 286 | optional?: bool 287 | } 288 | secret?: { 289 | key: string 290 | name?: string 291 | optional?: bool 292 | } 293 | } 294 | insecureSkipVerify?: bool 295 | keySecret?: { 296 | key: string 297 | name?: string 298 | optional?: bool 299 | } 300 | serverName?: string 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/core/v1/annotation_key_constants_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/core/v1 4 | 5 | package v1 6 | 7 | // ImagePolicyFailedOpenKey is added to pods created by failing open when the image policy 8 | // webhook backend fails. 9 | #ImagePolicyFailedOpenKey: "alpha.image-policy.k8s.io/failed-open" 10 | 11 | // MirrorAnnotationKey represents the annotation key set by kubelets when creating mirror pods 12 | #MirrorPodAnnotationKey: "kubernetes.io/config.mirror" 13 | 14 | // TolerationsAnnotationKey represents the key of tolerations data (json serialized) 15 | // in the Annotations of a Pod. 16 | #TolerationsAnnotationKey: "scheduler.alpha.kubernetes.io/tolerations" 17 | 18 | // TaintsAnnotationKey represents the key of taints data (json serialized) 19 | // in the Annotations of a Node. 20 | #TaintsAnnotationKey: "scheduler.alpha.kubernetes.io/taints" 21 | 22 | // SeccompPodAnnotationKey represents the key of a seccomp profile applied 23 | // to all containers of a pod. 24 | // Deprecated: set a pod security context `seccompProfile` field. 25 | #SeccompPodAnnotationKey: "seccomp.security.alpha.kubernetes.io/pod" 26 | 27 | // SeccompContainerAnnotationKeyPrefix represents the key of a seccomp profile applied 28 | // to one container of a pod. 29 | // Deprecated: set a container security context `seccompProfile` field. 30 | #SeccompContainerAnnotationKeyPrefix: "container.seccomp.security.alpha.kubernetes.io/" 31 | 32 | // SeccompProfileRuntimeDefault represents the default seccomp profile used by container runtime. 33 | // Deprecated: set a pod or container security context `seccompProfile` of type "RuntimeDefault" instead. 34 | #SeccompProfileRuntimeDefault: "runtime/default" 35 | 36 | // SeccompProfileNameUnconfined is the unconfined seccomp profile. 37 | #SeccompProfileNameUnconfined: "unconfined" 38 | 39 | // SeccompLocalhostProfileNamePrefix is the prefix for specifying profiles loaded from the node's disk. 40 | #SeccompLocalhostProfileNamePrefix: "localhost/" 41 | 42 | // AppArmorBetaContainerAnnotationKeyPrefix is the prefix to an annotation key specifying a container's apparmor profile. 43 | #AppArmorBetaContainerAnnotationKeyPrefix: "container.apparmor.security.beta.kubernetes.io/" 44 | 45 | // AppArmorBetaDefaultProfileAnnotationKey is the annotation key specifying the default AppArmor profile. 46 | #AppArmorBetaDefaultProfileAnnotationKey: "apparmor.security.beta.kubernetes.io/defaultProfileName" 47 | 48 | // AppArmorBetaAllowedProfilesAnnotationKey is the annotation key specifying the allowed AppArmor profiles. 49 | #AppArmorBetaAllowedProfilesAnnotationKey: "apparmor.security.beta.kubernetes.io/allowedProfileNames" 50 | 51 | // AppArmorBetaProfileRuntimeDefault is the profile specifying the runtime default. 52 | #AppArmorBetaProfileRuntimeDefault: "runtime/default" 53 | 54 | // AppArmorBetaProfileNamePrefix is the prefix for specifying profiles loaded on the node. 55 | #AppArmorBetaProfileNamePrefix: "localhost/" 56 | 57 | // AppArmorBetaProfileNameUnconfined is the Unconfined AppArmor profile 58 | #AppArmorBetaProfileNameUnconfined: "unconfined" 59 | 60 | // DeprecatedSeccompProfileDockerDefault represents the default seccomp profile used by docker. 61 | // Deprecated: set a pod or container security context `seccompProfile` of type "RuntimeDefault" instead. 62 | #DeprecatedSeccompProfileDockerDefault: "docker/default" 63 | 64 | // PreferAvoidPodsAnnotationKey represents the key of preferAvoidPods data (json serialized) 65 | // in the Annotations of a Node. 66 | #PreferAvoidPodsAnnotationKey: "scheduler.alpha.kubernetes.io/preferAvoidPods" 67 | 68 | // ObjectTTLAnnotationKey represents a suggestion for kubelet for how long it can cache 69 | // an object (e.g. secret, config map) before fetching it again from apiserver. 70 | // This annotation can be attached to node. 71 | #ObjectTTLAnnotationKey: "node.alpha.kubernetes.io/ttl" 72 | 73 | // annotation key prefix used to identify non-convertible json paths. 74 | #NonConvertibleAnnotationPrefix: "non-convertible.kubernetes.io" 75 | _#kubectlPrefix: "kubectl.kubernetes.io/" 76 | 77 | // LastAppliedConfigAnnotation is the annotation used to store the previous 78 | // configuration of a resource for use in a three way diff by UpdateApplyAnnotation. 79 | #LastAppliedConfigAnnotation: "kubectl.kubernetes.io/last-applied-configuration" 80 | 81 | // AnnotationLoadBalancerSourceRangesKey is the key of the annotation on a service to set allowed ingress ranges on their LoadBalancers 82 | // 83 | // It should be a comma-separated list of CIDRs, e.g. `0.0.0.0/0` to 84 | // allow full access (the default) or `18.0.0.0/8,56.0.0.0/8` to allow 85 | // access only from the CIDRs currently allocated to MIT & the USPS. 86 | // 87 | // Not all cloud providers support this annotation, though AWS & GCE do. 88 | #AnnotationLoadBalancerSourceRangesKey: "service.beta.kubernetes.io/load-balancer-source-ranges" 89 | 90 | // EndpointsLastChangeTriggerTime is the annotation key, set for endpoints objects, that 91 | // represents the timestamp (stored as RFC 3339 date-time string, e.g. '2018-10-22T19:32:52.1Z') 92 | // of the last change, of some Pod or Service object, that triggered the endpoints object change. 93 | // In other words, if a Pod / Service changed at time T0, that change was observed by endpoints 94 | // controller at T1, and the Endpoints object was changed at T2, the 95 | // EndpointsLastChangeTriggerTime would be set to T0. 96 | // 97 | // The "endpoints change trigger" here means any Pod or Service change that resulted in the 98 | // Endpoints object change. 99 | // 100 | // Given the definition of the "endpoints change trigger", please note that this annotation will 101 | // be set ONLY for endpoints object changes triggered by either Pod or Service change. If the 102 | // Endpoints object changes due to other reasons, this annotation won't be set (or updated if it's 103 | // already set). 104 | // 105 | // This annotation will be used to compute the in-cluster network programming latency SLI, see 106 | // https://github.com/kubernetes/community/blob/master/sig-scalability/slos/network_programming_latency.md 107 | #EndpointsLastChangeTriggerTime: "endpoints.kubernetes.io/last-change-trigger-time" 108 | 109 | // EndpointsOverCapacity will be set on an Endpoints resource when it 110 | // exceeds the maximum capacity of 1000 addresses. Initially the Endpoints 111 | // controller will set this annotation with a value of "warning". In a 112 | // future release, the controller may set this annotation with a value of 113 | // "truncated" to indicate that any addresses exceeding the limit of 1000 114 | // have been truncated from the Endpoints resource. 115 | #EndpointsOverCapacity: "endpoints.kubernetes.io/over-capacity" 116 | 117 | // MigratedPluginsAnnotationKey is the annotation key, set for CSINode objects, that is a comma-separated 118 | // list of in-tree plugins that will be serviced by the CSI backend on the Node represented by CSINode. 119 | // This annotation is used by the Attach Detach Controller to determine whether to use the in-tree or 120 | // CSI Backend for a volume plugin on a specific node. 121 | #MigratedPluginsAnnotationKey: "storage.alpha.kubernetes.io/migrated-plugins" 122 | 123 | // PodDeletionCost can be used to set to an int32 that represent the cost of deleting 124 | // a pod compared to other pods belonging to the same ReplicaSet. Pods with lower 125 | // deletion cost are preferred to be deleted before pods with higher deletion cost. 126 | // Note that this is honored on a best-effort basis, and so it does not offer guarantees on 127 | // pod deletion order. 128 | // The implicit deletion cost for pods that don't set the annotation is 0, negative values are permitted. 129 | // 130 | // This annotation is beta-level and is only honored when PodDeletionCost feature is enabled. 131 | #PodDeletionCost: "controller.kubernetes.io/pod-deletion-cost" 132 | 133 | // DeprecatedAnnotationTopologyAwareHints can be used to enable or disable 134 | // Topology Aware Hints for a Service. This may be set to "Auto" or 135 | // "Disabled". Any other value is treated as "Disabled". This annotation has 136 | // been deprecated in favor of the "service.kubernetes.io/topology-mode" 137 | // annotation. 138 | #DeprecatedAnnotationTopologyAwareHints: "service.kubernetes.io/topology-aware-hints" 139 | 140 | // AnnotationTopologyMode can be used to enable or disable Topology Aware 141 | // Routing for a Service. Well known values are "Auto" and "Disabled". 142 | // Implementations may choose to develop new topology approaches, exposing 143 | // them with domain-prefixed values. For example, "example.com/lowest-rtt" 144 | // could be a valid implementation-specific value for this annotation. These 145 | // heuristics will often populate topology hints on EndpointSlices, but that 146 | // is not a requirement. 147 | #AnnotationTopologyMode: "service.kubernetes.io/topology-mode" 148 | -------------------------------------------------------------------------------- /cue.mod/gen/k8s.io/api/rbac/v1/types_go_gen.cue: -------------------------------------------------------------------------------- 1 | // Code generated by cue get go. DO NOT EDIT. 2 | 3 | //cue:generate cue get go k8s.io/api/rbac/v1 4 | 5 | package v1 6 | 7 | import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | 9 | #APIGroupAll: "*" 10 | #ResourceAll: "*" 11 | #VerbAll: "*" 12 | #NonResourceAll: "*" 13 | #GroupKind: "Group" 14 | #ServiceAccountKind: "ServiceAccount" 15 | #UserKind: "User" 16 | 17 | // AutoUpdateAnnotationKey is the name of an annotation which prevents reconciliation if set to "false" 18 | #AutoUpdateAnnotationKey: "rbac.authorization.kubernetes.io/autoupdate" 19 | 20 | // PolicyRule holds information that describes a policy rule, but does not contain information 21 | // about who the rule applies to or which namespace the rule applies to. 22 | #PolicyRule: { 23 | // Verbs is a list of Verbs that apply to ALL the ResourceKinds contained in this rule. '*' represents all verbs. 24 | verbs: [...string] @go(Verbs,[]string) @protobuf(1,bytes,rep) 25 | 26 | // APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of 27 | // the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups. 28 | // +optional 29 | apiGroups?: [...string] @go(APIGroups,[]string) @protobuf(2,bytes,rep) 30 | 31 | // Resources is a list of resources this rule applies to. '*' represents all resources. 32 | // +optional 33 | resources?: [...string] @go(Resources,[]string) @protobuf(3,bytes,rep) 34 | 35 | // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. 36 | // +optional 37 | resourceNames?: [...string] @go(ResourceNames,[]string) @protobuf(4,bytes,rep) 38 | 39 | // NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path 40 | // Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding. 41 | // Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both. 42 | // +optional 43 | nonResourceURLs?: [...string] @go(NonResourceURLs,[]string) @protobuf(5,bytes,rep) 44 | } 45 | 46 | // Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, 47 | // or a value for non-objects such as user and group names. 48 | // +structType=atomic 49 | #Subject: { 50 | // Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". 51 | // If the Authorizer does not recognized the kind value, the Authorizer should report an error. 52 | kind: string @go(Kind) @protobuf(1,bytes,opt) 53 | 54 | // APIGroup holds the API group of the referenced subject. 55 | // Defaults to "" for ServiceAccount subjects. 56 | // Defaults to "rbac.authorization.k8s.io" for User and Group subjects. 57 | // +optional 58 | apiGroup?: string @go(APIGroup) @protobuf(2,bytes,opt.name=apiGroup) 59 | 60 | // Name of the object being referenced. 61 | name: string @go(Name) @protobuf(3,bytes,opt) 62 | 63 | // Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty 64 | // the Authorizer should report an error. 65 | // +optional 66 | namespace?: string @go(Namespace) @protobuf(4,bytes,opt) 67 | } 68 | 69 | // RoleRef contains information that points to the role being used 70 | // +structType=atomic 71 | #RoleRef: { 72 | // APIGroup is the group for the resource being referenced 73 | apiGroup: string @go(APIGroup) @protobuf(1,bytes,opt) 74 | 75 | // Kind is the type of resource being referenced 76 | kind: string @go(Kind) @protobuf(2,bytes,opt) 77 | 78 | // Name is the name of resource being referenced 79 | name: string @go(Name) @protobuf(3,bytes,opt) 80 | } 81 | 82 | // Role is a namespaced, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding. 83 | #Role: { 84 | metav1.#TypeMeta 85 | 86 | // Standard object's metadata. 87 | // +optional 88 | metadata?: metav1.#ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt) 89 | 90 | // Rules holds all the PolicyRules for this Role 91 | // +optional 92 | rules?: [...#PolicyRule] @go(Rules,[]PolicyRule) @protobuf(2,bytes,rep) 93 | } 94 | 95 | // RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace. 96 | // It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given 97 | // namespace only have effect in that namespace. 98 | #RoleBinding: { 99 | metav1.#TypeMeta 100 | 101 | // Standard object's metadata. 102 | // +optional 103 | metadata?: metav1.#ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt) 104 | 105 | // Subjects holds references to the objects the role applies to. 106 | // +optional 107 | subjects?: [...#Subject] @go(Subjects,[]Subject) @protobuf(2,bytes,rep) 108 | 109 | // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. 110 | // If the RoleRef cannot be resolved, the Authorizer must return an error. 111 | // This field is immutable. 112 | roleRef: #RoleRef @go(RoleRef) @protobuf(3,bytes,opt) 113 | } 114 | 115 | // RoleBindingList is a collection of RoleBindings 116 | #RoleBindingList: { 117 | metav1.#TypeMeta 118 | 119 | // Standard object's metadata. 120 | // +optional 121 | metadata?: metav1.#ListMeta @go(ListMeta) @protobuf(1,bytes,opt) 122 | 123 | // Items is a list of RoleBindings 124 | items: [...#RoleBinding] @go(Items,[]RoleBinding) @protobuf(2,bytes,rep) 125 | } 126 | 127 | // RoleList is a collection of Roles 128 | #RoleList: { 129 | metav1.#TypeMeta 130 | 131 | // Standard object's metadata. 132 | // +optional 133 | metadata?: metav1.#ListMeta @go(ListMeta) @protobuf(1,bytes,opt) 134 | 135 | // Items is a list of Roles 136 | items: [...#Role] @go(Items,[]Role) @protobuf(2,bytes,rep) 137 | } 138 | 139 | // ClusterRole is a cluster level, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding or ClusterRoleBinding. 140 | #ClusterRole: { 141 | metav1.#TypeMeta 142 | 143 | // Standard object's metadata. 144 | // +optional 145 | metadata?: metav1.#ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt) 146 | 147 | // Rules holds all the PolicyRules for this ClusterRole 148 | // +optional 149 | rules?: [...#PolicyRule] @go(Rules,[]PolicyRule) @protobuf(2,bytes,rep) 150 | 151 | // AggregationRule is an optional field that describes how to build the Rules for this ClusterRole. 152 | // If AggregationRule is set, then the Rules are controller managed and direct changes to Rules will be 153 | // stomped by the controller. 154 | // +optional 155 | aggregationRule?: null | #AggregationRule @go(AggregationRule,*AggregationRule) @protobuf(3,bytes,opt) 156 | } 157 | 158 | // AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole 159 | #AggregationRule: { 160 | // ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules. 161 | // If any of the selectors match, then the ClusterRole's permissions will be added 162 | // +optional 163 | clusterRoleSelectors?: [...metav1.#LabelSelector] @go(ClusterRoleSelectors,[]metav1.LabelSelector) @protobuf(1,bytes,rep) 164 | } 165 | 166 | // ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace, 167 | // and adds who information via Subject. 168 | #ClusterRoleBinding: { 169 | metav1.#TypeMeta 170 | 171 | // Standard object's metadata. 172 | // +optional 173 | metadata?: metav1.#ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt) 174 | 175 | // Subjects holds references to the objects the role applies to. 176 | // +optional 177 | subjects?: [...#Subject] @go(Subjects,[]Subject) @protobuf(2,bytes,rep) 178 | 179 | // RoleRef can only reference a ClusterRole in the global namespace. 180 | // If the RoleRef cannot be resolved, the Authorizer must return an error. 181 | // This field is immutable. 182 | roleRef: #RoleRef @go(RoleRef) @protobuf(3,bytes,opt) 183 | } 184 | 185 | // ClusterRoleBindingList is a collection of ClusterRoleBindings 186 | #ClusterRoleBindingList: { 187 | metav1.#TypeMeta 188 | 189 | // Standard object's metadata. 190 | // +optional 191 | metadata?: metav1.#ListMeta @go(ListMeta) @protobuf(1,bytes,opt) 192 | 193 | // Items is a list of ClusterRoleBindings 194 | items: [...#ClusterRoleBinding] @go(Items,[]ClusterRoleBinding) @protobuf(2,bytes,rep) 195 | } 196 | 197 | // ClusterRoleList is a collection of ClusterRoles 198 | #ClusterRoleList: { 199 | metav1.#TypeMeta 200 | 201 | // Standard object's metadata. 202 | // +optional 203 | metadata?: metav1.#ListMeta @go(ListMeta) @protobuf(1,bytes,opt) 204 | 205 | // Items is a list of ClusterRoles 206 | items: [...#ClusterRole] @go(Items,[]ClusterRole) @protobuf(2,bytes,rep) 207 | } 208 | --------------------------------------------------------------------------------