add helm charts

This commit is contained in:
Ybehrooz
2025-11-09 13:22:40 +03:30
parent 282c3e52d0
commit 38e4d749ad
1352 changed files with 190457 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@@ -0,0 +1,6 @@
apiVersion: v2
appVersion: v2.1.2
description: A Helm chart for Kubernetes
name: zot
type: application
version: 0.1.66

View File

@@ -0,0 +1,71 @@
configFiles:
config.json: |-
{
"storage": { "rootDirectory": "/var/lib/registry" },
"http": {
"address": "0.0.0.0",
"port": "5000",
"auth": { "htpasswd": { "path": "/secret/htpasswd" } },
"accessControl": {
"repositories": {
"**": {
"policies": [{
"users": ["user"],
"actions": ["read"]
}],
"defaultPolicy": ["read"],
"anonymousPolicy": ["read"]
}
},
"adminPolicy": {
"users": ["admin"],
"actions": ["read", "create", "update", "delete"]
}
}
},
"log": { "level": "debug" }
"extensions": {
"ui": {
"enable": true
}
}
}
service:
type: NodePort
port: 5000
nodePort: 30516 # Set to a specific port if type is NodePort
# Annotations to add to the service
annotations: {}
# Set to a static IP if a static IP is desired, only works when
# type: ClusterIP
clusterIP: null
persistence: true
# PVC data, only used if persistence is 'true'
pvc:
# Make the chart create the PVC, this option is used with storageClasses that
# can create volumes dynamically, if that is not the case is better to do it
# manually and set create to false
create: true
# Name of the PVC to use or create if persistence is enabled, if not set the
# value '$CHART_RELEASE-pvc' is used
name: null
# Volume access mode, if using more than one replica we need
accessMode: "ReadWriteOnce"
# Size of the volume requested
storage: 100Gi
# Name of the storage class to use if it is different than the default one
storageClassName: null
mountSecret: true
# If secretFiles does not exist the user is in charge of managing it, again, if
# you want to manage it the value has to be added empty to avoid using this one
secretFiles:
# Example htpasswd with 'admin:admin' & 'user:user' user:pass pairs
htpasswd: |-
admin:$2y$05$vmiurPmJvHylk78HHFWuruFFVePlit9rZWGA/FbZfTEmNRneGJtha
user:$2y$05$L86zqQDfH5y445dcMlwu6uHv.oXFgT6AiJCwpv3ehr7idc0rI3S2G
nodeSelector:
node.name: node-1

View File

@@ -0,0 +1,71 @@
configFiles:
config.json: |-
{
"storage": { "rootDirectory": "/var/lib/registry" },
"http": {
"address": "0.0.0.0",
"port": "5000",
"auth": { "htpasswd": { "path": "/secret/htpasswd" } },
"accessControl": {
"repositories": {
"**": {
"policies": [{
"users": ["user"],
"actions": ["read"]
}],
"defaultPolicy": ["read"],
"anonymousPolicy": ["read"]
}
},
"adminPolicy": {
"users": ["admin"],
"actions": ["read", "create", "update", "delete"]
}
}
},
"log": { "level": "debug" }
"extensions": {
"ui": {
"enable": true
}
}
}
service:
type: NodePort
port: 5000
nodePort: null # Set to a specific port if type is NodePort
# Annotations to add to the service
annotations: {}
# Set to a static IP if a static IP is desired, only works when
# type: ClusterIP
clusterIP: null
persistence: true
# PVC data, only used if persistence is 'true'
pvc:
# Make the chart create the PVC, this option is used with storageClasses that
# can create volumes dynamically, if that is not the case is better to do it
# manually and set create to false
create: true
# Name of the PVC to use or create if persistence is enabled, if not set the
# value '$CHART_RELEASE-pvc' is used
name: null
# Volume access mode, if using more than one replica we need
accessMode: "ReadWriteOnce"
# Size of the volume requested
storage: 100Gi
# Name of the storage class to use if it is different than the default one
storageClassName: null
mountSecret: true
# If secretFiles does not exist the user is in charge of managing it, again, if
# you want to manage it the value has to be added empty to avoid using this one
secretFiles:
# Example htpasswd with 'admin:admin' & 'user:user' user:pass pairs
htpasswd: |-
admin:$2y$05$vmiurPmJvHylk78HHFWuruFFVePlit9rZWGA/FbZfTEmNRneGJtha
user:$2y$05$L86zqQDfH5y445dcMlwu6uHv.oXFgT6AiJCwpv3ehr7idc0rI3S2G
nodeSelector:
kubernetes.io/hostname: worker-02

