Compare commits

..

20 Commits

Author SHA1 Message Date
Jeff McCune
7d5852d675 (#34) Print secret data as json
Closes: #34
2024-03-05 11:03:47 -08:00
Jeff McCune
66b4ca0e6c (#31) Fix helm missing in actions workflow
Causing test failures that should pass.
2024-03-05 10:11:43 -08:00
Jeff McCune
b3f682453d (#31) Inject istio sidecar into Deployment zitadel using Kustomize
Multiple holos components rely on kustomize to modify the output of the
upstream helm chart, for example patching a Deployment to inject the
istio sidecar.

The new holos cue based component system did not support running
kustomize after helm template.  This patch adds the kustomize execution
if two fields are defined in the helm chart kind of cue output.

The API spec is pretty loose in this patch but I'm proceeding for
expedience and to inform the final API with more use cases as more
components are migrated to cue.
2024-03-05 09:56:39 -08:00
Jeff McCune
0c3181ae05 (#31) Add VirtualService for Zitadel
Also import the Kustomize types using:

    cue get go sigs.k8s.io/kustomize/api/types/...
2024-03-04 17:18:46 -08:00
Jeff McCune
18cbff0c13 (#31) Add tls cert for zitadel to connect to cockroach db
Cockroach DB uses tls certs for client authentication.  Issue one for
Zitadel.

With this patch Zitadel starts up bit is not yet exposted with a
VirtualService.

Refer to https://zitadel.com/docs/self-hosting/manage/configure
2024-03-04 14:46:49 -08:00
Jeff McCune
b4fca0929c (#31) ExternalSecret for zitadel-masterkey 2024-03-04 14:31:27 -08:00
Jeff McCune
911d65bdc6 (#31) Setup login.ois.run with basic istio default Gateway
The istio default Gateway is the basis for what will become a dynamic
set of server entries specified from cue project data integrated with
extauthz.

For now we simply need to get the identity provider up and running as
the first step toward identity and access management.
2024-03-04 13:59:17 -08:00
Jeff McCune
2a5eccf0c1 (#33) Helm stderr logging
Log error messages from helm when building and rendering holos
components.

Closes: #33
2024-03-04 13:16:51 -08:00
Jeff McCune
9db4873205 (#31) Add Cockroach DB for Zitadel
Following https://github.com/zitadel/zitadel-charts/blob/main/examples/4-cockroach-secure/README.md
2024-03-04 10:31:39 -08:00
Jeff McCune
f90e83e142 (#30) Add httpbin Gateway and VirtualService
There isn't a default Gateway yet, so use a specific `httpbin` gateway
to test istio instead.
2024-03-02 21:12:03 -08:00
Jeff McCune
bdd2964edb (#30) Add httpbin Service for ns istio-ingress 2024-03-02 20:39:55 -08:00
Jeff McCune
56375b82d8 (#30) Fix httpbin Deployment selector match labels
Without this patch the deployment fails with:

```
Deployment/istio-ingress/httpbin dry-run failed, reason: Invalid:
Deployment.apps "httpbin" is invalid: spec.template.metadata.labels:
Invalid value:
map[string]string{"app.kubernetes.io/component":"httpbin",
"app.kubernetes.io/instance":"prod-mesh-httpbin",
"app.kubernetes.io/name":"mesh", "app .kubernetes.io/part-of":"prod",
"holos.run/component.name":"httpbin", "holos.run/project.name":"mesh",
"holos.run/stage.name":"prod", "sidecar.istio.io/inject":"true"}:
`selector` does not match template `labels`
```
2024-03-02 20:23:23 -08:00
Jeff McCune
dc27489249 (#30) Add httpbin Deployment in istio-ingress namespace
This patch gets the Deployment running with a restricted seccomp
profile.
2024-03-02 20:17:16 -08:00
Jeff McCune
7d8a618e25 (#30) Add httpbin Certificate to verify the mesh
Also fix certmanager which was not installing role bindings correctly
because the flux kustomization was writing over the metadata namespace
field.
2024-03-02 17:16:42 -08:00
Jeff McCune
646f6fcdb0 (#30) Add https redirect overlay resources
This patch migrates the https redirect and the
istio-ingressgateway-loopback Service from
`holos-infra/components/core/istio/ingress/templates/deployment`
2024-03-02 15:01:58 -08:00
Jeff McCune
4ce39db745 (#30) Enforce restricted pod security profile on istio-ingress namespace
This patch enforces the restricted pod security profile on the istio
ingress namespace. The istio cni to move the traffic redirection from
the init container to a cni daemon set pod.

Refer to:

 - https://istio.io/latest/docs/setup/additional-setup/pod-security-admission/
 - https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted
2024-03-02 11:16:55 -08:00
Jeff McCune
eba58d1639 (#30) Add ingress component and istio-ingressgateway Deployment
Migrated from holos-infra/components/core/istio/ingress
2024-03-02 10:22:21 -08:00
Jeff McCune
765832d90d (#30) Trim istiod 2024-03-01 16:27:49 -08:00
Jeff McCune
d1163d689a (#30) Add istiod istio controller and meshconfig
This patch adds the standard istiod controller, which depends on
istio-base.

The holos reference platform heavily customizes the meshconfig, so the
upstream istio ConfigMap is disabled in the helm chart values.  The mesh
config is generated from cue data defined in the controller holos
component.

Note: This patch adds a static configuration for the istio meshconfig in
the meshconfig.cue file.  The extauthz providers are a core piece of
functionality in the holos reference platform and a key motivation of
moving to CUE from Helm is the need to dynamically generate the
meshconfig from a platform scoped set of projects and services across
multiple clusters.

For expedience this dynamic generation is not part of this patch but is
expected to replace the static meshconfig once the cluster is more fully
configured with the new cue based holos command line interface.
2024-03-01 16:13:19 -08:00
Jeff McCune
63009ba419 (#30) Fix cue formatting 2024-03-01 10:35:32 -08:00
76 changed files with 5223 additions and 129 deletions

View File

@@ -23,5 +23,10 @@ jobs:
with:
go-version: stable
- name: Set up Helm
uses: azure/setup-helm@v4.1.0
with:
version: 'latest'
- name: Test
run: ./scripts/test

View File

@@ -0,0 +1,280 @@
# Want helm errors to show up
! exec holos build .
stderr 'Error: execution error at \(zitadel/templates/secret_zitadel-masterkey.yaml:2:4\): Either set .Values.zitadel.masterkey xor .Values.zitadel.masterkeySecretName'
-- cue.mod --
package holos
-- zitadel.cue --
package holos
cluster: string @tag(cluster, string)
apiVersion: "holos.run/v1alpha1"
kind: "HelmChart"
metadata: name: "zitadel"
namespace: "zitadel"
chart: {
name: "zitadel"
version: "7.9.0"
repository: {
name: "zitadel"
url: "https://charts.zitadel.com"
}
}
-- vendor/zitadel/templates/secret_zitadel-masterkey.yaml --
{{- if (or (and .Values.zitadel.masterkey .Values.zitadel.masterkeySecretName) (and (not .Values.zitadel.masterkey) (not .Values.zitadel.masterkeySecretName)) ) }}
{{- fail "Either set .Values.zitadel.masterkey xor .Values.zitadel.masterkeySecretName" }}
{{- end }}
{{- if .Values.zitadel.masterkey -}}
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: zitadel-masterkey
{{- with .Values.zitadel.masterkeyAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
labels:
{{- include "zitadel.labels" . | nindent 4 }}
stringData:
masterkey: {{ .Values.zitadel.masterkey }}
{{- end -}}
-- vendor/zitadel/Chart.yaml --
apiVersion: v2
appVersion: v2.46.0
description: A Helm chart for ZITADEL
icon: https://zitadel.com/zitadel-logo-dark.svg
kubeVersion: '>= 1.21.0-0'
maintainers:
- email: support@zitadel.com
name: zitadel
url: https://zitadel.com
name: zitadel
type: application
version: 7.9.0
-- vendor/zitadel/values.yaml --
# Default values for zitadel.
zitadel:
# The ZITADEL config under configmapConfig is written to a Kubernetes ConfigMap
# See all defaults here:
# https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
configmapConfig:
ExternalSecure: true
Machine:
Identification:
Hostname:
Enabled: true
Webhook:
Enabled: false
# The ZITADEL config under secretConfig is written to a Kubernetes Secret
# See all defaults here:
# https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
secretConfig:
# Annotations set on secretConfig secret
secretConfigAnnotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "0"
# Reference the name of a secret that contains ZITADEL configuration.
configSecretName:
# The key under which the ZITADEL configuration is located in the secret.
configSecretKey: config-yaml
# ZITADEL uses the masterkey for symmetric encryption.
# You can generate it for example with tr -dc A-Za-z0-9 </dev/urandom | head -c 32
masterkey: ""
# Reference the name of the secret that contains the masterkey. The key should be named "masterkey".
# Note: Either zitadel.masterkey or zitadel.masterkeySecretName must be set
masterkeySecretName: ""
# Annotations set on masterkey secret
masterkeyAnnotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "0"
# The CA Certificate needed for establishing secure database connections
dbSslCaCrt: ""
# The Secret containing the CA certificate at key ca.crt needed for establishing secure database connections
dbSslCaCrtSecret: ""
# The db admins secret containing the client certificate and key at tls.crt and tls.key needed for establishing secure database connections
dbSslAdminCrtSecret: ""
# The db users secret containing the client certificate and key at tls.crt and tls.key needed for establishing secure database connections
dbSslUserCrtSecret: ""
# Generate a self-signed certificate using an init container
# This will also mount the generated files to /etc/tls/ so that you can reference them in the pod.
# E.G. KeyPath: /etc/tls/tls.key CertPath: /etc/tls/tls.crt
# By default, the SAN DNS names include, localhost, the POD IP address and the POD name. You may include one more by using additionalDnsName like "my.zitadel.fqdn".
selfSignedCert:
enabled: false
additionalDnsName:
replicaCount: 3
image:
repository: ghcr.io/zitadel/zitadel
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
chownImage:
repository: alpine
pullPolicy: IfNotPresent
tag: "3.19"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
# Annotations to add to the deployment
annotations: {}
# Annotations to add to the configMap
configMap:
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "0"
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "0"
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
podAnnotations: {}
podAdditionalLabels: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
securityContext: {}
# Additional environment variables
env:
[]
# - name: ZITADEL_DATABASE_POSTGRES_HOST
# valueFrom:
# secretKeyRef:
# name: postgres-pguser-postgres
# key: host
service:
type: ClusterIP
# If service type is "ClusterIP", this can optionally be set to a fixed IP address.
clusterIP: ""
port: 8080
protocol: http2
annotations: {}
scheme: HTTP
ingress:
enabled: false
className: ""
annotations: {}
hosts:
- host: localhost
paths:
- path: /
pathType: Prefix
tls: []
resources: {}
nodeSelector: {}
tolerations: []
affinity: {}
topologySpreadConstraints: []
initJob:
# Once ZITADEL is installed, the initJob can be disabled.
enabled: true
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "1"
resources: {}
backoffLimit: 5
activeDeadlineSeconds: 300
extraContainers: []
podAnnotations: {}
# Available init commands :
# "": initialize ZITADEL instance (without skip anything)
# database: initialize only the database
# grant: set ALL grant to user
# user: initialize only the database user
# zitadel: initialize ZITADEL internals (skip "create user" and "create database")
command: ""
setupJob:
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "2"
resources: {}
activeDeadlineSeconds: 300
extraContainers: []
podAnnotations: {}
additionalArgs:
- "--init-projections=true"
machinekeyWriter:
image:
repository: bitnami/kubectl
tag: ""
resources: {}
readinessProbe:
enabled: true
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 3
livenessProbe:
enabled: true
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 3
startupProbe:
enabled: true
periodSeconds: 1
failureThreshold: 30
metrics:
enabled: false
serviceMonitor:
# If true, the chart creates a ServiceMonitor that is compatible with Prometheus Operator
# https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#monitoring.coreos.com/v1.ServiceMonitor.
# The Prometheus community Helm chart installs this operator
# https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack#kube-prometheus-stack
enabled: false
honorLabels: false
honorTimestamps: true
pdb:
enabled: false
# these values are used for the PDB and are mutally exclusive
minAvailable: 1
# maxUnavailable: 1
annotations: {}

View File

@@ -3066,7 +3066,7 @@ import (
// If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext.
// More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
// +optional
securityContext?: null | #SecurityContext @go(SecurityContext,*SecurityContext) @protobuf(15,bytes,opt)
securityContext?: #SecurityContext @go(SecurityContext,*SecurityContext) @protobuf(15,bytes,opt)
// Whether this container should allocate a buffer for stdin in the container runtime. If this
// is not set, reads from stdin in the container will always result in EOF.
@@ -3982,7 +3982,7 @@ import (
// SecurityContext holds pod-level security attributes and common container settings.
// Optional: Defaults to empty. See type description for default values of each field.
// +optional
securityContext?: null | #PodSecurityContext @go(SecurityContext,*PodSecurityContext) @protobuf(14,bytes,opt)
securityContext?: #PodSecurityContext @go(SecurityContext,*PodSecurityContext) @protobuf(14,bytes,opt)
// ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec.
// If specified, these secrets will be passed to individual puller implementations for them to use.

View File

@@ -324,13 +324,7 @@ import "strings"
// withoutHeader has the same syntax with the header, but has
// opposite meaning.
withoutHeaders?: {
[string]: ({} | {
exact: _
} | {
prefix: _
} | {
regex: _
}) & {
[string]: {
exact?: string
prefix?: string
@@ -383,11 +377,7 @@ import "strings"
// A HTTP rule can either return a direct_response, redirect or
// forward (default) traffic.
redirect?: ({} | {
port: _
} | {
derivePort: _
}) & {
redirect?: {
// On a redirect, overwrite the Authority/Host portion of the URL
// with this value.
authority?: string

View File

@@ -0,0 +1,7 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
_#_BuiltinPluginLoadingOptions_name: "BploUndefinedBploUseStaticallyLinkedBploLoadFromFileSys"

View File

@@ -0,0 +1,10 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// ConfigMapArgs contains the metadata of how to generate a configmap.
#ConfigMapArgs: {
#GeneratorArgs
}

View File

@@ -0,0 +1,10 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
// Package types holds the definition of the kustomization struct and
// supporting structs. It's the k8s API conformant object that describes
// a set of generation and transformation operations to create and/or
// modify k8s resources.
// A kustomization file is a serialization of this struct.
package types

View File

@@ -0,0 +1,29 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// FieldSpec completely specifies a kustomizable field in a k8s API object.
// It helps define the operands of transformations.
//
// For example, a directive to add a common label to objects
// will need to know that a 'Deployment' object (in API group
// 'apps', any version) can have labels at field path
// 'spec/template/metadata/labels', and further that it is OK
// (or not OK) to add that field path to the object if the
// field path doesn't exist already.
//
// This would look like
// {
// group: apps
// kind: Deployment
// path: spec/template/metadata/labels
// create: true
// }
#FieldSpec: {
path?: string @go(Path)
create?: bool @go(CreateIfNotPresent)
}
#FsSlice: [...#FieldSpec]

View File

@@ -0,0 +1,33 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// GenerationBehavior specifies generation behavior of configmaps, secrets and maybe other resources.
#GenerationBehavior: int // #enumGenerationBehavior
#enumGenerationBehavior:
#BehaviorUnspecified |
#BehaviorCreate |
#BehaviorReplace |
#BehaviorMerge
#values_GenerationBehavior: {
BehaviorUnspecified: #BehaviorUnspecified
BehaviorCreate: #BehaviorCreate
BehaviorReplace: #BehaviorReplace
BehaviorMerge: #BehaviorMerge
}
// BehaviorUnspecified is an Unspecified behavior; typically treated as a Create.
#BehaviorUnspecified: #GenerationBehavior & 0
// BehaviorCreate makes a new resource.
#BehaviorCreate: #GenerationBehavior & 1
// BehaviorReplace replaces a resource.
#BehaviorReplace: #GenerationBehavior & 2
// BehaviorMerge attempts to merge a new resource with an existing resource.
#BehaviorMerge: #GenerationBehavior & 3

View File

@@ -0,0 +1,27 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// GeneratorArgs contains arguments common to ConfigMap and Secret generators.
#GeneratorArgs: {
// Namespace for the resource, optional
namespace?: string @go(Namespace)
// Name - actually the partial name - of the generated resource.
// The full name ends up being something like
// NamePrefix + this.Name + hash(content of generated resource).
name?: string @go(Name)
// Behavior of generated resource, must be one of:
// 'create': create a new one
// 'replace': replace the existing one
// 'merge': merge with the existing one
behavior?: string @go(Behavior)
#KvPairSources
// Local overrides to global generatorOptions field.
options?: null | #GeneratorOptions @go(Options,*GeneratorOptions)
}

View File

@@ -0,0 +1,22 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// GeneratorOptions modify behavior of all ConfigMap and Secret generators.
#GeneratorOptions: {
// Labels to add to all generated resources.
labels?: {[string]: string} @go(Labels,map[string]string)
// Annotations to add to all generated resources.
annotations?: {[string]: string} @go(Annotations,map[string]string)
// DisableNameSuffixHash if true disables the default behavior of adding a
// suffix to the names of generated resources that is a hash of the
// resource contents.
disableNameSuffixHash?: bool @go(DisableNameSuffixHash)
// Immutable if true add to all generated resources.
immutable?: bool @go(Immutable)
}

View File

@@ -0,0 +1,116 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
#HelmDefaultHome: "charts"
#HelmGlobals: {
// ChartHome is a file path, relative to the kustomization root,
// to a directory containing a subdirectory for each chart to be
// included in the kustomization.
// The default value of this field is "charts".
// So, for example, kustomize looks for the minecraft chart
// at {kustomizationRoot}/{ChartHome}/minecraft.
// If the chart is there at build time, kustomize will use it as found,
// and not check version numbers or dates.
// If the chart is not there, kustomize will attempt to pull it
// using the version number specified in the kustomization file,
// and put it there. To suppress the pull attempt, simply assure
// that the chart is already there.
chartHome?: string @go(ChartHome)
// ConfigHome defines a value that kustomize should pass to helm via
// the HELM_CONFIG_HOME environment variable. kustomize doesn't attempt
// to read or write this directory.
// If omitted, {tmpDir}/helm is used, where {tmpDir} is some temporary
// directory created by kustomize for the benefit of helm.
// Likewise, kustomize sets
// HELM_CACHE_HOME={ConfigHome}/.cache
// HELM_DATA_HOME={ConfigHome}/.data
// for the helm subprocess.
configHome?: string @go(ConfigHome)
}
#HelmChart: {
// Name is the name of the chart, e.g. 'minecraft'.
name?: string @go(Name)
// Version is the version of the chart, e.g. '3.1.3'
version?: string @go(Version)
// Repo is a URL locating the chart on the internet.
// This is the argument to helm's `--repo` flag, e.g.
// `https://itzg.github.io/minecraft-server-charts`.
repo?: string @go(Repo)
// ReleaseName replaces RELEASE-NAME in chart template output,
// making a particular inflation of a chart unique with respect to
// other inflations of the same chart in a cluster. It's the first
// argument to the helm `install` and `template` commands, i.e.
// helm install {RELEASE-NAME} {chartName}
// helm template {RELEASE-NAME} {chartName}
// If omitted, the flag --generate-name is passed to 'helm template'.
releaseName?: string @go(ReleaseName)
// Namespace set the target namespace for a release. It is .Release.Namespace
// in the helm template
namespace?: string @go(Namespace)
// AdditionalValuesFiles are local file paths to values files to be used in
// addition to either the default values file or the values specified in ValuesFile.
additionalValuesFiles?: [...string] @go(AdditionalValuesFiles,[]string)
// ValuesFile is a local file path to a values file to use _instead of_
// the default values that accompanied the chart.
// The default values are in '{ChartHome}/{Name}/values.yaml'.
valuesFile?: string @go(ValuesFile)
// ValuesInline holds value mappings specified directly,
// rather than in a separate file.
valuesInline?: {...} @go(ValuesInline,map[string]interface{})
// ValuesMerge specifies how to treat ValuesInline with respect to Values.
// Legal values: 'merge', 'override', 'replace'.
// Defaults to 'override'.
valuesMerge?: string @go(ValuesMerge)
// IncludeCRDs specifies if Helm should also generate CustomResourceDefinitions.
// Defaults to 'false'.
includeCRDs?: bool @go(IncludeCRDs)
// SkipHooks sets the --no-hooks flag when calling helm template. This prevents
// helm from erroneously rendering test templates.
skipHooks?: bool @go(SkipHooks)
// ApiVersions is the kubernetes apiversions used for Capabilities.APIVersions
apiVersions?: [...string] @go(ApiVersions,[]string)
// KubeVersion is the kubernetes version used by Helm for Capabilities.KubeVersion"
kubeVersion?: string @go(KubeVersion)
// NameTemplate is for specifying the name template used to name the release.
nameTemplate?: string @go(NameTemplate)
// SkipTests skips tests from templated output.
skipTests?: bool @go(SkipTests)
}
// HelmChartArgs contains arguments to helm.
// Deprecated. Use HelmGlobals and HelmChart instead.
#HelmChartArgs: {
chartName?: string @go(ChartName)
chartVersion?: string @go(ChartVersion)
chartRepoUrl?: string @go(ChartRepoURL)
chartHome?: string @go(ChartHome)
chartRepoName?: string @go(ChartRepoName)
helmBin?: string @go(HelmBin)
helmHome?: string @go(HelmHome)
values?: string @go(Values)
valuesLocal?: {...} @go(ValuesLocal,map[string]interface{})
valuesMerge?: string @go(ValuesMerge)
releaseName?: string @go(ReleaseName)
releaseNamespace?: string @go(ReleaseNamespace)
extraArgs?: [...string] @go(ExtraArgs,[]string)
}

View File

@@ -0,0 +1,40 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
#Cloud: string // #enumCloud
#enumCloud:
#GKE
#GKE: #Cloud & "gke"
// IAMPolicyGeneratorArgs contains arguments to generate a GKE service account resource.
#IAMPolicyGeneratorArgs: {
// which cloud provider to generate for (e.g. "gke")
cloud: #Cloud @go(Cloud)
// information about the kubernetes cluster for this object
kubernetesService: #KubernetesService @go(KubernetesService)
// information about the service account and project
serviceAccount: #ServiceAccount @go(ServiceAccount)
}
#KubernetesService: {
// the name used for the Kubernetes service account
name: string @go(Name)
// the name of the Kubernetes namespace for this object
namespace?: string @go(Namespace)
}
#ServiceAccount: {
// the name of the new cloud provider service account
name: string @go(Name)
// The ID of the project
projectId: string @go(ProjectId)
}

View File

@@ -0,0 +1,26 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// Image contains an image name, a new name, a new tag or digest,
// which will replace the original name and tag.
#Image: {
// Name is a tag-less image name.
name?: string @go(Name)
// NewName is the value used to replace the original name.
newName?: string @go(NewName)
// TagSuffix is the value used to suffix the original tag
// If Digest and NewTag is present an error is thrown
tagSuffix?: string @go(TagSuffix)
// NewTag is the value used to replace the original tag.
newTag?: string @go(NewTag)
// Digest is the value used to replace the original image tag.
// If digest is present NewTag value is ignored.
digest?: string @go(Digest)
}

View File

@@ -0,0 +1,163 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
#KustomizationVersion: "kustomize.config.k8s.io/v1beta1"
#KustomizationKind: "Kustomization"
#ComponentVersion: "kustomize.config.k8s.io/v1alpha1"
#ComponentKind: "Component"
#MetadataNamespacePath: "metadata/namespace"
#MetadataNamespaceApiVersion: "v1"
#MetadataNamePath: "metadata/name"
#OriginAnnotations: "originAnnotations"
#TransformerAnnotations: "transformerAnnotations"
#ManagedByLabelOption: "managedByLabel"
// Kustomization holds the information needed to generate customized k8s api resources.
#Kustomization: {
#TypeMeta
// MetaData is a pointer to avoid marshalling empty struct
metadata?: null | #ObjectMeta @go(MetaData,*ObjectMeta)
// OpenAPI contains information about what kubernetes schema to use.
openapi?: {[string]: string} @go(OpenAPI,map[string]string)
// NamePrefix will prefix the names of all resources mentioned in the kustomization
// file including generated configmaps and secrets.
namePrefix?: string @go(NamePrefix)
// NameSuffix will suffix the names of all resources mentioned in the kustomization
// file including generated configmaps and secrets.
nameSuffix?: string @go(NameSuffix)
// Namespace to add to all objects.
namespace?: string @go(Namespace)
// CommonLabels to add to all objects and selectors.
commonLabels?: {[string]: string} @go(CommonLabels,map[string]string)
// Labels to add to all objects but not selectors.
labels?: [...#Label] @go(Labels,[]Label)
// CommonAnnotations to add to all objects.
commonAnnotations?: {[string]: string} @go(CommonAnnotations,map[string]string)
// Deprecated: Use the Patches field instead, which provides a superset of the functionality of PatchesStrategicMerge.
// PatchesStrategicMerge specifies the relative path to a file
// containing a strategic merge patch. Format documented at
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/strategic-merge-patch.md
// URLs and globs are not supported.
patchesStrategicMerge?: [...#PatchStrategicMerge] @go(PatchesStrategicMerge,[]PatchStrategicMerge)
// Deprecated: Use the Patches field instead, which provides a superset of the functionality of JSONPatches.
// JSONPatches is a list of JSONPatch for applying JSON patch.
// Format documented at https://tools.ietf.org/html/rfc6902
// and http://jsonpatch.com
patchesJson6902?: [...#Patch] @go(PatchesJson6902,[]Patch)
// Patches is a list of patches, where each one can be either a
// Strategic Merge Patch or a JSON patch.
// Each patch can be applied to multiple target objects.
patches?: [...#Patch] @go(Patches,[]Patch)
// Images is a list of (image name, new name, new tag or digest)
// for changing image names, tags or digests. This can also be achieved with a
// patch, but this operator is simpler to specify.
images?: [...#Image] @go(Images,[]Image)
// Deprecated: Use the Images field instead.
imageTags?: [...#Image] @go(ImageTags,[]Image)
// Replacements is a list of replacements, which will copy nodes from a
// specified source to N specified targets.
replacements?: [...#ReplacementField] @go(Replacements,[]ReplacementField)
// Replicas is a list of {resourcename, count} that allows for simpler replica
// specification. This can also be done with a patch.
replicas?: [...#Replica] @go(Replicas,[]Replica)
// Deprecated: Vars will be removed in future release. Migrate to Replacements instead.
// Vars allow things modified by kustomize to be injected into a
// kubernetes object specification. A var is a name (e.g. FOO) associated
// with a field in a specific resource instance. The field must
// contain a value of type string/bool/int/float, and defaults to the name field
// of the instance. Any appearance of "$(FOO)" in the object
// spec will be replaced at kustomize build time, after the final
// value of the specified field has been determined.
vars?: [...#Var] @go(Vars,[]Var)
// SortOptions change the order that kustomize outputs resources.
sortOptions?: null | #SortOptions @go(SortOptions,*SortOptions)
// Resources specifies relative paths to files holding YAML representations
// of kubernetes API objects, or specifications of other kustomizations
// via relative paths, absolute paths, or URLs.
resources?: [...string] @go(Resources,[]string)
// Components specifies relative paths to specifications of other Components
// via relative paths, absolute paths, or URLs.
components?: [...string] @go(Components,[]string)
// Crds specifies relative paths to Custom Resource Definition files.
// This allows custom resources to be recognized as operands, making
// it possible to add them to the Resources list.
// CRDs themselves are not modified.
crds?: [...string] @go(Crds,[]string)
// Deprecated: Anything that would have been specified here should be specified in the Resources field instead.
bases?: [...string] @go(Bases,[]string)
// ConfigMapGenerator is a list of configmaps to generate from
// local data (one configMap per list item).
// The resulting resource is a normal operand, subject to
// name prefixing, patching, etc. By default, the name of
// the map will have a suffix hash generated from its contents.
configMapGenerator?: [...#ConfigMapArgs] @go(ConfigMapGenerator,[]ConfigMapArgs)
// SecretGenerator is a list of secrets to generate from
// local data (one secret per list item).
// The resulting resource is a normal operand, subject to
// name prefixing, patching, etc. By default, the name of
// the map will have a suffix hash generated from its contents.
secretGenerator?: [...#SecretArgs] @go(SecretGenerator,[]SecretArgs)
// HelmGlobals contains helm configuration that isn't chart specific.
helmGlobals?: null | #HelmGlobals @go(HelmGlobals,*HelmGlobals)
// HelmCharts is a list of helm chart configuration instances.
helmCharts?: [...#HelmChart] @go(HelmCharts,[]HelmChart)
// HelmChartInflationGenerator is a list of helm chart configurations.
// Deprecated. Auto-converted to HelmGlobals and HelmCharts.
helmChartInflationGenerator?: [...#HelmChartArgs] @go(HelmChartInflationGenerator,[]HelmChartArgs)
// GeneratorOptions modify behavior of all ConfigMap and Secret generators.
generatorOptions?: null | #GeneratorOptions @go(GeneratorOptions,*GeneratorOptions)
// Configurations is a list of transformer configuration files
configurations?: [...string] @go(Configurations,[]string)
// Generators is a list of files containing custom generators
generators?: [...string] @go(Generators,[]string)
// Transformers is a list of files containing transformers
transformers?: [...string] @go(Transformers,[]string)
// Validators is a list of files containing validators
validators?: [...string] @go(Validators,[]string)
// BuildMetadata is a list of strings used to toggle different build options
buildMetadata?: [...string] @go(BuildMetadata,[]string)
}
_#deprecatedWarningToRunEditFix: "Run 'kustomize edit fix' to update your Kustomization automatically."
_#deprecatedWarningToRunEditFixExperimential: "[EXPERIMENTAL] Run 'kustomize edit fix' to update your Kustomization automatically."
_#deprecatedBaseWarningMessage: "# Warning: 'bases' is deprecated. Please use 'resources' instead. Run 'kustomize edit fix' to update your Kustomization automatically."
_#deprecatedImageTagsWarningMessage: "# Warning: 'imageTags' is deprecated. Please use 'images' instead. Run 'kustomize edit fix' to update your Kustomization automatically."
_#deprecatedPatchesJson6902Message: "# Warning: 'patchesJson6902' is deprecated. Please use 'patches' instead. Run 'kustomize edit fix' to update your Kustomization automatically."
_#deprecatedPatchesStrategicMergeMessage: "# Warning: 'patchesStrategicMerge' is deprecated. Please use 'patches' instead. Run 'kustomize edit fix' to update your Kustomization automatically."
_#deprecatedVarsMessage: "# Warning: 'vars' is deprecated. Please use 'replacements' instead. [EXPERIMENTAL] Run 'kustomize edit fix' to update your Kustomization automatically."
_#deprecatedCommonLabelsWarningMessage: "# Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically."

View File

@@ -0,0 +1,37 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// KvPairSources defines places to obtain key value pairs.
#KvPairSources: {
// LiteralSources is a list of literal
// pair sources. Each literal source should
// be a key and literal value, e.g. `key=value`
literals?: [...string] @go(LiteralSources,[]string)
// FileSources is a list of file "sources" to
// use in creating a list of key, value pairs.
// A source takes the form: [{key}=]{path}
// If the "key=" part is missing, the key is the
// path's basename. If they "key=" part is present,
// it becomes the key (replacing the basename).
// In either case, the value is the file contents.
// Specifying a directory will iterate each named
// file in the directory whose basename is a
// valid configmap key.
files?: [...string] @go(FileSources,[]string)
// EnvSources is a list of file paths.
// The contents of each file should be one
// key=value pair per line, e.g. a Docker
// or npm ".env" file or a ".ini" file
// (wikipedia.org/wiki/INI_file)
envs?: [...string] @go(EnvSources,[]string)
// Older, singular form of EnvSources.
// On edits (e.g. `kustomize fix`) this is merged into the plural form
// for consistency with LiteralSources and FileSources.
env?: string @go(EnvSource)
}

View File

@@ -0,0 +1,23 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
#Label: {
// Pairs contains the key-value pairs for labels to add
pairs?: {[string]: string} @go(Pairs,map[string]string)
// IncludeSelectors inidicates should transformer include the
// fieldSpecs for selectors. Custom fieldSpecs specified by
// FieldSpecs will be merged with builtin fieldSpecs if this
// is true.
includeSelectors?: bool @go(IncludeSelectors)
// IncludeTemplates inidicates should transformer include the
// spec/template/metadata fieldSpec. Custom fieldSpecs specified by
// FieldSpecs will be merged with spec/template/metadata fieldSpec if this
// is true. If IncludeSelectors is true, IncludeTemplates is not needed.
includeTemplates?: bool @go(IncludeTemplates)
fields?: [...#FieldSpec] @go(FieldSpecs,[]FieldSpec)
}

View File

@@ -0,0 +1,34 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// Restrictions on what things can be referred to
// in a kustomization file.
//
//go:generate stringer -type=LoadRestrictions
#LoadRestrictions: int // #enumLoadRestrictions
#enumLoadRestrictions:
#LoadRestrictionsUnknown |
#LoadRestrictionsRootOnly |
#LoadRestrictionsNone
#values_LoadRestrictions: {
LoadRestrictionsUnknown: #LoadRestrictionsUnknown
LoadRestrictionsRootOnly: #LoadRestrictionsRootOnly
LoadRestrictionsNone: #LoadRestrictionsNone
}
#LoadRestrictionsUnknown: #LoadRestrictions & 0
// Files referenced by a kustomization file must be in
// or under the directory holding the kustomization
// file itself.
#LoadRestrictionsRootOnly: #LoadRestrictions & 1
// The kustomization file may specify absolute or
// relative paths to patch or resources files outside
// its own tree.
#LoadRestrictionsNone: #LoadRestrictions & 2

View File

@@ -0,0 +1,7 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
_#_LoadRestrictions_name: "LoadRestrictionsUnknownLoadRestrictionsRootOnlyLoadRestrictionsNone"

View File

@@ -0,0 +1,14 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// ObjectMeta partially copies apimachinery/pkg/apis/meta/v1.ObjectMeta
// No need for a direct dependence; the fields are stable.
#ObjectMeta: {
name?: string @go(Name)
namespace?: string @go(Namespace)
labels?: {[string]: string} @go(Labels,map[string]string)
annotations?: {[string]: string} @go(Annotations,map[string]string)
}

View File

@@ -0,0 +1,11 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// Pair is a key value pair.
#Pair: {
Key: string
Value: string
}

View File

@@ -0,0 +1,23 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// Patch represent either a Strategic Merge Patch or a JSON patch
// and its targets.
// The content of the patch can either be from a file
// or from an inline string.
#Patch: {
// Path is a relative file path to the patch file.
path?: string @go(Path)
// Patch is the content of a patch.
patch?: string @go(Patch)
// Target points to the resources that the patch is applied to
target?: #Target | #Selector @go(Target,*Selector)
// Options is a list of options for the patch
options?: {[string]: bool} @go(Options,map[string]bool)
}

View File

@@ -0,0 +1,10 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// PatchStrategicMerge represents a relative path to a
// stategic merge patch with the format
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/strategic-merge-patch.md
#PatchStrategicMerge: string

View File

@@ -0,0 +1,27 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
#HelmConfig: {
Enabled: bool
Command: string
ApiVersions: [...string] @go(,[]string)
KubeVersion: string
}
// PluginConfig holds plugin configuration.
#PluginConfig: {
// PluginRestrictions distinguishes plugin restrictions.
PluginRestrictions: #PluginRestrictions
// BpLoadingOptions distinguishes builtin plugin behaviors.
BpLoadingOptions: #BuiltinPluginLoadingOptions
// FnpLoadingOptions sets the way function-based plugin behaviors.
FnpLoadingOptions: #FnPluginLoadingOptions
// HelmConfig contains metadata needed for allowing and running helm.
HelmConfig: #HelmConfig
}

View File

@@ -0,0 +1,87 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// Some plugin classes
// - builtin: plugins defined in the kustomize repo.
// May be freely used and re-configured.
// - local: plugins that aren't builtin but are
// locally defined (presumably by the user), meaning
// the kustomization refers to them via a relative
// file path, not a URL.
// - remote: require a build-time download to obtain.
// Unadvised, unless one controls the
// serving site.
//
//go:generate stringer -type=PluginRestrictions
#PluginRestrictions: int // #enumPluginRestrictions
#enumPluginRestrictions:
#PluginRestrictionsUnknown |
#PluginRestrictionsBuiltinsOnly |
#PluginRestrictionsNone
#values_PluginRestrictions: {
PluginRestrictionsUnknown: #PluginRestrictionsUnknown
PluginRestrictionsBuiltinsOnly: #PluginRestrictionsBuiltinsOnly
PluginRestrictionsNone: #PluginRestrictionsNone
}
#PluginRestrictionsUnknown: #PluginRestrictions & 0
// Non-builtin plugins completely disabled.
#PluginRestrictionsBuiltinsOnly: #PluginRestrictions & 1
// No restrictions, do whatever you want.
#PluginRestrictionsNone: #PluginRestrictions & 2
// BuiltinPluginLoadingOptions distinguish ways in which builtin plugins are used.
//go:generate stringer -type=BuiltinPluginLoadingOptions
#BuiltinPluginLoadingOptions: int // #enumBuiltinPluginLoadingOptions
#enumBuiltinPluginLoadingOptions:
#BploUndefined |
#BploUseStaticallyLinked |
#BploLoadFromFileSys
#values_BuiltinPluginLoadingOptions: {
BploUndefined: #BploUndefined
BploUseStaticallyLinked: #BploUseStaticallyLinked
BploLoadFromFileSys: #BploLoadFromFileSys
}
#BploUndefined: #BuiltinPluginLoadingOptions & 0
// Desired in production use for performance.
#BploUseStaticallyLinked: #BuiltinPluginLoadingOptions & 1
// Desired in testing and development cycles where it's undesirable
// to generate static code.
#BploLoadFromFileSys: #BuiltinPluginLoadingOptions & 2
// FnPluginLoadingOptions set way functions-based plugins are restricted
#FnPluginLoadingOptions: {
// Allow to run executables
EnableExec: bool
// Allow to run starlark
EnableStar: bool
// Allow container access to network
Network: bool
NetworkName: string
// list of mounts
Mounts: [...string] @go(,[]string)
// list of env variables to pass to fn
Env: [...string] @go(,[]string)
// Run as uid and gid of the command executor
AsCurrentUser: bool
// Run in this working directory
WorkingDir: string
}

View File

@@ -0,0 +1,7 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
_#_PluginRestrictions_name: "PluginRestrictionsUnknownPluginRestrictionsBuiltinsOnlyPluginRestrictionsNone"

View File

@@ -0,0 +1,57 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
#DefaultReplacementFieldPath: "metadata.name"
// Replacement defines how to perform a substitution
// where it is from and where it is to.
#Replacement: {
// The source of the value.
source?: null | #SourceSelector @go(Source,*SourceSelector)
// The N fields to write the value to.
targets?: [...null | #TargetSelector] @go(Targets,[]*TargetSelector)
}
// SourceSelector is the source of the replacement transformer.
#SourceSelector: {
// Structured field path expected in the allowed object.
fieldPath?: string @go(FieldPath)
// Used to refine the interpretation of the field.
options?: null | #FieldOptions @go(Options,*FieldOptions)
}
// TargetSelector specifies fields in one or more objects.
#TargetSelector: {
// Include objects that match this.
select?: null | #Selector @go(Select,*Selector)
// From the allowed set, remove objects that match this.
reject?: [...null | #Selector] @go(Reject,[]*Selector)
// Structured field paths expected in each allowed object.
fieldPaths?: [...string] @go(FieldPaths,[]string)
// Used to refine the interpretation of the field.
options?: null | #FieldOptions @go(Options,*FieldOptions)
}
// FieldOptions refine the interpretation of FieldPaths.
#FieldOptions: {
// Used to split/join the field.
delimiter?: string @go(Delimiter)
// Which position in the split to consider.
index?: int @go(Index)
// TODO (#3492): Implement use of this option
// None, Base64, URL, Hex, etc
encoding?: string @go(Encoding)
// If field missing, add it.
create?: bool @go(Create)
}

View File

@@ -0,0 +1,10 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
#ReplacementField: {
#Replacement
path?: string @go(Path)
}

View File

@@ -0,0 +1,17 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// Replica specifies a modification to a replica config.
// The number of replicas of a resource whose name matches will be set to count.
// This struct is used by the ReplicaCountTransform, and is meant to supplement
// the existing patch functionality with a simpler syntax for replica configuration.
#Replica: {
// The name of the resource to change the replica count
name?: string @go(Name)
// The number of replicas required.
count: int64 @go(Count)
}

View File

@@ -0,0 +1,19 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// SecretArgs contains the metadata of how to generate a secret.
#SecretArgs: {
#GeneratorArgs
// Type of the secret.
//
// This is the same field as the secret type field in v1/Secret:
// It can be "Opaque" (default), or "kubernetes.io/tls".
//
// If type is "kubernetes.io/tls", then "literals" or "files" must have exactly two
// keys: "tls.key" and "tls.crt"
type?: string @go(Type)
}

View File

@@ -0,0 +1,20 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// Selector specifies a set of resources.
// Any resource that matches intersection of all conditions
// is included in this set.
#Selector: {
// AnnotationSelector is a string that follows the label selection expression
// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api
// It matches with the resource annotations.
annotationSelector?: string @go(AnnotationSelector)
// LabelSelector is a string that follows the label selection expression
// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api
// It matches with the resource labels.
labelSelector?: string @go(LabelSelector)
}

View File

@@ -0,0 +1,36 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// SortOptions defines the order that kustomize outputs resources.
#SortOptions: {
// Order selects the ordering strategy.
order?: #SortOrder @go(Order)
// LegacySortOptions tweaks the sorting for the "legacy" sort ordering
// strategy.
legacySortOptions?: null | #LegacySortOptions @go(LegacySortOptions,*LegacySortOptions)
}
// SortOrder defines different ordering strategies.
#SortOrder: string // #enumSortOrder
#enumSortOrder:
#LegacySortOrder |
#FIFOSortOrder
#LegacySortOrder: #SortOrder & "legacy"
#FIFOSortOrder: #SortOrder & "fifo"
// LegacySortOptions define various options for tweaking the "legacy" ordering
// strategy.
#LegacySortOptions: {
// OrderFirst selects the resource kinds to order first.
orderFirst: [...string] @go(OrderFirst,[]string)
// OrderLast selects the resource kinds to order last.
orderLast: [...string] @go(OrderLast,[]string)
}

View File

@@ -0,0 +1,12 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// TypeMeta partially copies apimachinery/pkg/apis/meta/v1.TypeMeta
// No need for a direct dependence; the fields are stable.
#TypeMeta: {
kind?: string @go(Kind)
apiVersion?: string @go(APIVersion)
}

View File

@@ -0,0 +1,45 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go sigs.k8s.io/kustomize/api/types
package types
// Var represents a variable whose value will be sourced
// from a field in a Kubernetes object.
#Var: {
// Value of identifier name e.g. FOO used in container args, annotations
// Appears in pod template as $(FOO)
name: string @go(Name)
// ObjRef must refer to a Kubernetes resource under the
// purview of this kustomization. ObjRef should use the
// raw name of the object (the name specified in its YAML,
// before addition of a namePrefix and a nameSuffix).
objref: #Target @go(ObjRef)
// FieldRef refers to the field of the object referred to by
// ObjRef whose value will be extracted for use in
// replacing $(FOO).
// If unspecified, this defaults to fieldPath: $defaultFieldPath
fieldref?: #FieldSelector @go(FieldRef)
}
// Target refers to a kubernetes object by Group, Version, Kind and Name
// gvk.Gvk contains Group, Version and Kind
// APIVersion is added to keep the backward compatibility of using ObjectReference
// for Var.ObjRef
#Target: {
apiVersion?: string @go(APIVersion)
name: string @go(Name)
namespace?: string @go(Namespace)
}
// FieldSelector contains the fieldPath to an object field.
// This struct is added to keep the backward compatibility of using ObjectFieldSelector
// for Var.FieldRef
#FieldSelector: {
fieldPath?: string @go(FieldPath)
}
// byName is a sort interface which sorts Vars by name alphabetically
_#byName: [...#Var]

View File

@@ -0,0 +1,6 @@
package v1
#Deployment: {
apiVersion: "apps/v1"
kind: "Deployment"
}

View File

@@ -1,11 +1,11 @@
package v1
#CronJob: {
apiVersion: "batch/v1"
kind: "CronJob"
apiVersion: "batch/v1"
kind: "CronJob"
}
#Job: {
apiVersion: "batch/v1"
kind: "Job"
apiVersion: "batch/v1"
kind: "Job"
}

View File

@@ -1,21 +1,26 @@
package v1
#Namespace: {
apiVersion: "v1"
kind: "Namespace"
apiVersion: "v1"
kind: "Namespace"
}
#ConfigMap: {
apiVersion: "v1"
kind: "ConfigMap"
apiVersion: "v1"
kind: "ConfigMap"
}
#ServiceAccount: {
apiVersion: "v1"
kind: "ServiceAccount"
apiVersion: "v1"
kind: "ServiceAccount"
}
#Pod: {
apiVersion: "v1"
kind: "Pod"
apiVersion: "v1"
kind: "Pod"
}
#Service: {
apiVersion: "v1"
kind: "Service"
}