View File

@@ -0,0 +1,71 @@
configFiles:
config.json: |-
{
"storage": { "rootDirectory": "/var/lib/registry" },
"http": {
"address": "0.0.0.0",
"port": "5000",
"auth": { "htpasswd": { "path": "/secret/htpasswd" } },
"accessControl": {
"repositories": {
"**": {
"policies": [{
"users": ["user"],
"actions": ["read"]
}],
"defaultPolicy": ["read"],
"anonymousPolicy": ["read"]
}
},
"adminPolicy": {
"users": ["admin"],
"actions": ["read", "create", "update", "delete"]
}
}
},
"log": { "level": "debug" }
"extensions": {
"ui": {
"enable": true
}
}
}
service:
type: NodePort
port: 5000
nodePort: 30516 # Set to a specific port if type is NodePort
# Annotations to add to the service
annotations: {}
# Set to a static IP if a static IP is desired, only works when
# type: ClusterIP
clusterIP: null
persistence: true
# PVC data, only used if persistence is 'true'
pvc:
# Make the chart create the PVC, this option is used with storageClasses that
# can create volumes dynamically, if that is not the case is better to do it
# manually and set create to false
create: true
# Name of the PVC to use or create if persistence is enabled, if not set the
# value '$CHART_RELEASE-pvc' is used
name: null
# Volume access mode, if using more than one replica we need
accessMode: "ReadWriteOnce"
# Size of the volume requested
storage: 100Gi
# Name of the storage class to use if it is different than the default one
storageClassName: null
mountSecret: true
# If secretFiles does not exist the user is in charge of managing it, again, if
# you want to manage it the value has to be added empty to avoid using this one
secretFiles:
# Example htpasswd with 'admin:admin' & 'user:user' user:pass pairs
htpasswd: |-
admin:$2y$05$vmiurPmJvHylk78HHFWuruFFVePlit9rZWGA/FbZfTEmNRneGJtha
user:$2y$05$L86zqQDfH5y445dcMlwu6uHv.oXFgT6AiJCwpv3ehr7idc0rI3S2G
nodeSelector:
node.name: node-01

View File

@@ -0,0 +1,71 @@
configFiles:
config.json: |-
{
"storage": { "rootDirectory": "/var/lib/registry" },
"http": {
"address": "0.0.0.0",
"port": "5000",
"auth": { "htpasswd": { "path": "/secret/htpasswd" } },
"accessControl": {
"repositories": {
"**": {
"policies": [{
"users": ["user"],
"actions": ["read"]
}],
"defaultPolicy": ["read"],
"anonymousPolicy": ["read"]
}
},
"adminPolicy": {
"users": ["admin"],
"actions": ["read", "create", "update", "delete"]
}
}
},
"log": { "level": "debug" }
"extensions": {
"ui": {
"enable": true
}
}
}
service:
type: NodePort
port: 5000
nodePort: 30516 # Set to a specific port if type is NodePort
# Annotations to add to the service
annotations: {}
# Set to a static IP if a static IP is desired, only works when
# type: ClusterIP
clusterIP: null
persistence: true
# PVC data, only used if persistence is 'true'
pvc:
# Make the chart create the PVC, this option is used with storageClasses that
# can create volumes dynamically, if that is not the case is better to do it
# manually and set create to false
create: true
# Name of the PVC to use or create if persistence is enabled, if not set the
# value '$CHART_RELEASE-pvc' is used
name: null
# Volume access mode, if using more than one replica we need
accessMode: "ReadWriteOnce"
# Size of the volume requested
storage: 100Gi
# Name of the storage class to use if it is different than the default one
storageClassName: null
mountSecret: true
# If secretFiles does not exist the user is in charge of managing it, again, if
# you want to manage it the value has to be added empty to avoid using this one
secretFiles:
# Example htpasswd with 'admin:admin' & 'user:user' user:pass pairs
htpasswd: |-
admin:$2y$05$vmiurPmJvHylk78HHFWuruFFVePlit9rZWGA/FbZfTEmNRneGJtha
user:$2y$05$L86zqQDfH5y445dcMlwu6uHv.oXFgT6AiJCwpv3ehr7idc0rI3S2G
nodeSelector:
node.name: node-1

View File

@@ -0,0 +1,6 @@
Get the application URL by running these commands:
{{- if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "zot.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- end }}

View File

@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "zot.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "zot.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "zot.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "zot.labels" -}}
helm.sh/chart: {{ include "zot.chart" . }}
{{ include "zot.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "zot.selectorLabels" -}}
app.kubernetes.io/name: {{ include "zot.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "zot.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "zot.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,11 @@
{{- if and .Values.mountConfig .Values.configFiles }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-config
namespace: {{ .Values.namespace | default .Release.Namespace }}
data:
{{- range $key, $val := .Values.configFiles }}
{{ $key }}: {{ $val | quote }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,169 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "zot.fullname" . }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
labels:
{{- include "zot.labels" . | nindent 4 }}
{{- with .Values.deploymentAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.replicaCount }}
{{- with .Values.strategy }}
strategy:
{{- toYaml . | nindent 4 }}
{{- end }}
selector:
matchLabels:
{{- include "zot.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if and .Values.mountConfig .Values.configFiles }}
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
{{- end }}
{{- if and .Values.mountSecret .Values.secretFiles }}
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.forceRoll }}
rollme: {{ randAlphaNum 5 | quote }}
{{- end }}
labels:
{{- include "zot.selectorLabels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "zot.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
{{- with .Values.priorityClassName }}
priorityClassName: {{ . }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- with .Values.extraArgs }}
args:
{{- toYaml . | nindent 12 }}
{{- end }}
env:
{{- toYaml .Values.env | nindent 12 }}
ports:
- name: zot
containerPort: 5000
protocol: TCP
{{- if or (not (empty .Values.extraVolumeMounts)) .Values.mountConfig .Values.mountSecret .Values.persistence .Values.externalSecrets }}
volumeMounts:
{{- if .Values.mountConfig }}
- mountPath: '/etc/zot'
name: {{ .Release.Name }}-config
{{- end }}
{{- if .Values.mountSecret }}
- mountPath: '/secret'
name: {{ .Release.Name }}-secret
{{- end }}
{{- range .Values.externalSecrets }}
- mountPath: {{ .mountPath | quote }}
name: {{ .secretName | quote }}
{{- end }}
{{- if .Values.persistence }}
- mountPath: '/var/lib/registry'
name: {{ .Release.Name }}-volume
{{- end }}
{{- with .Values.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
livenessProbe:
initialDelaySeconds: 5
httpGet:
path: /v2/
port: 5000
scheme: {{ .Values.httpGet.scheme }}
{{- if .Values.authHeader }}
httpHeaders:
- name: Authorization
value: Basic {{ .Values.authHeader }}
{{- end }}
readinessProbe:
initialDelaySeconds: 5
httpGet:
path: /v2/
port: 5000
scheme: {{ .Values.httpGet.scheme }}
{{- if .Values.authHeader }}
httpHeaders:
- name: Authorization
value: Basic {{ .Values.authHeader }}
{{- end }}
startupProbe:
initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.startupProbe.periodSeconds }}
failureThreshold: {{ .Values.startupProbe.failureThreshold }}
httpGet:
path: /v2/
port: 5000
scheme: {{ .Values.httpGet.scheme }}
{{- if .Values.authHeader }}
httpHeaders:
- name: Authorization
value: Basic {{ .Values.authHeader }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- if or .Values.mountConfig .Values.mountSecret .Values.persistence .Values.externalSecrets (not (empty .Values.extraVolumes))}}
volumes:
{{- if .Values.mountConfig }}
- name: {{ .Release.Name }}-config
configMap:
name: {{ .Release.Name }}-config
{{- end }}
{{- if .Values.mountSecret }}
- name: {{ .Release.Name }}-secret
secret:
secretName: {{ .Release.Name }}-secret
{{- end }}
{{- range .Values.externalSecrets }}
- name: {{ .secretName }}
secret:
secretName: {{ .secretName }}
{{- end }}
{{- if .Values.persistence }}
- name: {{ .Release.Name }}-volume
persistentVolumeClaim:
claimName: {{ .Values.pvc.name | default (printf "%s-pvc" .Release.Name) }}
{{- end }}
{{- with .Values.extraVolumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.dnsConfig }}
dnsConfig:
{{- toYaml . | nindent 8 }}
{{- end }}
dnsPolicy: {{ .Values.dnsPolicy }}

View File

@@ -0,0 +1,64 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "zot.fullname" . -}}
{{- $httpPort := .Values.service.port -}}
{{- $pathtype := .Values.ingress.pathtype -}}
{{- $ingressPath := .Values.ingress.path -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
labels:
app: {{ .Chart.Name }}
release: {{ .Release.Name }}
{{- with .Values.ingress.annotations }}
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className | quote }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- if .ingressPath }}
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- else }}
{{ toYaml .Values.ingress.tls | indent 4 }}
{{- end }}
{{- end}}
rules:
{{- range .Values.ingress.hosts }}
{{- if $ingressPath }}
- host: {{ . }}
http:
paths:
- path: {{ $ingressPath }}
pathType: {{ $pathtype }}
backend:
service:
name: {{ $fullName }}
port:
number: {{ $httpPort }}
{{- else }}
- host: {{ .host }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ $pathtype }}
backend:
service:
name: {{ $fullName }}
port:
number: {{ .servicePort | default $httpPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,16 @@
{{- if and .Values.persistence .Values.pvc .Values.pvc.create }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ .Values.pvc.name | default (printf "%s-pvc" .Release.Name) }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
spec:
accessModes:
- {{ .Values.pvc.accessMode | default "ReadWriteOnce" }}
resources:
requests:
storage: {{ .Values.pvc.storage | default "8Gi" }}
{{- if .Values.pvc.storageClassName }}
storageClassName: {{ .Values.pvc.storageClassName }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,12 @@
{{- if and .Values.mountSecret .Values.secretFiles }}
apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-secret
namespace: {{ .Values.namespace | default .Release.Namespace }}
type: Opaque
data:
{{- range $key, $val := .Values.secretFiles }}
{{ $key }}: {{ $val | b64enc }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,26 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "zot.fullname" . }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
labels:
{{- include "zot.labels" . | nindent 4 }}
{{- with .Values.service.annotations }}
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
{{- if and .Values.service.clusterIP ( eq .Values.service.type "ClusterIP" ) }}
clusterIP: {{ .Values.service.clusterIP }}
{{- end }}
ports:
- port: {{ .Values.service.port }}
targetPort: zot
protocol: TCP
name: zot
{{- if .Values.service.nodePort }}
nodePort: {{ .Values.service.nodePort }}
{{- end }}
selector:
{{- include "zot.selectorLabels" . | nindent 4 }}

View File

@@ -0,0 +1,13 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "zot.serviceAccountName" . }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
labels:
{{- include "zot.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,39 @@
{{- if .Values.metrics }}
{{- if .Values.metrics.enabled }}
{{- if .Values.metrics.serviceMonitor }}
{{- if .Values.metrics.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "zot.fullname" . }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
labels:
app.kubernetes.io/component: metrics
spec:
{{- if .Values.metrics.serviceMonitor.jobLabel }}
jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }}
{{- end }}
selector:
matchLabels:
{{- include "zot.selectorLabels" . | nindent 6 }}
endpoints:
- port: zot
{{- if .Values.metrics.serviceMonitor.interval }}
interval: {{ .Values.metrics.serviceMonitor.interval }}
{{- end }}
{{- if .Values.metrics.serviceMonitor.scrapeTimeout }}
scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }}
{{- end }}
{{- if .Values.metrics.serviceMonitor.path }}
path: {{ .Values.metrics.serviceMonitor.path }}
{{- end }}
{{- if .Values.metrics.serviceMonitor.scheme }}
scheme: {{ .Values.metrics.serviceMonitor.scheme }}
{{- end }}
namespaceSelector:
matchNames:
- {{ .Release.Namespace }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,29 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "zot.fullname" . }}-test-connection-fails"
namespace: {{ .Values.namespace | default .Release.Namespace }}
labels:
{{- include "zot.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed
spec:
containers:
- name: wget
image: alpine:3.18
command:
- sh
- -c
- |
scheme="http"
{{- if eq $.Values.httpGet.scheme "HTTPS"}}
scheme="https"
{{- end }}
echo "$scheme"
{{- if .Values.authHeader }}
wget --no-check-certificate -o output $scheme://{{ include "zot.fullname" . }}:{{ .Values.service.port }}/v2/_catalog || (grep Unauthorized output)
{{- else }}
wget --no-check-certificate $scheme://{{ include "zot.fullname" . }}:{{ .Values.service.port }}/v2/_catalog
{{- end }}
restartPolicy: Never

View File

@@ -0,0 +1,29 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "zot.fullname" . }}-test-connection"
namespace: {{ .Values.namespace | default .Release.Namespace }}
labels:
{{- include "zot.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed
spec:
containers:
- name: wget
image: alpine:3.18
command:
- sh
- -c
- |
scheme="http"
{{- if eq $.Values.httpGet.scheme "HTTPS"}}
scheme="https"
{{- end }}
echo "$scheme"
{{- if .Values.authHeader }}
wget --no-check-certificate --header "Authorization: Basic {{ .Values.authHeader }}" $scheme://{{ include "zot.fullname" . }}:{{ .Values.service.port }}/v2/_catalog
{{- else }}
wget --no-check-certificate $scheme://{{ include "zot.fullname" . }}:{{ .Values.service.port }}/v2/_catalog
{{- end }}
restartPolicy: Never

View File

@@ -0,0 +1,30 @@
should match snapshot of default values:
1: |
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
labels:
app: zot
release: RELEASE-NAME
name: RELEASE-NAME-zot
namespace: NAMESPACE
spec:
ingressClassName: nginx-test
rules:
- host: chart-example.local
http:
paths:
- backend:
service:
name: RELEASE-NAME-zot
port:
number: 5000
path: /
pathType: ImplementationSpecific
tls:
- hosts:
- chart-example.local
secretName: chart-example-tls

View File

@@ -0,0 +1,23 @@
suite: configmap checksum in deployment
# Can't use global templates in this test suite as it will break the checksum calculation
# causing false negative test outcome.
# templates:
# - deployment.yaml
tests:
- it: has no checksum/config if no config
template: deployment.yaml
asserts:
- isNull:
path: spec.template.metadata.annotations.checksum/config
- it: generate checksum/config if config is present
template: deployment.yaml
set:
mountConfig: true
configFiles:
config.json: "{}"
asserts:
- isNotNull:
path: spec.template.metadata.annotations.checksum/config
- matchRegex:
path: spec.template.metadata.annotations.checksum/config
pattern: "^[a-f0-9]{64}$" # SHA256 hex output

View File

@@ -0,0 +1,47 @@
suite: test ingress
templates:
- ingress.yaml
tests:
- it: should be empty if ingress is not enabled
asserts:
- hasDocuments:
count: 0
- it: should have apiVersion networking.k8s.io/v1 for k8s >= 1.19
set:
ingress.enabled: true
capabilities:
majorVersion: 1
minorVersion: 19
asserts:
- hasDocuments:
count: 1
- isKind:
of: Ingress
- isAPIVersion:
of: networking.k8s.io/v1
- it: should have an ingressClassName for k8s >= 1.19
set:
ingress.enabled: true
ingress.className: nginx-test
capabilities:
majorVersion: 1
minorVersion: 19
asserts:
- hasDocuments:
count: 1
- equal:
path: spec.ingressClassName
value: nginx-test
- it: should match snapshot of default values
set:
ingress.enabled: true
ingress.className: nginx-test
ingress.annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
ingress.tls:
- secretName: chart-example-tls
hosts:
- chart-example.local
asserts:
- matchSnapshot: { }

View File

@@ -0,0 +1,25 @@
suite: secret checksum in deployment
# Can't use global templates in this test suite as it will break the checksum calculation
# causing false negative test outcome.
# templates:
# - deployment.yaml
tests:
- it: has no checksum/secret if no config
template: deployment.yaml
asserts:
- isNull:
path: spec.template.metadata.annotations.checksum/secret
- it: generate checksum/secret if config is present
template: deployment.yaml
set:
mountSecret: true
secretFiles:
htpasswd: |-
admin:$2y$05$vmiurPmJvHylk78HHFWuruFFVePlit9rZWGA/FbZfTEmNRneGJtha
user:$2y$05$L86zqQDfH5y445dcMlwu6uHv.oXFgT6AiJCwpv3ehr7idc0rI3S2G
asserts:
- isNotNull:
path: spec.template.metadata.annotations.checksum/secret
- matchRegex:
path: spec.template.metadata.annotations.checksum/secret
pattern: "^[a-f0-9]{64}$" # SHA256 hex output

View File

@@ -0,0 +1,201 @@
# Default values for zot.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: ghcr.io/project-zot/zot-linux-amd64
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: "v2.1.2"
# Defaults to the release namespace if not specified
namespace: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
service:
type: NodePort
port: 5000
nodePort: null # Set to a specific port if type is NodePort
# Annotations to add to the service
annotations: {}
# Set to a static IP if a static IP is desired, only works when
# type: ClusterIP
clusterIP: null
# Enabling this will publicly expose your zot server
# Only enable this if you have security enabled on your cluster
ingress:
enabled: false
annotations: {}
kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
# If using nginx, disable body limits and increase read and write timeouts
# nginx.ingress.kubernetes.io/proxy-body-size: "0"
# nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
# nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
className: "nginx"
pathtype: ImplementationSpecific
hosts:
- host: reg.tavanasys.app
paths:
- path: /
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
# By default, Kubernetes HTTP probes use HTTP 'scheme'. So if TLS is enabled
# in configuration, to prevent failures, the scheme must be set to 'HTTPS'.
httpGet:
scheme: HTTP
# By default, Kubernetes considers a Pod healthy if the liveness probe returns
# successfully. However, sometimes applications need additional startup time on
# their first initialization. By defining a startupProbe, we can allow the
# application to take extra time for initialization without compromising fast
# response to deadlocks.
startupProbe:
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 3
# If mountConfig is true the configMap named $CHART_RELEASE-config is mounted
# on the pod's '/etc/zot' directory
mountConfig: false
# If mountConfig is true the chart creates the '$CHART_RELEASE-config', if it
# does not exist the user is in charge of managing it (as this file includes a
# sample file you have to add it empty to handle it externally).
configFiles:
config.json: |-
{
"storage": { "rootDirectory": "/var/lib/registry" },
"http": { "address": "0.0.0.0", "port": "5000" },
"log": { "level": "debug" }
}
# Alternatively, the configuration can include authentication and acessControl
# data and we can use mountSecret option for the passwords.
#
# config.json: |-
# {
# "storage": { "rootDirectory": "/var/lib/registry" },
# "http": {
# "address": "0.0.0.0",
# "port": "5000",
# "auth": { "htpasswd": { "path": "/secret/htpasswd" } },
# "accessControl": {
# "repositories": {
# "**": {
# "policies": [{
# "users": ["user"],
# "actions": ["read"]
# }],
# "defaultPolicy": []
# }
# },
# "adminPolicy": {
# "users": ["admin"],
# "actions": ["read", "create", "update", "delete"]
# }
# }
# },
# "log": { "level": "debug" }
# }
# externalSecrets allows to mount external (meaning not managed by this chart)
# Kubernetes secrets within the Zot container.
# The secret is identified by its name (property "secretName") and should be
# present in the same namespace. The property "mountPath" specifies the path
# within the container filesystem where the secret is mounted.
#
# Below is an example:
#
# externalSecrets:
# - secretName: "secret1"
# mountPath: "/secrets/s1"
# - secretName: "secret2"
# mountPath: "/secrets/s2"
externalSecrets: []
# If mountSecret is true, the Secret named $CHART_RELEASE-secret is mounted on
# the pod's '/secret' directory (it is used to keep files with passwords, like
# a `htpasswd` file)
mountSecret: false
# If secretFiles does not exist the user is in charge of managing it, again, if
# you want to manage it the value has to be added empty to avoid using this one
secretFiles:
# Example htpasswd with 'admin:admin' & 'user:user' user:pass pairs
htpasswd: |-
admin:$2y$05$vmiurPmJvHylk78HHFWuruFFVePlit9rZWGA/FbZfTEmNRneGJtha
user:$2y$05$L86zqQDfH5y445dcMlwu6uHv.oXFgT6AiJCwpv3ehr7idc0rI3S2G
# Authentication string for Kubernetes probes, which is needed when `htpasswd`
# authentication is enabled, but the anonymous access policy is not.
# It contains a `user:password` string encoded in base64. The example value is
# from running `echo -n "foo:var" | base64`
# authHeader: "Zm9vOmJhcg=="
# If persistence is 'true' the service uses a persistentVolumeClaim to mount a
# volume for zot on '/var/lib/registry'; by default the pvc used is named
# '$CHART_RELEASE-pvc', but the name can be changed below
persistence: false
# PVC data, only used if persistence is 'true'
pvc:
# Make the chart create the PVC, this option is used with storageClasses that
# can create volumes dynamically, if that is not the case is better to do it
# manually and set create to false
create: false
# Name of the PVC to use or create if persistence is enabled, if not set the
# value '$CHART_RELEASE-pvc' is used
name: null
# Volume access mode, if using more than one replica we need
accessMode: "ReadWriteOnce"
# Size of the volume requested
storage: 8Gi
# Name of the storage class to use if it is different than the default one
storageClassName: null
# List of environment variables to set on the container
env:
# - name: "TEST"
# value: "ME"
# - name: SECRET_NAME
# valueFrom:
# secretKeyRef:
# name: mysecret
# key: username
# Extra Volume Mounts
extraVolumeMounts: []
# - name: data
# mountPath: /var/lib/registry
# Extra Volumes
extraVolumes: []
# - name: data
# emptyDir: {}
# Deployment strategy type
strategy:
type: RollingUpdate
# rollingUpdate:
# maxUnavailable: 25%
# Extra args to pass to the deployment's container
extraArgs: []
podAnnotations: {}
podLabels: {}
deploymentAnnotations: {}
priorityClassName: ""
dnsConfig: {}
dnsPolicy: "ClusterFirst"
# Metrics configuration
# NOTE: need enable metric extension in config.json
metrics:
# Start a prometheus exporter
enabled: false
# Prometheus Operator ServiceMonitor configuration
serviceMonitor:
# Start a ServiceMonitor for Prometheus Operator
enabled: false
# Specify the interval at which metrics should be scraped
interval: "30s"
# Specify the path to scrape metrics from
path: "/metrics"