View File

@@ -0,0 +1,15 @@
package types
#Patch: {
// Path is a relative file path to the patch file.
path?: string @go(Path)
// Patch is the content of a patch.
patch?: string @go(Patch)
// Target points to the resources that the patch is applied to
target?: #Target | #Selector @go(Target,*Selector)
// Options is a list of options for the patch
options?: {[string]: bool} @go(Options,map[string]bool)
}

View File

@@ -0,0 +1,7 @@
package types
#Target: {
group?: string @go(Group)
version?: string @go(Version)
kind?: string @go(Kind)
}

View File

@@ -4,6 +4,7 @@ package holos
#PlatformNamespace: {
name: string
labels?: {[string]: string}
annotations?: {[string]: string}
}
// #PlatformNamespaces is a list of namespaces to manage across the platform.

View File

@@ -0,0 +1,10 @@
package holos
// Components under this directory are part of this collection
#InputKeys: project: "iam"
// Shared dependencies for all components in this collection.
#DependsOn: _Namespaces
// Common Dependencies
_Namespaces: Namespaces: name: "\(#StageName)-secrets-namespaces"

View File

@@ -0,0 +1,17 @@
# IAM
The IAM service provides identity and access management for a holos managed platform. Zitadel is the identity provider which integrates tightly with:
1. AuthorizationPolicy at the level of the service mesh.
2. Application level oidc login (ArgoCD, Grafana, etc...)
3. Cloud provider IAM via oidc.
## Preflight
The zitadel master key needs to have a data key named `masterkey` with a Secret name of `zitadel-masterkey`.
```bash
holos create secret zitadel-masterkey --namespace prod-iam-zitadel --append-hash=false --data-stdin <<EOF
{"masterkey":"$(tr -dc A-Za-z0-9 </dev/urandom | head -c 32)"}
EOF
```

View File

@@ -0,0 +1,26 @@
package holos
#InputKeys: component: "crdb"
#HelmChart & {
namespace: #TargetNamespace
chart: {
name: "cockroachdb"
version: "11.2.3"
repository: {
name: "cockroachdb"
url: "https://charts.cockroachdb.com/"
}
}
values: #Values
apiObjects: {
Issuer: {
// https://github.com/cockroachdb/helm-charts/blob/3dcf96726ebcfe3784afb526ddcf4095a1684aea/README.md?plain=1#L196-L201
cockroachdb: #Issuer & {
metadata: name: #ComponentName
metadata: namespace: #TargetNamespace
spec: selfSigned: {}
}
}
}
}

View File

@@ -0,0 +1,606 @@
package holos
#Values: {
// Generated file, DO NOT EDIT. Source: build/templates/values.yaml
// Overrides the chart name against the label "app.kubernetes.io/name: " placed on every resource this chart creates.
nameOverride: ""
// Override the resource names created by this chart which originally is generated using release and chart name.
fullnameOverride: string | *""
image: {
repository: string | *"cockroachdb/cockroach"
tag: "v23.1.13"
pullPolicy: "IfNotPresent"
credentials: {}
}
// registry: docker.io
// username: john_doe
// password: changeme
// Additional labels to apply to all Kubernetes resources created by this chart.
labels: {}
// app.kubernetes.io/part-of: my-app
// Cluster's default DNS domain.
// You should overwrite it if you're using a different one,
// otherwise CockroachDB nodes discovery won't work.
clusterDomain: "cluster.local"
conf: {
// An ordered list of CockroachDB node attributes.
// Attributes are arbitrary strings specifying machine capabilities.
// Machine capabilities might include specialized hardware or number of cores
// (e.g. "gpu", "x16c").
attrs: []
// - x16c
// - gpu
// Total size in bytes for caches, shared evenly if there are multiple
// storage devices. Size suffixes are supported (e.g. `1GB` and `1GiB`).
// A percentage of physical memory can also be specified (e.g. `.25`).
cache: "25%"
// Sets a name to verify the identity of a cluster.
// The value must match between all nodes specified via `conf.join`.
// This can be used as an additional verification when either the node or
// cluster, or both, have not yet been initialized and do not yet know their
// cluster ID.
// To introduce a cluster name into an already-initialized cluster, pair this
// option with `conf.disable-cluster-name-verification: yes`.
"cluster-name": ""
// Tell the server to ignore `conf.cluster-name` mismatches.
// This is meant for use when opting an existing cluster into starting to use
// cluster name verification, or when changing the cluster name.
// The cluster should be restarted once with `conf.cluster-name` and
// `conf.disable-cluster-name-verification: yes` combined, and once all nodes
// have been updated to know the new cluster name, the cluster can be restarted
// again with `conf.disable-cluster-name-verification: no`.
// This option has no effect if `conf.cluster-name` is not specified.
"disable-cluster-name-verification": false
// The addresses for connecting a CockroachDB nodes to an existing cluster.
// If you are deploying a second CockroachDB instance that should join a first
// one, use the below list to join to the existing instance.
// Each item in the array should be a FQDN (and port if needed) resolvable by
// new Pods.
join: []
// New logging configuration.
log: {
enabled: false
// https://www.cockroachlabs.com/docs/v21.1/configure-logs
config: {}
}
// file-defaults:
// dir: /custom/dir/path/
// fluent-defaults:
// format: json-fluent
// sinks:
// stderr:
// channels: [DEV]
// Logs at or above this threshold to STDERR. Ignored when "log" is enabled
logtostderr: "INFO"
// Maximum storage capacity available to store temporary disk-based data for
// SQL queries that exceed the memory budget (e.g. join, sorts, etc are
// sometimes able to spill intermediate results to disk).
// Accepts numbers interpreted as bytes, size suffixes (e.g. `32GB` and
// `32GiB`) or a percentage of disk size (e.g. `10%`).
// The location of the temporary files is within the first store dir.
// If expressed as a percentage, `max-disk-temp-storage` is interpreted
// relative to the size of the storage device on which the first store is
// placed. The temp space usage is never counted towards any store usage
// (although it does share the device with the first store) so, when
// configuring this, make sure that the size of this temp storage plus the size
// of the first store don't exceed the capacity of the storage device.
// If the first store is an in-memory one (i.e. `type=mem`), then this
// temporary "disk" data is also kept in-memory.
// A percentage value is interpreted as a percentage of the available internal
// memory.
// max-disk-temp-storage: 0GB
// Maximum allowed clock offset for the cluster. If observed clock offsets
// exceed this limit, servers will crash to minimize the likelihood of
// reading inconsistent data. Increasing this value will increase the time
// to recovery of failures as well as the frequency of uncertainty-based
// read restarts.
// Note, that this value must be the same on all nodes in the cluster.
// In order to change it, all nodes in the cluster must be stopped
// simultaneously and restarted with the new value.
// max-offset: 500ms
// Maximum memory capacity available to store temporary data for SQL clients,
// including prepared queries and intermediate data rows during query
// execution. Accepts numbers interpreted as bytes, size suffixes
// (e.g. `1GB` and `1GiB`) or a percentage of physical memory (e.g. `.25`).
"max-sql-memory": "25%"
// An ordered, comma-separated list of key-value pairs that describe the
// topography of the machine. Topography might include country, datacenter
// or rack designations. Data is automatically replicated to maximize
// diversities of each tier. The order of tiers is used to determine
// the priority of the diversity, so the more inclusive localities like
// country should come before less inclusive localities like datacenter.
// The tiers and order must be the same on all nodes. Including more tiers
// is better than including fewer. For example:
// locality: country=us,region=us-west,datacenter=us-west-1b,rack=12
// locality: country=ca,region=ca-east,datacenter=ca-east-2,rack=4
// locality: planet=earth,province=manitoba,colo=secondary,power=3
locality: ""
// Run CockroachDB instances in standalone mode with replication disabled
// (replication factor = 1).
// Enabling this option makes the following values to be ignored:
// - `conf.cluster-name`
// - `conf.disable-cluster-name-verification`
// - `conf.join`
//
// WARNING: Enabling this option makes each deployed Pod as a STANDALONE
// CockroachDB instance, so the StatefulSet does NOT FORM A CLUSTER.
// Don't use this option for production deployments unless you clearly
// understand what you're doing.
// Usually, this option is intended to be used in conjunction with
// `statefulset.replicas: 1` for temporary one-time deployments (like
// running E2E tests, for example).
"single-node": false
// If non-empty, create a SQL audit log in the specified directory.
"sql-audit-dir": ""
// CockroachDB's port to listen to inter-communications and client connections.
port: 26257
// CockroachDB's port to listen to HTTP requests.
"http-port": 8080
// CockroachDB's data mount path.
path: "cockroach-data"
// CockroachDB's storage configuration https://www.cockroachlabs.com/docs/v21.1/cockroach-start.html#storage
// Uses --store flag
store: {
enabled: false
// Should be empty or 'mem'
type: null
// Required for type=mem. If type and size is empty - storage.persistentVolume.size is used
size: null
// Arbitrary strings, separated by colons, specifying disk type or capability
attrs: null
}
}
statefulset: {
replicas: 3
updateStrategy: type: "RollingUpdate"
podManagementPolicy: "Parallel"
budget: maxUnavailable: 1
// List of additional command-line arguments you want to pass to the
// `cockroach start` command.
args: []
// - --disable-cluster-name-verification
// List of extra environment variables to pass into container
env: []
// - name: COCKROACH_ENGINE_MAX_SYNC_DURATION
// value: "24h"
// List of Secrets names in the same Namespace as the CockroachDB cluster,
// which shall be mounted into `/etc/cockroach/secrets/` for every cluster
// member.
secretMounts: []
// Additional labels to apply to this StatefulSet and all its Pods.
labels: {
"app.kubernetes.io/component": "cockroachdb"
}
// Additional annotations to apply to the Pods of this StatefulSet.
annotations: {}
// Affinity rules for scheduling Pods of this StatefulSet on Nodes.
// https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity
nodeAffinity: {}
// Inter-Pod Affinity rules for scheduling Pods of this StatefulSet.
// https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity
podAffinity: {}
// Anti-affinity rules for scheduling Pods of this StatefulSet.
// https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity
// You may either toggle options below for default anti-affinity rules,
// or specify the whole set of anti-affinity rules instead of them.
podAntiAffinity: {
// The topologyKey to be used.
// Can be used to spread across different nodes, AZs, regions etc.
topologyKey: "kubernetes.io/hostname"
// Type of anti-affinity rules: either `soft`, `hard` or empty value (which
// disables anti-affinity rules).
type: "soft"
// Weight for `soft` anti-affinity rules.
// Does not apply for other anti-affinity types.
weight: 100
}
// Node selection constraints for scheduling Pods of this StatefulSet.
// https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
nodeSelector: {}
// PriorityClassName given to Pods of this StatefulSet
// https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass
priorityClassName: ""
// Taints to be tolerated by Pods of this StatefulSet.
// https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
tolerations: []
// https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
topologySpreadConstraints: {
maxSkew: 1
topologyKey: "topology.kubernetes.io/zone"
whenUnsatisfiable: "ScheduleAnyway"
}
// Uncomment the following resources definitions or pass them from
// command line to control the CPU and memory resources allocated
// by Pods of this StatefulSet.
resources: {}
// limits:
// cpu: 100m
// memory: 512Mi
// requests:
// cpu: 100m
// memory: 512Mi
// Custom Liveness probe
// https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-liveness-http-request
customLivenessProbe: {}
// httpGet:
// path: /health
// port: http
// scheme: HTTPS
// initialDelaySeconds: 30
// periodSeconds: 5
// Custom Rediness probe
// https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-readiness-probes
customReadinessProbe: {}
// httpGet:
// path: /health
// port: http
// scheme: HTTPS
// initialDelaySeconds: 30
// periodSeconds: 5
securityContext: {
enabled: true
}
serviceAccount: {
// Specifies whether this ServiceAccount should be created.
create: true
// The name of this ServiceAccount to use.
// If not set and `create` is `true`, then service account is auto-generated.
// If not set and `create` is `false`, then it uses default service account.
name: ""
// Additional serviceAccount annotations (e.g. for attaching AWS IAM roles to pods)
annotations: {}
}
}
service: {
ports: {
// You can set a different external and internal gRPC ports and their name.
grpc: {
external: {
port: 26257
name: "grpc"
}
// If the port number is different than `external.port`, then it will be
// named as `internal.name` in Service.
internal: {
port: 26257
// If using Istio set it to `cockroach`.
name: "grpc-internal"
}
}
http: {
port: 8080
name: "http"
}
}
// This Service is meant to be used by clients of the database.
// It exposes a ClusterIP that will automatically load balance connections
// to the different database Pods.
public: {
type: "ClusterIP"
// Additional labels to apply to this Service.
labels: {
"app.kubernetes.io/component": "cockroachdb"
}
// Additional annotations to apply to this Service.
annotations: {}
}
// This service only exists to create DNS entries for each pod in
// the StatefulSet such that they can resolve each other's IP addresses.
// It does not create a load-balanced ClusterIP and should not be used directly
// by clients in most circumstances.
discovery: {
// Additional labels to apply to this Service.
labels: {
"app.kubernetes.io/component": "cockroachdb"
}
// Additional annotations to apply to this Service.
annotations: {}
}
}
// CockroachDB's ingress for web ui.
ingress: {
enabled: false
labels: {}
annotations: {}
// kubernetes.io/ingress.class: nginx
// cert-manager.io/cluster-issuer: letsencrypt
paths: ["/"]
hosts: []
// - cockroachlabs.com
tls: []
}
// - hosts: [cockroachlabs.com]
// secretName: cockroachlabs-tls
prometheus: {
enabled: true
}
securityContext: enabled: true
// CockroachDB's Prometheus operator ServiceMonitor support
serviceMonitor: {
enabled: false
labels: {}
annotations: {}
interval: "10s"
// scrapeTimeout: 10s
// Limits the ServiceMonitor to the current namespace if set to `true`.
namespaced: false
// tlsConfig: TLS configuration to use when scraping the endpoint.
// Of type: https://github.com/coreos/prometheus-operator/blob/main/Documentation/api.md#tlsconfig
tlsConfig: {}
}
// CockroachDB's data persistence.
// If neither `persistentVolume` nor `hostPath` is used, then data will be
// persisted in ad-hoc `emptyDir`.
storage: {
// Absolute path on host to store CockroachDB's data.
// If not specified, then `emptyDir` will be used instead.
// If specified, but `persistentVolume.enabled` is `true`, then has no effect.
hostPath: ""
// If `enabled` is `true` then a PersistentVolumeClaim will be created and
// used to store CockroachDB's data, otherwise `hostPath` is used.
persistentVolume: {
enabled: true
size: string | *"100Gi"
// If defined, then `storageClassName: <storageClass>`.
// If set to "-", then `storageClassName: ""`, which disables dynamic
// provisioning.
// If undefined or empty (default), then no `storageClassName` spec is set,
// so the default provisioner will be chosen (gp2 on AWS, standard on
// GKE, AWS & OpenStack).
storageClass: ""
// Additional labels to apply to the created PersistentVolumeClaims.
labels: {}
// Additional annotations to apply to the created PersistentVolumeClaims.
annotations: {}
}
}
// Kubernetes Job which initializes multi-node CockroachDB cluster.
// It's not created if `statefulset.replicas` is `1`.
init: {
// Additional labels to apply to this Job and its Pod.
labels: {
"app.kubernetes.io/component": "init"
}
// Additional annotations to apply to this Job.
jobAnnotations: {}
// Additional annotations to apply to the Pod of this Job.
annotations: {}
// Affinity rules for scheduling the Pod of this Job.
// https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity
affinity: {}
// Node selection constraints for scheduling the Pod of this Job.
// https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
nodeSelector: {}
// Taints to be tolerated by the Pod of this Job.
// https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
tolerations: []
// The init Pod runs at cluster creation to initialize CockroachDB. It finishes
// quickly and doesn't continue to consume resources in the Kubernetes
// cluster. Normally, you should leave this section commented out, but if your
// Kubernetes cluster uses Resource Quotas and requires all pods to specify
// resource requests or limits, you can set those here.
resources: {}
// requests:
// cpu: "10m"
// memory: "128Mi"
// limits:
// cpu: "10m"
// memory: "128Mi"
securityContext: {
enabled: true
}
provisioning: {
enabled: false
// https://www.cockroachlabs.com/docs/stable/cluster-settings.html
clusterSettings: null
// cluster.organization: "'FooCorp - Local Testing'"
// enterprise.license: "'xxxxx'"
users: []
// - name:
// password:
// # https://www.cockroachlabs.com/docs/stable/create-user.html#parameters
// options: [LOGIN]
databases: []
}
}
// - name:
// # https://www.cockroachlabs.com/docs/stable/create-database.html#parameters
// options: [encoding='utf-8']
// owners: []
// # https://www.cockroachlabs.com/docs/stable/grant.html#parameters
// owners_with_grant_option: []
// # Backup schedules are not idemponent for now and will fail on next run
// # https://github.com/cockroachdb/cockroach/issues/57892
// backup:
// into: s3://
// # Enterprise-only option (revision_history)
// # https://www.cockroachlabs.com/docs/stable/create-schedule-for-backup.html#backup-options
// options: [revision_history]
// recurring: '@always'
// # Enterprise-only feature. Remove this value to use `FULL BACKUP ALWAYS`
// fullBackup: '@daily'
// schedule:
// # https://www.cockroachlabs.com/docs/stable/create-schedule-for-backup.html#schedule-options
// options: [first_run = 'now']
// Whether to run securely using TLS certificates.
tls: {
enabled: true
copyCerts: image: "busybox"
certs: {
// Bring your own certs scenario. If provided, tls.init section will be ignored.
provided: false
// Secret name for the client root cert.
clientRootSecret: "cockroachdb-root"
// Secret name for node cert.
nodeSecret: "cockroachdb-node"
// Secret name for CA cert
caSecret: "cockroach-ca"
// Enable if the secret is a dedicated TLS.
// TLS secrets are created by cert-mananger, for example.
tlsSecret: false
// Enable if the you want cockroach db to create its own certificates
selfSigner: {
// If set, the cockroach db will generate its own certificates
enabled: false | *true
// Run selfSigner as non-root
securityContext: {
enabled: true
}
// If set, the user should provide the CA certificate to sign other certificates.
caProvided: false
// It holds the name of the secret with caCerts. If caProvided is set, this can not be empty.
caSecret: ""
// Minimum Certificate duration for all the certificates, all certs duration will be validated against this.
minimumCertDuration: "624h"
// Duration of CA certificates in hour
caCertDuration: "43800h"
// Expiry window of CA certificates means a window before actual expiry in which CA certs should be rotated.
caCertExpiryWindow: "648h"
// Duration of Client certificates in hour
clientCertDuration: "672h"
// Expiry window of client certificates means a window before actual expiry in which client certs should be rotated.
clientCertExpiryWindow: "48h"
// Duration of node certificates in hour
nodeCertDuration: "8760h"
// Expiry window of node certificates means a window before actual expiry in which node certs should be rotated.
nodeCertExpiryWindow: "168h"
// If set, the cockroachdb cert selfSigner will rotate the certificates before expiry.
rotateCerts: true
// Wait time for each cockroachdb replica to become ready once it comes in running state. Only considered when rotateCerts is set to true
readinessWait: "30s"
// Wait time for each cockroachdb replica to get to running state. Only considered when rotateCerts is set to true
podUpdateTimeout: "2m"
// ServiceAccount annotations for selfSigner jobs (e.g. for attaching AWS IAM roles to pods)
svcAccountAnnotations: {}
}
// Use cert-manager to issue certificates for mTLS.
certManager: true | *false
// Specify an Issuer or a ClusterIssuer to use, when issuing
// node and client certificates. The values correspond to the
// issuerRef specified in the certificate.
certManagerIssuer: {
group: "cert-manager.io"
kind: "Issuer"
name: string | *"cockroachdb"
// Make it false when you are providing your own CA issuer
isSelfSignedIssuer: true
// Duration of Client certificates in hours
clientCertDuration: "672h"
// Expiry window of client certificates means a window before actual expiry in which client certs should be rotated.
clientCertExpiryWindow: "48h"
// Duration of node certificates in hours
nodeCertDuration: "8760h"
// Expiry window of node certificates means a window before actual expiry in which node certs should be rotated.
nodeCertExpiryWindow: "168h"
}
}
selfSigner: {
// Additional annotations to apply to the Pod of this Job.
annotations: {}
// Affinity rules for scheduling the Pod of this Job.
// https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity
affinity: {}
// Node selection constraints for scheduling the Pod of this Job.
// https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
nodeSelector: {}
// Taints to be tolerated by the Pod of this Job.
// https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
tolerations: []
// Image Placeholder for the selfSigner utility. This will be changed once the CI workflows for the image is in place.
image: {
repository: "cockroachlabs-helm-charts/cockroach-self-signer-cert"
tag: "1.5"
pullPolicy: "IfNotPresent"
credentials: {}
registry: "gcr.io"
}
}
}
// username: john_doe
// password: changeme
networkPolicy: {
enabled: false
ingress: {
// List of sources which should be able to access the CockroachDB Pods via
// gRPC port. Items in this list are combined using a logical OR operation.
// Rules for allowing inter-communication are applied automatically.
// If empty, then connections from any Pod is allowed.
grpc: []
// - podSelector:
// matchLabels:
// app.kubernetes.io/name: my-app-django
// app.kubernetes.io/instance: my-app
// List of sources which should be able to access the CockroachDB Pods via
// HTTP port. Items in this list are combined using a logical OR operation.
// If empty, then connections from any Pod is allowed.
http: []
}
}
// - namespaceSelector:
// matchLabels:
// project: my-project
// To put the admin interface behind Identity Aware Proxy (IAP) on Google Cloud Platform
// make sure to set ingress.paths: ['/*']
iap: {
enabled: false
}
}

View File

@@ -0,0 +1,25 @@
package holos
#Values: {
image: repository: "quay.io/holos/cockroachdb/cockroach"
fullnameOverride: #ComponentName
tls: {
enabled: true
certs: {
// https://github.com/cockroachdb/helm-charts/blob/3dcf96726ebcfe3784afb526ddcf4095a1684aea/README.md?plain=1#L204-L215
selfSigner: enabled: false
certManager: true
certManagerIssuer: {
kind: "Issuer"
name: #ComponentName
}
}
}
storage: persistentVolume: {
enabled: true
size: "1Gi"
}
}

View File

@@ -0,0 +1,10 @@
package holos
#TargetNamespace: #InstancePrefix + "-zitadel"
#DB: {
Host: "crdb-public"
}
// The canonical login domain for the entire platform. Zitadel will be active on a singlec cluster at a time, but always accessible from this hostname.
#ExternalDomain: "login.\(#Platform.org.domain)"

View File

@@ -0,0 +1,251 @@
package holos
#Values: {
// Default values for zitadel.
zitadel: {
// The ZITADEL config under configmapConfig is written to a Kubernetes ConfigMap
// See all defaults here:
// https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
configmapConfig: {
ExternalSecure: true
Machine: Identification: {
Hostname: Enabled: true
Webhook: Enabled: false
}
}
// The ZITADEL config under secretConfig is written to a Kubernetes Secret
// See all defaults here:
// https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
secretConfig: null
// Annotations set on secretConfig secret
secretConfigAnnotations: {
"helm.sh/hook": "pre-install,pre-upgrade"
"helm.sh/hook-delete-policy": "before-hook-creation"
"helm.sh/hook-weight": "0"
}
// Reference the name of a secret that contains ZITADEL configuration.
configSecretName: null
// The key under which the ZITADEL configuration is located in the secret.
configSecretKey: "config-yaml"
// ZITADEL uses the masterkey for symmetric encryption.
// You can generate it for example with tr -dc A-Za-z0-9 </dev/urandom | head -c 32
masterkey: ""
// Reference the name of the secret that contains the masterkey. The key should be named "masterkey".
// Note: Either zitadel.masterkey or zitadel.masterkeySecretName must be set
masterkeySecretName: string | *""
// Annotations set on masterkey secret
masterkeyAnnotations: {
"helm.sh/hook": "pre-install,pre-upgrade"
"helm.sh/hook-delete-policy": "before-hook-creation"
"helm.sh/hook-weight": "0"
}
// The CA Certificate needed for establishing secure database connections
dbSslCaCrt: ""
// The Secret containing the CA certificate at key ca.crt needed for establishing secure database connections
dbSslCaCrtSecret: string | *""
// The db admins secret containing the client certificate and key at tls.crt and tls.key needed for establishing secure database connections
dbSslAdminCrtSecret: string | *""
// The db users secret containing the client certificate and key at tls.crt and tls.key needed for establishing secure database connections
dbSslUserCrtSecret: string | *""
// Generate a self-signed certificate using an init container
// This will also mount the generated files to /etc/tls/ so that you can reference them in the pod.
// E.G. KeyPath: /etc/tls/tls.key CertPath: /etc/tls/tls.crt
// By default, the SAN DNS names include, localhost, the POD IP address and the POD name. You may include one more by using additionalDnsName like "my.zitadel.fqdn".
selfSignedCert: {
enabled: false
additionalDnsName: null
}
}
replicaCount: 3
image: {
repository: "ghcr.io/zitadel/zitadel"
pullPolicy: "IfNotPresent"
// Overrides the image tag whose default is the chart appVersion.
tag: ""
}
chownImage: {
repository: "alpine"
pullPolicy: "IfNotPresent"
tag: "3.19"
}
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
// Annotations to add to the deployment
annotations: {}
// Annotations to add to the configMap
configMap: {
annotations: {
"helm.sh/hook": "pre-install,pre-upgrade"
"helm.sh/hook-delete-policy": "before-hook-creation"
"helm.sh/hook-weight": "0"
}
}
serviceAccount: {
// Specifies whether a service account should be created
create: true
// Annotations to add to the service account
annotations: {
"helm.sh/hook": "pre-install,pre-upgrade"
"helm.sh/hook-delete-policy": "before-hook-creation"
"helm.sh/hook-weight": "0"
}
// The name of the service account to use.
// If not set and create is true, a name is generated using the fullname template
name: ""
}
podAnnotations: {}
podAdditionalLabels: {}
podSecurityContext: {
runAsNonRoot: true
runAsUser: 1000
}
securityContext: {}
// Additional environment variables
env: []
// - name: ZITADEL_DATABASE_POSTGRES_HOST
// valueFrom:
// secretKeyRef:
// name: postgres-pguser-postgres
// key: host
service: {
type: "ClusterIP"
// If service type is "ClusterIP", this can optionally be set to a fixed IP address.
clusterIP: ""
port: 8080
protocol: "http2"
annotations: {}
scheme: "HTTP"
}
ingress: {
enabled: false
className: ""
annotations: {}
hosts: [{
host: "localhost"
paths: [{
path: "/"
pathType: "Prefix"
}]
}]
tls: []
}
resources: {}
nodeSelector: {}
tolerations: []
affinity: {}
topologySpreadConstraints: []
initJob: {
// Once ZITADEL is installed, the initJob can be disabled.
enabled: true
annotations: {
"helm.sh/hook": "pre-install,pre-upgrade"
"helm.sh/hook-delete-policy": "before-hook-creation"
"helm.sh/hook-weight": "1"
}
resources: {}
backoffLimit: 5
activeDeadlineSeconds: 300
extraContainers: []
podAnnotations: {}
// Available init commands :
// "": initialize ZITADEL instance (without skip anything)
// database: initialize only the database
// grant: set ALL grant to user
// user: initialize only the database user
// zitadel: initialize ZITADEL internals (skip "create user" and "create database")
command: ""
}
setupJob: {
annotations: {
"helm.sh/hook": "pre-install,pre-upgrade"
"helm.sh/hook-delete-policy": "before-hook-creation"
"helm.sh/hook-weight": "2"
}
resources: {}
activeDeadlineSeconds: 300
extraContainers: []
podAnnotations: {}
additionalArgs: ["--init-projections=true"]
machinekeyWriter: {
image: {
repository: "bitnami/kubectl"
tag: ""
}
resources: {}
}
}
readinessProbe: {
enabled: true
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 3
}
livenessProbe: {
enabled: true
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 3
}
startupProbe: {
enabled: true
periodSeconds: 1
failureThreshold: 30
}
metrics: {
enabled: false
serviceMonitor: {
// If true, the chart creates a ServiceMonitor that is compatible with Prometheus Operator
// https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#monitoring.coreos.com/v1.ServiceMonitor.
// The Prometheus community Helm chart installs this operator
// https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack#kube-prometheus-stack
enabled: false
honorLabels: false
honorTimestamps: true
}
}
pdb: {
enabled: false
// these values are used for the PDB and are mutally exclusive
minAvailable: 1
// maxUnavailable: 1
annotations: {}
}
}

View File

@@ -0,0 +1,34 @@
package holos
#Values: {
// https://raw.githubusercontent.com/zitadel/zitadel-charts/main/examples/4-cockroach-secure/zitadel-values.yaml
zitadel: {
masterkeySecretName: "zitadel-masterkey"
// https://github.com/zitadel/zitadel-charts/blob/zitadel-7.4.0/charts/zitadel/templates/configmap.yaml#L13
configmapConfig: {
// NOTE: You can change the ExternalDomain, ExternalPort and ExternalSecure
// configuration options at any time. However, for ZITADEL to be able to
// pick up the changes, you need to rerun ZITADELs setup phase. Do so with
// kubectl delete job zitadel-setup, then re-apply the new config.
//
// https://zitadel.com/docs/self-hosting/manage/custom-domain
ExternalDomain: #ExternalDomain
ExternalPort: 443
ExternalSecure: true
TLS: Enabled: false
Database: Cockroach: {
Host: #DB.Host
User: SSL: Mode: "verify-full"
Admin: SSL: Mode: "verify-full"
}
}
// Managed by crdb component
dbSslCaCrtSecret: "cockroach-ca"
dbSslAdminCrtSecret: "cockroachdb-root"
// Managed by this component
dbSslUserCrtSecret: "cockroachdb-zitadel"
}
}

View File

@@ -0,0 +1,70 @@
package holos
import "encoding/yaml"
let Name = "zitadel"
#InputKeys: component: Name
// Upstream helm chart doesn't specify the namespace field for all resources.
#Kustomization: spec: targetNamespace: #TargetNamespace
#HelmChart & {
namespace: #TargetNamespace
chart: {
name: Name
version: "7.9.0"
repository: {
name: Name
url: "https://charts.zitadel.com"
}
}
values: #Values
apiObjects: {
ExternalSecret: masterkey: #ExternalSecret & {
_name: "zitadel-masterkey"
}
Certificate: zitadel: #Certificate & {
metadata: name: "crdb-zitadel-client"
metadata: namespace: #TargetNamespace
spec: {
commonName: "zitadel"
issuerRef: {
group: "cert-manager.io"
kind: "Issuer"
name: "crdb-ca-issuer"
}
privateKey: algorithm: "RSA"
privateKey: size: 2048
renewBefore: "48h0m0s"
secretName: "cockroachdb-zitadel"
subject: organizations: ["Cockroach"]
usages: ["digital signature", "key encipherment", "client auth"]
}
}
VirtualService: zitadel: #VirtualService & {
metadata: name: Name
metadata: namespace: #TargetNamespace
spec: hosts: ["login.\(#Platform.org.domain)"]
spec: gateways: ["istio-ingress/default"]
spec: http: [{route: [{destination: host: Name}]}]
}
}
}
// TODO: Generalize this common pattern of injecting the istio sidecar into a Deployment
let Patch = [{op: "add", path: "/spec/template/metadata/labels/sidecar.istio.io~1inject", value: "true"}]
#Kustomize: {
patches: [
{
target: {
group: "apps"
version: "v1"
kind: "Deployment"
name: Name
}
patch: yaml.Marshal(Patch)
},
]
}

View File

@@ -10,7 +10,9 @@ package holos
}
#HelmChart & {
values: installCRDs: true
values: #UpstreamValues & {
installCRDs: true
}
namespace: #TargetNamespace
chart: {
name: "cert-manager"

View File

@@ -0,0 +1,17 @@
package holos
#InputKeys: component: "istio-base"
#TargetNamespace: "istio-system"
#HelmChart & {
namespace: #TargetNamespace
chart: {
name: "base"
version: "1.20.3"
repository: {
name: "istio"
url: "https://istio-release.storage.googleapis.com/charts"
}
}
values: #IstioValues
}

View File

@@ -1,42 +0,0 @@
package holos
#InputKeys: component: "istio-base"
#TargetNamespace: "istio-system"
#HelmChart & {
namespace: #TargetNamespace
chart: {
name: "base"
version: "1.20.3"
repository: {
name: "istio"
url: "https://istio-release.storage.googleapis.com/charts"
}
}
values: {
global: {
// Used to locate istiod.
istioNamespace: #TargetNamespace
// Switch the hub away from the default docker.io to avoid rate limits
hub: "gcr.io/istio-release"
// ImagePullSecrets for control plane ServiceAccount, list of secrets in the same namespace
// to use for pulling any images in pods that reference this ServiceAccount.
// Must be set for any cluster configured with private docker registry.
imagePullSecrets: []
istiod: enableAnalysis: false
configValidation: true
externalIstiod: false
remotePilotAddress: ""
}
base: {
// Include the CRDs in the helm template output
enableCRDTemplates: true
// Validation webhook configuration url
// For example: https://$remotePilotAddress:15017/validate
validationURL: ""
// For istioctl usage to disable istio config crds in base
enableIstioConfigCRDs: true
}
defaultRevision: "default"
}
}

View File

@@ -0,0 +1,10 @@
package holos
#InputKeys: component: "cni"
#TargetNamespace: "kube-system"
#HelmChart & {
namespace: #TargetNamespace
chart: name: "cni"
values: #IstioValues
}

View File

@@ -0,0 +1,46 @@
package holos
// The primary istio Gateway, named default
let Name = "gateway"
#InputKeys: component: Name
#TargetNamespace: "istio-ingress"
#DependsOn: _IngressGateway
// TODO: We need to generalize this for multiple services hanging off the default gateway.
let LoginCert = #Certificate & {
metadata: {
name: "login"
namespace: #TargetNamespace
}
spec: {
commonName: "login.\(#Platform.org.domain)"
dnsNames: [commonName]
secretName: metadata.name
issuerRef: kind: "ClusterIssuer"
issuerRef: name: "letsencrypt"
}
}
#KubernetesObjects & {
apiObjects: {
Certificate: login: LoginCert
Gateway: default: #Gateway & {
metadata: name: "default"
metadata: namespace: #TargetNamespace
spec: selector: istio: "ingressgateway"
spec: servers: [
{
hosts: ["prod-iam-zitadel/\(LoginCert.spec.commonName)"]
port: name: "https-prod-iam-zitadel"
port: number: 443
port: protocol: "HTTPS"
tls: credentialName: LoginCert.spec.secretName
tls: mode: "SIMPLE"
},
]
}
}
}

View File

@@ -0,0 +1,75 @@
package holos
let Name = "httpbin"
let SecretName = #InputKeys.cluster + "-" + Name
let MatchLabels = {app: Name} & #SelectorLabels
let Metadata = {
name: Name
namespace: #TargetNamespace
labels: app: Name
}
#InputKeys: component: Name
#TargetNamespace: "istio-ingress"
#DependsOn: _IngressGateway
let Cert = #HTTP01Cert & {
_name: Name
_secret: SecretName
}
#KubernetesObjects & {
apiObjects: {
Certificate: httpbin: Cert.object
Deployment: httpbin: #Deployment & {
metadata: Metadata
spec: selector: matchLabels: MatchLabels
spec: template: {
metadata: labels: MatchLabels
metadata: labels: #CommonLabels
metadata: labels: #IstioSidecar
spec: securityContext: seccompProfile: type: "RuntimeDefault"
spec: containers: [{
name: Name
image: "quay.io/holos/mccutchen/go-httpbin"
ports: [{containerPort: 8080}]
securityContext: {
seccompProfile: type: "RuntimeDefault"
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1337
runAsGroup: 1337
capabilities: drop: ["ALL"]
}}]
}
}
Service: httpbin: #Service & {
metadata: Metadata
spec: selector: MatchLabels
spec: ports: [
{port: 80, targetPort: 8080, protocol: "TCP", name: "http"},
]
}
Gateway: httpbin: #Gateway & {
metadata: Metadata
spec: selector: istio: "ingressgateway"
spec: servers: [
{
hosts: ["\(#TargetNamespace)/\(Cert.Host)"]
port: name: "https-\(#InstanceName)"
port: number: 443
port: protocol: "HTTPS"
tls: credentialName: Cert.SecretName
tls: mode: "SIMPLE"
},
]
}
VirtualService: httpbin: #VirtualService & {
metadata: Metadata
spec: hosts: [Cert.Host]
spec: gateways: ["\(#TargetNamespace)/\(Name)"]
spec: http: [{route: [{destination: host: Name}]}]
}
}
}

View File

@@ -0,0 +1,155 @@
package holos
import "encoding/json"
#InputKeys: component: "ingress"
#TargetNamespace: "istio-ingress"
#DependsOn: _IstioD
#HelmChart & {
chart: name: "gateway"
namespace: #TargetNamespace
values: #GatewayValues & {
// This component expects the load balancer to send the PROXY protocol header.
// Refer to: https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/service/annotations/#proxy-protocol-v2
podAnnotations: "proxy.istio.io/config": json.Marshal(_ProxyProtocol)
// TODO This configuration is specific to the OIS Metal NLB, refactor it out to the metal collection.
service: {
type: "NodePort"
annotations: "service.beta.kubernetes.io/aws-load-balancer-proxy-protocol": "*"
externalTrafficPolicy: "Local"
// Add 30000 to the port to get the Nodeport
ports: [
{
name: "status-port"
port: 15021
protocol: "TCP"
targetPort: 15021
nodePort: 30021
},
{
name: "http2"
port: 80
protocol: "TCP"
targetPort: 80
nodePort: 30080
},
{
name: "https"
port: 443
protocol: "TCP"
targetPort: 443
nodePort: 30443
},
]
}
}
apiObjects: _APIObjects
}
_ProxyProtocol: gatewayTopology: proxyProtocol: {}
// Additional holos specific API Objects
let Name = #GatewayValues.name
let GatewayLabels = {
app: Name
istio: "ingressgateway"
}
let RedirectMetaName = {
name: Name + "-https-redirect"
namespace: #TargetNamespace
}
// https-redirect
_APIObjects: {
Gateway: {
httpsRedirect: #Gateway & {
metadata: RedirectMetaName
spec: selector: GatewayLabels
spec: servers: [{
port: {
number: 80
name: "http2"
protocol: "HTTP2"
}
hosts: ["*"]
// handled by the VirtualService
tls: httpsRedirect: false
}]
}
}
VirtualService: {
httpsRedirect: #VirtualService & {
metadata: RedirectMetaName
spec: hosts: ["*"]
spec: gateways: [RedirectMetaName.name]
spec: http: [{
match: [{withoutHeaders: ":path": prefix: "/.well-known/acme-challenge/"}]
redirect: {
scheme: "https"
redirectCode: 302
}
}]
}
}
}
let LoopbackName = Name + "-loopback"
let LoopbackDescription = "Allows in-cluster traffic to stay in cluster via traffic routing"
let LoopbackLabels = {
app: LoopbackName
istio: "ingressgateway"
}
let LoopbackMetaName = {
name: LoopbackName
namespace: #TargetNamespace
}
// istio-ingressgateway-loopback
_APIObjects: {
Deployment: {
loopback: #Deployment & {
_description: LoopbackDescription
metadata: LoopbackMetaName
spec: {
selector: matchLabels: LoopbackLabels
template: {
metadata: {
annotations: "inject.istio.io/templates": "gateway"
annotations: #Description & {
_Description: LoopbackDescription
}
labels: LoopbackLabels & {"sidecar.istio.io/inject": "true"}
}
spec: {
serviceAccountName: "istio-ingressgateway"
// Allow binding to all ports (such as 80 and 443)
securityContext: {
runAsNonRoot: true
seccompProfile: type: "RuntimeDefault"
sysctls: [{name: "net.ipv4.ip_unprivileged_port_start", value: "0"}]
}
containers: [{
name: "istio-proxy"
image: "auto" // Managed by istiod
securityContext: {
allowPrivilegeEscalation: false
capabilities: drop: ["ALL"]
runAsUser: 1337
runAsGroup: 1337
}
}]
}
}
}
}
}
Service: {
loopback: #Service & {
_description: LoopbackDescription
metadata: LoopbackMetaName
spec: selector: LoopbackLabels
spec: ports: [{port: 80, name: "http"}, {port: 443, name: "https"}]
}
}
}

View File

@@ -0,0 +1,13 @@
package holos
#DependsOn: _IstioBase
#HelmChart: {
chart: {
version: "1.20.3"
repository: {
name: "istio"
url: "https://istio-release.storage.googleapis.com/charts"
}
}
}

View File

@@ -0,0 +1,34 @@
package holos
import "encoding/yaml"
#InputKeys: component: "istiod"
#TargetNamespace: "istio-system"
#HelmChart & {
namespace: #TargetNamespace
chart: {
name: "istiod"
}
values: #IstioValues & {
pilot: {
// The istio meshconfig ConfigMap is handled in the holos component instead of
// the upstream chart so extension providers can be collected from holos data.
configMap: false
// Set to `type: RuntimeDefault` to use the default profile if available.
seccompProfile: type: "RuntimeDefault"
}
}
apiObjects: ConfigMap: istio: #IstioConfigMap
}
#IstioConfigMap: #ConfigMap & {
metadata: {
name: "istio"
namespace: #TargetNamespace
}
data: {
mesh: yaml.Marshal(_MeshConfig)
meshNetworks: "networks: {}"
}
}

View File

@@ -0,0 +1,74 @@
package holos
// Istio meshconfig
// TODO: Generate per-project extauthz providers.
_MeshConfig: {
accessLogEncoding: "JSON"
accessLogFile: "/dev/stdout"
defaultConfig: {
discoveryAddress: "istiod.istio-system.svc:15012"
tracing: zipkin: address: "zipkin.istio-system:9411"
}
defaultProviders: metrics: ["prometheus"]
enablePrometheusMerge: true
// For PROXY PROTOCOL at the ingress gateway.
gatewayTopology: {
numTrustedProxies: 2
}
rootNamespace: "istio-system"
trustDomain: "cluster.local"
extensionProviders: [{
name: "cluster-trace"
zipkin: {
maxTagLength: 56
port: 9411
service: "zipkin.istio-system.svc"
}
}, {
name: "cluster-gatekeeper"
envoyExtAuthzHttp: {
headersToDownstreamOnDeny: [
"content-type",
"set-cookie",
]
headersToUpstreamOnAllow: [
"authorization",
"path",
"x-auth-request-user",
"x-auth-request-email",
"x-auth-request-access-token",
]
includeAdditionalHeadersInCheck: "X-Auth-Request-Redirect": "%REQ(x-forwarded-proto)%://%REQ(:authority)%%REQ(:path)%%REQ(:query)%"
includeRequestHeadersInCheck: [
"authorization",
"cookie",
"x-forwarded-for",
]
port: 4180
service: "oauth2-proxy.istio-ingress.svc.cluster.local"
}
}, {
name: "core-authorizer"
envoyExtAuthzHttp: {
headersToDownstreamOnDeny: [
"content-type",
"set-cookie",
]
headersToUpstreamOnAllow: [
"authorization",
"path",
"x-auth-request-user",
"x-auth-request-email",
"x-auth-request-access-token",
]
includeAdditionalHeadersInCheck: "X-Auth-Request-Redirect": "%REQ(x-forwarded-proto)%://%REQ(:authority)%%REQ(:path)%%REQ(:query)%"
includeRequestHeadersInCheck: [
"authorization",
"cookie",
"x-forwarded-for",
]
port: 4180
service: "oauth2-proxy.prod-core-system.svc.cluster.local"
}
}]
}

View File

@@ -0,0 +1,161 @@
package holos
// Default values.yaml imported from the cni chart
#CNIValues: {
cni: {
hub: ""
tag: ""
variant: ""
image: "install-cni"
pullPolicy: ""
// Refer to https://istio.io/latest/docs/setup/additional-setup/cni/#installing-with-helm
enabled: #IstioValues.istio_cni.enabled
// Configuration log level of istio-cni binary
// by default istio-cni send all logs to UDS server
// if want to see them you need change global.logging.level with cni:debug
logLevel: "debug"
// Configuration file to insert istio-cni plugin configuration
// by default this will be the first file found in the cni-conf-dir
// Example
// cniConfFileName: 10-calico.conflist
// CNI bin and conf dir override settings
// defaults:
cniBinDir: "" // Auto-detected based on version; defaults to /opt/cni/bin.
cniConfDir: "/etc/cni/net.d"
cniConfFileName: ""
// This directory must exist on the node, if it does not, consult your container runtime
// documentation for the appropriate path.
cniNetnsDir: null // Defaults to '/var/run/netns', in minikube/docker/others can be '/var/run/docker/netns'.
excludeNamespaces: [
"istio-system",
"kube-system",
]
// Allows user to set custom affinity for the DaemonSet
affinity: {}
// Custom annotations on pod level, if you need them
podAnnotations: {}
// If this value is set a RoleBinding will be created
// in the same namespace as the istio-cni DaemonSet is created.
// This can be used to bind a preexisting ClusterRole to the istio/cni ServiceAccount
// e.g. if you use PodSecurityPolicies
psp_cluster_role: ""
// Deploy the config files as plugin chain (value "true") or as standalone files in the conf dir (value "false")?
// Some k8s flavors (e.g. OpenShift) do not support the chain approach, set to false if this is the case
chained: #IstioValues.istio_cni.chained
// Allow the istio-cni container to run in privileged mode, needed for some platforms (e.g. OpenShift) or features (repairPods)
privileged: false
// Custom configuration happens based on the CNI provider.
// Possible values: "default", "multus"
provider: "default"
// Configure ambient settings
ambient: {
// If enabled, ambient redirection will be enabled
enabled: false
// Set ambient redirection mode: "iptables" or "ebpf"
redirectMode: "iptables"
// Set ambient config dir path: defaults to /etc/ambient-config
configDir: ""
}
repair: {
enabled: true
hub: ""
tag: ""
// Repair controller has 3 modes. Pick which one meets your use cases. Note only one may be used.
// This defines the action the controller will take when a pod is detected as broken.
// labelPods will label all pods with <brokenPodLabelKey>=<brokenPodLabelValue>.
// This is only capable of identifying broken pods; the user is responsible for fixing them (generally, by deleting them).
labelPods: false
// deletePods will delete any broken pod. These will then be rescheduled, hopefully onto a node that is fully ready.
deletePods: true
// repairPods will dynamically repair any broken pod by setting up the pod networking configuration even after it has started.
// Note the pod will be crashlooping, so this may take a few minutes to become fully functional based on when the retry occurs.
// This requires no RBAC privilege, but does require `securityContext.privileged`.
repairPods: false
initContainerName: "istio-validation"
brokenPodLabelKey: "cni.istio.io/uninitialized"
brokenPodLabelValue: "true"
}
// Set to `type: RuntimeDefault` to use the default profile if available.
seccompProfile: {}
resources: requests: {
cpu: "100m"
memory: "100Mi"
}
resourceQuotas: {
enabled: false
pods: 5000
}
// The number of pods that can be unavailable during rolling update (see
// `updateStrategy.rollingUpdate.maxUnavailable` here:
// https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/daemon-set-v1/#DaemonSetSpec).
// May be specified as a number of pods or as a percent of the total number
// of pods at the start of the update.
rollingMaxUnavailable: 1
}
// Revision is set as 'version' label and part of the resource names when installing multiple control planes.
revision: ""
// For Helm compatibility.
ownerName: ""
global: {
// Default hub for Istio images.
// Releases are published to docker hub under 'istio' project.
// Dev builds from prow are on gcr.io
hub: "docker.io/istio"
// Default tag for Istio images.
tag: "1.20.3"
// Variant of the image to use.
// Currently supported are: [debug, distroless]
variant: ""
// Specify image pull policy if default behavior isn't desired.
// Default behavior: latest images will be Always else IfNotPresent.
imagePullPolicy: ""
// change cni scope level to control logging out of istio-cni-node DaemonSet
logging: {
level: "default:info,cni:info"
}
logAsJson: false
// ImagePullSecrets for all ServiceAccount, list of secrets in the same namespace
// to use for pulling any images in pods that reference this ServiceAccount.
// For components that don't use ServiceAccounts (i.e. grafana, servicegraph, tracing)
// ImagePullSecrets will be added to the corresponding Deployment(StatefulSet) objects.
// Must be set for any cluster configured with private docker registry.
imagePullSecrets: []
// - private-registry-key
// Default resources allocated
defaultResources: {
requests: {
cpu: "100m"
memory: "100Mi"
}
}
}
}

View File

@@ -0,0 +1,170 @@
package holos
// Gateway default values.yaml imported from the gateway chart.
#GatewayValues: {
// Name allows overriding the release name. Generally this should not be set
name: "istio-ingressgateway"
// revision declares which revision this gateway is a part of
revision: ""
// Controls the spec.replicas setting for the Gateway deployment if set.
// Otherwise defaults to Kubernetes Deployment default (1).
replicaCount: null
kind: "Deployment"
rbac: {
// If enabled, roles will be created to enable accessing certificates from Gateways. This is not needed
// when using http://gateway-api.org/.
enabled: true
}
serviceAccount: {
// If set, a service account will be created. Otherwise, the default is used
create: true
// Annotations to add to the service account
annotations: {}
// The name of the service account to use.
// If not set, the release name is used
name: ""
}
podAnnotations: {
"prometheus.io/port": "15020"
"prometheus.io/scrape": "true"
"prometheus.io/path": "/stats/prometheus"
"inject.istio.io/templates": "gateway"
"sidecar.istio.io/inject": "true"
...
}
// Define the security context for the pod.
// If unset, this will be automatically set to the minimum privileges required to bind to port 80 and 443.
// On Kubernetes 1.22+, this only requires the `net.ipv4.ip_unprivileged_port_start` sysctl.
securityContext: {
seccompProfile: type: "RuntimeDefault"
sysctls: [{name: "net.ipv4.ip_unprivileged_port_start", value: "0"}]
}
containerSecurityContext: null
service: {
// Type of service. Set to "None" to disable the service entirely
type: string | *"LoadBalancer"
ports: [...] | *[{
name: "status-port"
port: 15021
protocol: "TCP"
targetPort: 15021
}, {
name: "http2"
port: 80
protocol: "TCP"
targetPort: 80
}, {
name: "https"
port: 443
protocol: "TCP"
targetPort: 443
}]
annotations: {...}
loadBalancerIP: ""
loadBalancerSourceRanges: []
externalTrafficPolicy: string | *""
externalIPs: []
ipFamilyPolicy: ""
ipFamilies: []
}
resources: {
requests: {
cpu: "100m"
memory: "128Mi"
}
limits: {
cpu: "2000m"
memory: "1024Mi"
}
}
autoscaling: {
enabled: true
minReplicas: 1
maxReplicas: 5
targetCPUUtilizationPercentage: 80
autoscaleBehavior: {}
}
// Pod environment variables
env: {}
// Labels to apply to all resources
labels: {}
// Annotations to apply to all resources
annotations: {}
nodeSelector: {}
tolerations: []
topologySpreadConstraints: []
affinity: {}
// If specified, the gateway will act as a network gateway for the given network.
networkGateway: ""
// Specify image pull policy if default behavior isn't desired.
// Default behavior: latest images will be Always else IfNotPresent
imagePullPolicy: ""
imagePullSecrets: []
// This value is used to configure a Kubernetes PodDisruptionBudget for the gateway.
//
// By default, the `podDisruptionBudget` is disabled (set to `{}`),
// which means that no PodDisruptionBudget resource will be created.
//
// To enable the PodDisruptionBudget, configure it by specifying the
// `minAvailable` or `maxUnavailable`. For example, to set the
// minimum number of available replicas to 1, you can update this value as follows:
//
// podDisruptionBudget:
// minAvailable: 1
//
// Or, to allow a maximum of 1 unavailable replica, you can set:
//
// podDisruptionBudget:
// maxUnavailable: 1
//
// You can also specify the `unhealthyPodEvictionPolicy` field, and the valid values are `IfHealthyBudget` and `AlwaysAllow`.
// For example, to set the `unhealthyPodEvictionPolicy` to `AlwaysAllow`, you can update this value as follows:
//
// podDisruptionBudget:
// minAvailable: 1
// unhealthyPodEvictionPolicy: AlwaysAllow
//
// To disable the PodDisruptionBudget, you can leave it as an empty object `{}`:
//
// podDisruptionBudget: {}
//
podDisruptionBudget: {}
terminationGracePeriodSeconds: 30
// A list of `Volumes` added into the Gateway Pods. See
// https://kubernetes.io/docs/concepts/storage/volumes/.
volumes: []
// A list of `VolumeMounts` added into the Gateway Pods. See
// https://kubernetes.io/docs/concepts/storage/volumes/.
volumeMounts: []
// Configure this to a higher priority class in order to make sure your Istio gateway pods
// will not be killed because of low priority class.
// Refer to https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass
// for more detail.
priorityClassName: ""
}

View File

@@ -4,9 +4,11 @@ package holos
#InputKeys: project: "mesh"
// Shared dependencies for all components in this collection.
#Kustomization: spec: targetNamespace: #TargetNamespace
#DependsOn: _Namespaces
// Common Dependencies
_CertManager: CertManager: name: "\(#InstancePrefix)-certmanager"
_Namespaces: Namespaces: name: "\(#StageName)-secrets-namespaces"
_CertManager: CertManager: name: "\(#InstancePrefix)-certmanager"
_Namespaces: Namespaces: name: "\(#StageName)-secrets-namespaces"
_IstioBase: IstioBase: name: "\(#InstancePrefix)-istio-base"
_IstioD: IstioD: name: "\(#InstancePrefix)-istiod"
_IngressGateway: IngressGateway: name: "\(#InstancePrefix)-ingress"

View File

@@ -0,0 +1,547 @@
package holos
// Default istio values from the istiod chart using cue import values.yaml
#IstioValues: {
// Discovery Settings
pilot: {
autoscaleEnabled: true
autoscaleMin: 1
autoscaleMax: 5
autoscaleBehavior: {}
replicaCount: 1
rollingMaxSurge: "100%"
rollingMaxUnavailable: "25%"
hub: string | *""
tag: string | *""
variant: string | *""
// Can be a full hub/image:tag
image: "pilot"
traceSampling: 1.0
// Resources for a small pilot install
resources: {
requests: {
cpu: "500m"
memory: "2048Mi"
}
}
// Set to `type: RuntimeDefault` to use the default profile if available.
seccompProfile: {...}
// Additional container arguments
extraContainerArgs: []
env: {}
cpu: targetAverageUtilization: 80
// Additional volumeMounts to the istiod container
volumeMounts: []
// Additional volumes to the istiod pod
volumes: []
nodeSelector: {}
podAnnotations: {}
serviceAnnotations: {}
topologySpreadConstraints: []
// You can use jwksResolverExtraRootCA to provide a root certificate
// in PEM format. This will then be trusted by pilot when resolving
// JWKS URIs.
jwksResolverExtraRootCA: ""
// This is used to set the source of configuration for
// the associated address in configSource, if nothing is specified
// the default MCP is assumed.
configSource: {
subscribedResources: []
}
plugins: []
// The following is used to limit how long a sidecar can be connected
// to a pilot. It balances out load across pilot instances at the cost of
// increasing system churn.
keepaliveMaxServerConnectionAge: "30m"
// Additional labels to apply to the deployment.
deploymentLabels: {}
//# Mesh config settings
// Install the mesh config map, generated from values.yaml.
// If false, pilot wil use default values (by default) or user-supplied values.
configMap: *true | false
// Additional labels to apply on the pod level for monitoring and logging configuration.
podLabels: {}
// Setup how istiod Service is configured. See https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services
ipFamilyPolicy: ""
ipFamilies: []
}
sidecarInjectorWebhook: {
// You can use the field called alwaysInjectSelector and neverInjectSelector which will always inject the sidecar or
// always skip the injection on pods that match that label selector, regardless of the global policy.
// See https://istio.io/docs/setup/kubernetes/additional-setup/sidecar-injection/#more-control-adding-exceptions
neverInjectSelector: []
alwaysInjectSelector: []
// injectedAnnotations are additional annotations that will be added to the pod spec after injection
// This is primarily to support PSP annotations. For example, if you defined a PSP with the annotations:
//
// annotations:
// apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
// apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
//
// The PSP controller would add corresponding annotations to the pod spec for each container. However, this happens before
// the inject adds additional containers, so we must specify them explicitly here. With the above example, we could specify:
// injectedAnnotations:
// container.apparmor.security.beta.kubernetes.io/istio-init: runtime/default
// container.apparmor.security.beta.kubernetes.io/istio-proxy: runtime/default
injectedAnnotations: {}
// This enables injection of sidecar in all namespaces,
// with the exception of namespaces with "istio-injection:disabled" annotation
// Only one environment should have this enabled.
enableNamespacesByDefault: false
// Mutations that occur after the sidecar injector are not handled by default, as the Istio sidecar injector is only run
// once. For example, an OPA sidecar injected after the Istio sidecar will not have it's liveness/readiness probes rewritten.
// Setting this to `IfNeeded` will result in the sidecar injector being run again if additional mutations occur.
reinvocationPolicy: "Never"
rewriteAppHTTPProbe: true
// Templates defines a set of custom injection templates that can be used. For example, defining:
//
// templates:
// hello: |
// metadata:
// labels:
// hello: world
//
// Then starting a pod with the `inject.istio.io/templates: hello` annotation, will result in the pod
// being injected with the hello=world labels.
// This is intended for advanced configuration only; most users should use the built in template
templates: {}
// Default templates specifies a set of default templates that are used in sidecar injection.
// By default, a template `sidecar` is always provided, which contains the template of default sidecar.
// To inject other additional templates, define it using the `templates` option, and add it to
// the default templates list.
// For example:
//
// templates:
// hello: |
// metadata:
// labels:
// hello: world
//
// defaultTemplates: ["sidecar", "hello"]
defaultTemplates: []
}
istiodRemote: {
// Sidecar injector mutating webhook configuration clientConfig.url value.
// For example: https://$remotePilotAddress:15017/inject
// The host should not refer to a service running in the cluster; use a service reference by specifying
// the clientConfig.service field instead.
injectionURL: ""
// Sidecar injector mutating webhook configuration path value for the clientConfig.service field.
// Override to pass env variables, for example: /inject/cluster/remote/net/network2
injectionPath: "/inject"
}
telemetry: {
enabled: true
v2: {
// For Null VM case now.
// This also enables metadata exchange.
enabled: true
metadataExchange: {
// Indicates whether to enable WebAssembly runtime for metadata exchange filter.
wasmEnabled: false
}
// Indicate if prometheus stats filter is enabled or not
prometheus: {
enabled: true
// Indicates whether to enable WebAssembly runtime for stats filter.
wasmEnabled: false
// overrides stats EnvoyFilter configuration.
configOverride: {
gateway: {}
inboundSidecar: {}
outboundSidecar: {}
}
}
// stackdriver filter settings.
stackdriver: {
enabled: false
logging: false
monitoring: false
topology: false // deprecated. setting this to true will have no effect, as this option is no longer supported.
disableOutbound: false
// configOverride parts give you the ability to override the low level configuration params passed to envoy filter.
configOverride: {}
}
// e.g.
// disable_server_access_logging: false
// disable_host_header_fallback: true
// Access Log Policy Filter Settings. This enables filtering of access logs from stackdriver.
accessLogPolicy: {
enabled: false
// To reduce the number of successful logs, default log window duration is
// set to 12 hours.
logWindowDuration: "43200s"
}
}
}
// Revision is set as 'version' label and part of the resource names when installing multiple control planes.
revision: ""
// Revision tags are aliases to Istio control plane revisions
revisionTags: []
// For Helm compatibility.
ownerName: ""
// meshConfig defines runtime configuration of components, including Istiod and istio-agent behavior
// See https://istio.io/docs/reference/config/istio.mesh.v1alpha1/ for all available options
meshConfig: {
enablePrometheusMerge: true
}
global: {
// Used to locate istiod.
istioNamespace: "istio-system"
// List of cert-signers to allow "approve" action in the istio cluster role
//
// certSigners:
// - clusterissuers.cert-manager.io/istio-ca
certSigners: []
// enable pod disruption budget for the control plane, which is used to
// ensure Istio control plane components are gradually upgraded or recovered.
defaultPodDisruptionBudget: {
enabled: true
}
// The values aren't mutable due to a current PodDisruptionBudget limitation
// minAvailable: 1
// A minimal set of requested resources to applied to all deployments so that
// Horizontal Pod Autoscaler will be able to function (if set).
// Each component can overwrite these default values by adding its own resources
// block in the relevant section below and setting the desired resources values.
defaultResources: {
requests: cpu: "10m"
}
// memory: 128Mi
// limits:
// cpu: 100m
// memory: 128Mi
// Default hub for Istio images.
// Releases are published to docker hub under 'istio' project.
// Dev builds from prow are on gcr.io
hub: string | *"docker.io/istio"
// Default tag for Istio images.
tag: string | *"1.20.3"
// Variant of the image to use.
// Currently supported are: [debug, distroless]
variant: string | *""
// Specify image pull policy if default behavior isn't desired.
// Default behavior: latest images will be Always else IfNotPresent.
imagePullPolicy: string | *""
// ImagePullSecrets for all ServiceAccount, list of secrets in the same namespace
// to use for pulling any images in pods that reference this ServiceAccount.
// For components that don't use ServiceAccounts (i.e. grafana, servicegraph, tracing)
// ImagePullSecrets will be added to the corresponding Deployment(StatefulSet) objects.
// Must be set for any cluster configured with private docker registry.
imagePullSecrets: []
// - private-registry-key
// Enabled by default in master for maximising testing.
istiod: {
enableAnalysis: false
}
// To output all istio components logs in json format by adding --log_as_json argument to each container argument
logAsJson: false
// Comma-separated minimum per-scope logging level of messages to output, in the form of <scope>:<level>,<scope>:<level>
// The control plane has different scopes depending on component, but can configure default log level across all components
// If empty, default scope and level will be used as configured in code
logging: {
level: "default:info"
}
omitSidecarInjectorConfigMap: false
// Whether to restrict the applications namespace the controller manages;
// If not set, controller watches all namespaces
oneNamespace: false
// Configure whether Operator manages webhook configurations. The current behavior
// of Istiod is to manage its own webhook configurations.
// When this option is set as true, Istio Operator, instead of webhooks, manages the
// webhook configurations. When this option is set as false, webhooks manage their
// own webhook configurations.
operatorManageWebhooks: false
// Custom DNS config for the pod to resolve names of services in other
// clusters. Use this to add additional search domains, and other settings.
// see
// https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#dns-config
// This does not apply to gateway pods as they typically need a different
// set of DNS settings than the normal application pods (e.g., in
// multicluster scenarios).
// NOTE: If using templates, follow the pattern in the commented example below.
//podDNSSearchNamespaces:
//- global
//- "{{ valueOrDefault .DeploymentMeta.Namespace \"default\" }}.global"
// Kubernetes >=v1.11.0 will create two PriorityClass, including system-cluster-critical and
// system-node-critical, it is better to configure this in order to make sure your Istio pods
// will not be killed because of low priority class.
// Refer to https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass
// for more detail.
priorityClassName: ""
proxy: {
image: "proxyv2"
// This controls the 'policy' in the sidecar injector.
autoInject: "enabled"
// CAUTION: It is important to ensure that all Istio helm charts specify the same clusterDomain value
// cluster domain. Default value is "cluster.local".
clusterDomain: "cluster.local"
// Per Component log level for proxy, applies to gateways and sidecars. If a component level is
// not set, then the global "logLevel" will be used.
componentLogLevel: "misc:error"
// If set, newly injected sidecars will have core dumps enabled.
enableCoreDump: false
// istio ingress capture allowlist
// examples:
// Redirect only selected ports: --includeInboundPorts="80,8080"
excludeInboundPorts: ""
includeInboundPorts: "*"
// istio egress capture allowlist
// https://istio.io/docs/tasks/traffic-management/egress.html#calling-external-services-directly
// example: includeIPRanges: "172.30.0.0/16,172.20.0.0/16"
// would only capture egress traffic on those two IP Ranges, all other outbound traffic would
// be allowed by the sidecar
includeIPRanges: "*"
excludeIPRanges: ""
includeOutboundPorts: ""
excludeOutboundPorts: ""
// Log level for proxy, applies to gateways and sidecars.
// Expected values are: trace|debug|info|warning|error|critical|off
logLevel: "warning"
//If set to true, istio-proxy container will have privileged securityContext
privileged: false
// The number of successive failed probes before indicating readiness failure.
readinessFailureThreshold: 4
// The initial delay for readiness probes in seconds.
readinessInitialDelaySeconds: 0
// The period between readiness probes.
readinessPeriodSeconds: 15
// Enables or disables a startup probe.
// For optimal startup times, changing this should be tied to the readiness probe values.
//
// If the probe is enabled, it is recommended to have delay=0s,period=15s,failureThreshold=4.
// This ensures the pod is marked ready immediately after the startup probe passes (which has a 1s poll interval),
// and doesn't spam the readiness endpoint too much
//
// If the probe is disabled, it is recommended to have delay=1s,period=2s,failureThreshold=30.
// This ensures the startup is reasonable fast (polling every 2s). 1s delay is used since the startup is not often ready instantly.
startupProbe: {
enabled: true
failureThreshold: 600
} // 10 minutes
// Resources for the sidecar.
resources: {
requests: {
cpu: "100m"
memory: "128Mi"
}
limits: {
cpu: "2000m"
memory: "1024Mi"
}
}
// Default port for Pilot agent health checks. A value of 0 will disable health checking.
statusPort: 15020
// Specify which tracer to use. One of: zipkin, lightstep, datadog, stackdriver.
// If using stackdriver tracer outside GCP, set env GOOGLE_APPLICATION_CREDENTIALS to the GCP credential file.
tracer: "zipkin"
}
proxy_init: {
// Base name for the proxy_init container, used to configure iptables.
image: "proxyv2"
}
// configure remote pilot and istiod service and endpoint
remotePilotAddress: ""
//#############################################################################################
// The following values are found in other charts. To effectively modify these values, make #
// make sure they are consistent across your Istio helm charts #
//#############################################################################################
// The customized CA address to retrieve certificates for the pods in the cluster.
// CSR clients such as the Istio Agent and ingress gateways can use this to specify the CA endpoint.
// If not set explicitly, default to the Istio discovery address.
caAddress: ""
// Configure a remote cluster data plane controlled by an external istiod.
// When set to true, istiod is not deployed locally and only a subset of the other
// discovery charts are enabled.
externalIstiod: false
// Configure a remote cluster as the config cluster for an external istiod.
configCluster: false
// Configure the policy for validating JWT.
// Currently, two options are supported: "third-party-jwt" and "first-party-jwt".
jwtPolicy: "third-party-jwt"
// Mesh ID means Mesh Identifier. It should be unique within the scope where
// meshes will interact with each other, but it is not required to be
// globally/universally unique. For example, if any of the following are true,
// then two meshes must have different Mesh IDs:
// - Meshes will have their telemetry aggregated in one place
// - Meshes will be federated together
// - Policy will be written referencing one mesh from the other
//
// If an administrator expects that any of these conditions may become true in
// the future, they should ensure their meshes have different Mesh IDs
// assigned.
//
// Within a multicluster mesh, each cluster must be (manually or auto)
// configured to have the same Mesh ID value. If an existing cluster 'joins' a
// multicluster mesh, it will need to be migrated to the new mesh ID. Details
// of migration TBD, and it may be a disruptive operation to change the Mesh
// ID post-install.
//
// If the mesh admin does not specify a value, Istio will use the value of the
// mesh's Trust Domain. The best practice is to select a proper Trust Domain
// value.
meshID: ""
// Configure the mesh networks to be used by the Split Horizon EDS.
//
// The following example defines two networks with different endpoints association methods.
// For `network1` all endpoints that their IP belongs to the provided CIDR range will be
// mapped to network1. The gateway for this network example is specified by its public IP
// address and port.
// The second network, `network2`, in this example is defined differently with all endpoints
// retrieved through the specified Multi-Cluster registry being mapped to network2. The
// gateway is also defined differently with the name of the gateway service on the remote
// cluster. The public IP for the gateway will be determined from that remote service (only
// LoadBalancer gateway service type is currently supported, for a NodePort type gateway service,
// it still need to be configured manually).
//
// meshNetworks:
// network1:
// endpoints:
// - fromCidr: "192.168.0.1/24"
// gateways:
// - address: 1.1.1.1
// port: 80
// network2:
// endpoints:
// - fromRegistry: reg1
// gateways:
// - registryServiceName: istio-ingressgateway.istio-system.svc.cluster.local
// port: 443
//
meshNetworks: {}
// Use the user-specified, secret volume mounted key and certs for Pilot and workloads.
mountMtlsCerts: false
multiCluster: {
// Set to true to connect two kubernetes clusters via their respective
// ingressgateway services when pods in each cluster cannot directly
// talk to one another. All clusters should be using Istio mTLS and must
// have a shared root CA for this model to work.
enabled: false
// Should be set to the name of the cluster this installation will run in. This is required for sidecar injection
// to properly label proxies
clusterName: ""
}
// Network defines the network this cluster belong to. This name
// corresponds to the networks in the map of mesh networks.
network: ""
// Configure the certificate provider for control plane communication.
// Currently, two providers are supported: "kubernetes" and "istiod".
// As some platforms may not have kubernetes signing APIs,
// Istiod is the default
pilotCertProvider: "istiod"
sds: {
// The JWT token for SDS and the aud field of such JWT. See RFC 7519, section 4.1.3.
// When a CSR is sent from Istio Agent to the CA (e.g. Istiod), this aud is to make sure the
// JWT is intended for the CA.
token: {
aud: "istio-ca"
}
}
sts: {
// The service port used by Security Token Service (STS) server to handle token exchange requests.
// Setting this port to a non-zero value enables STS server.
servicePort: 0
}
// The name of the CA for workload certificates.
// For example, when caName=GkeWorkloadCertificate, GKE workload certificates
// will be used as the certificates for workloads.
// The default value is "" and when caName="", the CA will be configured by other
// mechanisms (e.g., environmental variable CA_PROVIDER).
caName: ""
// whether to use autoscaling/v2 template for HPA settings
// for internal usage only, not to be configured by users.
autoscalingv2API: true
}
base: {
// For istioctl usage to disable istio config crds in base
enableIstioConfigCRDs: true
// If enabled, gateway-api types will be validated using the standard upstream validation logic.
// This is an alternative to deploying the standalone validation server the project provides.
// This is disabled by default, as the cluster may already have a validation server; while technically
// it works to have multiple redundant validations, this adds complexity and operational risks.
// Users should consider enabling this if they want full gateway-api validation but don't have other validation servers.
validateGateway: false
}
// keep in sync with settings used when installing the Istio CNI chart
istio_cni: {
// Refer to https://istio.io/latest/docs/setup/additional-setup/cni/#installing-with-helm
// values.istio_cni.enabled should be set to the same value as values.cni.enabled.
// values.istio_cni.chained should be set to the same value as values.cni.chained.
enabled: true
chained: true
}
}

View File

@@ -0,0 +1,28 @@
package holos
#IstioValues: {
global: {
// Used to locate istiod.
istioNamespace: "istio-system"
// Switch the hub away from the default docker.io to avoid rate limits
hub: "gcr.io/istio-release"
// ImagePullSecrets for control plane ServiceAccount, list of secrets in the same namespace
// to use for pulling any images in pods that reference this ServiceAccount.
// Must be set for any cluster configured with private docker registry.
imagePullSecrets: []
istiod: enableAnalysis: false
configValidation: true
externalIstiod: false
remotePilotAddress: ""
}
base: {
// Include the CRDs in the helm template output
enableCRDTemplates: true
// Validation webhook configuration url
// For example: https://$remotePilotAddress:15017/validate
validationURL: ""
// For istioctl usage to disable istio config crds in base
enableIstioConfigCRDs: true
}
defaultRevision: "default"
}

View File

@@ -1,6 +1,14 @@
package holos
let Privileged = {labels: "pod-security.kubernetes.io/enforce": "privileged"}
// Refer to https://kubernetes.io/docs/concepts/security/pod-security-standards/
let Restricted = {
labels: "pod-security.kubernetes.io/enforce": "restricted"
labels: "pod-security.kubernetes.io/enforce-version": "latest"
}
let Privileged = {
labels: "pod-security.kubernetes.io/enforce": "privileged"
labels: "pod-security.kubernetes.io/enforce-version": "latest"
}
// #PlatformNamespaces is the union of all namespaces across all cluster types. Namespaces are created in all clusters regardless of if they're
// used within the cluster or not. The is important for security and consistency with IAM, RBAC, and Secrets sync between clusters.
@@ -10,7 +18,8 @@ let Privileged = {labels: "pod-security.kubernetes.io/enforce": "privileged"}
{name: "flux-system"},
{name: "ceph-system"} & Privileged,
{name: "istio-system"} & Privileged,
{name: "istio-ingress"} & Privileged,
{name: "istio-ingress"} & Restricted,
{name: "cert-manager"},
{name: "argocd"},
{name: "prod-iam-zitadel"},
]

View File

@@ -3,15 +3,23 @@ package holos
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ksv1 "kustomize.toolkit.fluxcd.io/kustomization/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
batchv1 "k8s.io/api/batch/v1"
es "external-secrets.io/externalsecret/v1beta1"
ss "external-secrets.io/secretstore/v1beta1"
cm "cert-manager.io/clusterissuer/v1"
is "cert-manager.io/issuer/v1"
ci "cert-manager.io/clusterissuer/v1"
crt "cert-manager.io/certificate/v1"
gw "networking.istio.io/gateway/v1beta1"
vs "networking.istio.io/virtualservice/v1beta1"
kc "sigs.k8s.io/kustomize/api/types"
"encoding/yaml"
)
let ResourcesFile = "resources.yaml"
// _apiVersion is the version of this schema. Defines the interface between CUE output and the holos cli.
_apiVersion: "holos.run/v1alpha1"
@@ -36,11 +44,17 @@ _apiVersion: "holos.run/v1alpha1"
// #TargetNamespace is the target namespace for a holos component.
#TargetNamespace: string
// #SelectorLabels are mixed into selectors.
#SelectorLabels: {
"holos.run/stage.name": #StageName
"holos.run/project.name": #CollectionName
"holos.run/component.name": #ComponentName
...
}
// #CommonLabels are mixed into every kubernetes api object.
#CommonLabels: {
"holos.run/stage.name": #StageName
"holos.run/project.name": #CollectionName
"holos.run/component.name": #ComponentName
#SelectorLabels
"app.kubernetes.io/part-of": #StageName
"app.kubernetes.io/name": #CollectionName
"app.kubernetes.io/component": #ComponentName
@@ -49,14 +63,26 @@ _apiVersion: "holos.run/v1alpha1"
}
#ClusterObject: {
_description: string | *""
metadata: metav1.#ObjectMeta & {
labels: #CommonLabels
annotations: #Description & {
_Description: _description
...
}
}
...
}
#Description: {
_Description: string | *""
"holos.run/description": _Description
...
}
#NamespaceObject: #ClusterObject & {
metadata: namespace: string
...
}
// Kubernetes API Objects
@@ -68,14 +94,42 @@ _apiVersion: "holos.run/v1alpha1"
}
#ClusterRole: #ClusterObject & rbacv1.#ClusterRole
#ClusterRoleBinding: #ClusterObject & rbacv1.#ClusterRoleBinding
#ClusterIssuer: #ClusterObject & cm.#ClusterIssuer & {...}
#ClusterIssuer: #ClusterObject & ci.#ClusterIssuer & {...}
#Issuer: #NamespaceObject & is.#Issuer
#Role: #NamespaceObject & rbacv1.#Role
#RoleBinding: #NamespaceObject & rbacv1.#RoleBinding
#ConfigMap: #NamespaceObject & corev1.#ConfigMap
#ServiceAccount: #NamespaceObject & corev1.#ServiceAccount
#Pod: #NamespaceObject & corev1.#Pod
#Service: #NamespaceObject & corev1.#Service
#Job: #NamespaceObject & batchv1.#Job
#CronJob: #NamespaceObject & batchv1.#CronJob
#Deployment: #NamespaceObject & appsv1.#Deployment
#Gateway: #NamespaceObject & gw.#Gateway
#VirtualService: #NamespaceObject & vs.#VirtualService
#Certificate: #NamespaceObject & crt.#Certificate
// #HTTP01Cert defines a http01 certificate.
#HTTP01Cert: {
_name: string
_secret: string | *_name
SecretName: _secret
Host: _name + "." + #ClusterDomain
object: #Certificate & {
metadata: {
name: _secret
namespace: string | *#TargetNamespace
}
spec: {
commonName: Host
dnsNames: [Host]
secretName: _secret
issuerRef: kind: "ClusterIssuer"
issuerRef: name: "letsencrypt"
}
}
}
// Flux Kustomization CRDs
#Kustomization: #NamespaceObject & ksv1.#Kustomization & {
@@ -209,7 +263,7 @@ _apiVersion: "holos.run/v1alpha1"
}
}
// apiObjectsContent holds the marshalled representation of apiObjects
// apiObjectMap holds the marshalled representation of apiObjects
apiObjectMap: {
for kind, v in apiObjects {
"\(kind)": {
@@ -289,6 +343,10 @@ _apiVersion: "holos.run/v1alpha1"
platform: #Platform
// instance returns the key values of the holos component instance.
instance: #InputKeys
// resources is the intermediate file name for api objects.
resourcesFile: ResourcesFile
// kustomizeFiles represents the files in a kustomize directory tree.
kustomizeFiles: #KustomizeFiles.Files
}
// #PlatformSpec is the output schema of a platform specification.
@@ -300,6 +358,37 @@ _apiVersion: "holos.run/v1alpha1"
// #SecretName is the name of a Secret, ususally coupling a Deployment to an ExternalSecret
#SecretName: string
// Cluster Domain is the cluster specific domain
#ClusterDomain: #InputKeys.cluster + "." + #Platform.org.domain
// #SidecarInject represents the istio sidecar inject label
#IstioSidecar: {
"sidecar.istio.io/inject": "true"
...
}
// #KustomizeTree represents a kustomize build.
#KustomizeFiles: {
Objects: {
"kustomization.yaml": #Kustomize
}
// Files holds the marshaled output holos writes to the filesystem
Files: {
for filename, obj in Objects {
"\(filename)": yaml.Marshal(obj)
}
...
}
}
// kustomization.yaml
#Kustomize: kc.#Kustomization & {
apiVersion: "kustomize.config.k8s.io/v1beta1"
kind: "Kustomization"
resources: [ResourcesFile]
...
}
// By default, render kind: Skipped so holos knows to skip over intermediate cue files.
// This enables the use of holos render ./foo/bar/baz/... when bar contains intermediary constraints which are not complete components.
// Holos skips over these intermediary cue instances.

10
go.mod
View File

@@ -5,10 +5,14 @@ go 1.21.5
require (
cuelang.org/go v0.7.0
github.com/mattn/go-isatty v0.0.20
github.com/rogpeppe/go-internal v1.12.0
github.com/spf13/cobra v1.7.0
golang.org/x/tools v0.18.0
k8s.io/api v0.29.2
k8s.io/apimachinery v0.29.2
k8s.io/client-go v0.29.2
k8s.io/kubectl v0.29.2
sigs.k8s.io/yaml v1.4.0
)
require (
@@ -27,7 +31,7 @@ require (
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
@@ -41,7 +45,6 @@ require (
github.com/opencontainers/image-spec v1.1.0-rc4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/oauth2 v0.10.0 // indirect
@@ -54,12 +57,9 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.29.2 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
k8s.io/kubectl v0.29.2 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

11
go.sum
View File

@@ -46,8 +46,8 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJY
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -96,8 +96,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0 h1:sadMIsgmHpEOGbUs6VtHBXRR1OHevnj7hLx9ZcdNGW4=
github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c=
github.com/rogpeppe/go-internal v1.11.1-0.20231026093722-fa6a31e0812c h1:fPpdjePK1atuOg28PXfNSqgwf9I/qD1Hlo39JFwKBXk=
github.com/rogpeppe/go-internal v1.11.1-0.20231026093722-fa6a31e0812c/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -177,6 +175,7 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A=
@@ -197,5 +196,5 @@ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMm
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

View File

@@ -23,7 +23,7 @@ func makeBuildRunFunc(cfg *holos.Config) command.RunFunc {
if result.Skip {
continue
}
outs = append(outs, result.FinalOutput())
outs = append(outs, result.AccumulatedOutput())
}
out := strings.Join(outs, "---\n")
if _, err := fmt.Fprintln(cmd.OutOrStdout(), out); err != nil {

View File

@@ -32,7 +32,7 @@ func makeRenderRunFunc(cfg *holos.Config) command.RunFunc {
}
// API Objects
path := result.Filename(cfg.WriteTo(), cfg.ClusterName())
if err := result.Save(ctx, path, result.FinalOutput()); err != nil {
if err := result.Save(ctx, path, result.AccumulatedOutput()); err != nil {
return wrapper.Wrap(err)
}
// Kustomization

View File

@@ -2,10 +2,12 @@ package secret
import (
"context"
"encoding/json"
"fmt"
"github.com/holos-run/holos/pkg/cli/command"
"github.com/holos-run/holos/pkg/holos"
"github.com/holos-run/holos/pkg/logger"
"github.com/holos-run/holos/pkg/util"
"github.com/holos-run/holos/pkg/wrapper"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -90,17 +92,26 @@ func makeGetRunFunc(hc *holos.Config, cfg *config) command.RunFunc {
printFile := *cfg.printFile
if len(toExtract) == 0 {
if printFile == "" {
printFile = secretName
}
}
if printFile != "" {
if data, found := secret.Data[printFile]; found {
hc.Write(data)
} else {
err := fmt.Errorf("cannot print: want %s have %v: did you mean --extract-all or --%s=name", printFile, keys, printFlagName)
return wrapper.Wrap(err)
if printFile == "" { // print all data keys
data := make(map[string]string)
for k, v := range secret.Data {
data[k] = string(v)
}
b, err := json.MarshalIndent(data, "", " ")
if err != nil {
return wrapper.Wrap(err)
}
log.Info(fmt.Sprintf("len: %v", len(b)))
b = util.EnsureNewline(b)
log.Info(fmt.Sprintf("len: %v", len(b)))
hc.Write(b)
} else { // print named data keys keys
if data, found := secret.Data[printFile]; found {
hc.Write(data)
} else {
err := fmt.Errorf("cannot print: want %s have %v: did you mean --extract-all or --%s=name", printFile, keys, printFlagName)
return wrapper.Wrap(err)
}
}
}

View File

@@ -36,6 +36,30 @@ var secret = v1.Secret{
Type: "Opaque",
}
var loginSecret = v1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "zitadel-admin-d7fgbgbfbt",
Namespace: "secrets",
Labels: map[string]string{
"holos.run/owner.name": "jeff",
"holos.run/secret.name": "zitadel-admin",
},
CreationTimestamp: metav1.Time{
Time: time.Date(2021, time.January, 1, 0, 0, 0, 0, time.UTC),
},
},
Data: map[string][]byte{
"url": []byte("https://login.example.com"),
"username": []byte("zitadel-admin@zitadel.login.example.com"),
"password": []byte("Password1!"),
},
Type: "Opaque",
}
// cmdHolos executes the holos root command with a kubernetes.Interface that
// persists for the duration of the testscript. holos is NOT executed in a
// subprocess, the current working directory is not and should not be changed.
@@ -72,7 +96,7 @@ func TestSecrets(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testdata",
Setup: func(env *testscript.Env) error {
env.Values[clientsetKey] = fake.NewSimpleClientset(&secret)
env.Values[clientsetKey] = fake.NewSimpleClientset(&secret, &loginSecret)
return nil
},
Cmds: map[string]func(ts *testscript.TestScript, neg bool, args []string){

View File

@@ -17,6 +17,7 @@ import (
"os/exec"
"path/filepath"
"slices"
"strings"
"cuelang.org/go/cue/cuecontext"
"cuelang.org/go/cue/load"
@@ -81,13 +82,21 @@ type Metadata struct {
// holos cli. A map is used to improve the clarity of error messages from cue.
type apiObjectMap map[string]map[string]string
// fileContentMap is a map of file names to file contents.
type fileContentMap map[string]string
// Result is the build result for display or writing.
type Result struct {
Metadata Metadata `json:"metadata,omitempty"`
KsContent string `json:"ksContent,omitempty"`
APIObjectMap apiObjectMap `json:"apiObjectMap,omitempty"`
finalOutput string
Skip bool
Metadata Metadata `json:"metadata,omitempty"`
KsContent string `json:"ksContent,omitempty"`
// APIObjectMap holds the marshalled representation of api objects.
APIObjectMap apiObjectMap `json:"apiObjectMap,omitempty"`
accumulatedOutput string
Skip bool
// KustomizeFiles holds the files for a kustomize kustomization directory.
KustomizeFiles fileContentMap `json:"kustomizeFiles"`
// ResourcesFile is the file name used for api objects in kustomization.yaml
ResourcesFile string `json:"resourcesFile,omitempty"`
}
type Repository struct {
@@ -103,14 +112,15 @@ type Chart struct {
// A HelmChart represents a helm command to provide chart values in order to render kubernetes api objects.
type HelmChart struct {
APIVersion string `json:"apiVersion"`
Kind string `json:"kind"`
Metadata Metadata `json:"metadata"`
KsContent string `json:"ksContent"`
Namespace string `json:"namespace"`
Chart Chart `json:"chart"`
ValuesContent string `json:"valuesContent"`
APIObjectMap apiObjectMap `json:"APIObjectMap"`
APIVersion string `json:"apiVersion"`
Kind string `json:"kind"`
Metadata Metadata `json:"metadata"`
KsContent string `json:"ksContent"`
Namespace string `json:"namespace"`
Chart Chart `json:"chart"`
ValuesContent string `json:"valuesContent"`
// APIObjectMap holds the marshalled representation of api objects.
APIObjectMap apiObjectMap `json:"APIObjectMap"`
}
// Name returns the metadata name of the result. Equivalent to the
@@ -127,14 +137,14 @@ func (r *Result) KustomizationFilename(writeTo string, cluster string) string {
return filepath.Join(writeTo, "clusters", cluster, "holos", "components", r.Name()+"-kustomization.gen.yaml")
}
// FinalOutput returns the final rendered output.
func (r *Result) FinalOutput() string {
return r.finalOutput
// AccumulatedOutput returns the accumulated rendered output.
func (r *Result) AccumulatedOutput() string {
return r.accumulatedOutput
}
// addAPIObjects adds the overlay api objects to finalOutput.
// addAPIObjects adds the overlay api objects to accumulatedOutput.
func (r *Result) addOverlayObjects(log *slog.Logger) {
b := []byte(r.FinalOutput())
b := []byte(r.AccumulatedOutput())
kinds := make([]string, 0, len(r.APIObjectMap))
// Sort the keys
for kind := range r.APIObjectMap {
@@ -154,13 +164,64 @@ func (r *Result) addOverlayObjects(log *slog.Logger) {
for _, name := range names {
yamlString := v[name]
log.Debug(fmt.Sprintf("%s/%s", kind, name), "kind", kind, "name", name)
util.EnsureNewline(b)
b = util.EnsureNewline(b)
header := fmt.Sprintf("---\n# Source: CUE apiObjects.%s.%s\n", kind, name)
b = append(b, []byte(header+yamlString)...)
util.EnsureNewline(b)
b = util.EnsureNewline(b)
}
}
r.finalOutput = string(b)
r.accumulatedOutput = string(b)
}
// kustomize replaces the final output with the output of kustomize build if the
func (r *Result) kustomize(ctx context.Context) error {
log := logger.FromContext(ctx)
if r.ResourcesFile == "" {
log.DebugContext(ctx, "skipping kustomize: no resourcesFile")
return nil
}
if len(r.KustomizeFiles) < 1 {
log.DebugContext(ctx, "skipping kustomize: no kustomizeFiles")
return nil
}
tempDir, err := os.MkdirTemp("", "holos.kustomize")
if err != nil {
return wrapper.Wrap(err)
}
defer remove(ctx, tempDir)
// Write the main api object resources file for kustomize.
target := filepath.Join(tempDir, r.ResourcesFile)
b := []byte(r.AccumulatedOutput())
b = util.EnsureNewline(b)
if err := os.WriteFile(target, b, 0644); err != nil {
return wrapper.Wrap(fmt.Errorf("could not write resources: %w", err))
}
log.DebugContext(ctx, "wrote: "+target, "op", "write", "path", target, "bytes", len(b))
// Write the kustomization tree, kustomization.yaml must be in this map for kustomize to work.
for file, content := range r.KustomizeFiles {
target := filepath.Join(tempDir, file)
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
return wrapper.Wrap(err)
}
b := []byte(content)
b = util.EnsureNewline(b)
if err := os.WriteFile(target, b, 0644); err != nil {
return wrapper.Wrap(fmt.Errorf("could not write: %w", err))
}
log.DebugContext(ctx, "wrote: "+target, "op", "write", "path", target, "bytes", len(b))
}
// Run kustomize.
kOut, err := runCmd(ctx, "kubectl", "kustomize", tempDir)
if err != nil {
log.ErrorContext(ctx, kOut.stderr.String())
return wrapper.Wrap(err)
}
// Replace the accumulated output
r.accumulatedOutput = kOut.stdout.String()
return nil
}
// Save writes the content to the filesystem for git ops.
@@ -277,6 +338,9 @@ func (b *Builder) Run(ctx context.Context) (results []*Result, err error) {
return nil, err
}
result.addOverlayObjects(log)
if err := result.kustomize(ctx); err != nil {
return nil, wrapper.Wrap(fmt.Errorf("could not kustomize: %w", err))
}
default:
return nil, wrapper.Wrap(fmt.Errorf("build kind not implemented: %v", kind))
}
@@ -381,10 +445,17 @@ func runHelm(ctx context.Context, hc *HelmChart, r *Result, path holos.PathCompo
chart := hc.Chart
helmOut, err := runCmd(ctx, "helm", "template", "--values", valuesPath, "--namespace", hc.Namespace, "--kubeconfig", "/dev/null", "--version", chart.Version, chart.Name, cachedChartPath)
if err != nil {
stderr := helmOut.stderr.String()
lines := strings.Split(stderr, "\n")
for _, line := range lines {
if strings.HasPrefix(line, "Error:") {
err = fmt.Errorf("%s: %w", line, err)
}
}
return wrapper.Wrap(fmt.Errorf("could not run helm template: %w", err))
}
r.finalOutput = helmOut.stdout.String()
r.accumulatedOutput = helmOut.stdout.String()
return nil
}

View File

@@ -1 +1 @@
49
51

View File

@@ -1 +1 @@
0
1