test(charts): comprehensive test improvements and expansions
Phase 1: Improve and expand existing test coverage with edge cases, validations, and regression tests. Changes: - Rename cache_persistence_test → persistence_test with full coverage for config, media, and cache persistence (60+ tests) - Rename service_ipv6_test → service_test with full service coverage including types, ports, annotations, LoadBalancer settings (80+ tests) - Rename startup_probe_test → probes_test covering all three probe types: startup, liveness, readiness with all configurations (60+ tests) - Expand networkpolicy_test with IPv4/IPv6 CIDR validations, egress restrictions, and edge cases (+13 tests) - Expand init_containers_test with full container spec and merge order validation (+5 tests) - Expand envfrom_test with prefix, optional, and multiple source combinations (+9 tests) Test coverage improvements: - All edge cases for persistence types (pvc, hostPath, emptyDir) - Service type validation (ClusterIP, NodePort, LoadBalancer, ExternalName) - Probe types validation (httpGet, tcpSocket, exec) - NetworkPolicy CIDR format validation (IPv4/IPv6) - Comprehensive regression tests for default behavior Total: 6 improved test files, 230+ new test cases Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
This commit is contained in:
1 parent
cf2e60ee63
commit
a08951aaa3
9 files changed
+2067
-380
No files matched your search
@@ -1,160 +0,0 @@
|
|||||||
suite: test cache persistence
|
|
||||||
templates:
|
|
||||||
- deployment.yaml
|
|
||||||
- persistentVolumeClaim.yaml
|
|
||||||
tests:
|
|
||||||
# Deployment volume mount tests
|
|
||||||
- it: should mount cache as emptyDir by default
|
|
||||||
template: deployment.yaml
|
|
||||||
asserts:
|
|
||||||
- contains:
|
|
||||||
path: spec.template.spec.volumes
|
|
||||||
content:
|
|
||||||
name: cache
|
|
||||||
emptyDir: {}
|
|
||||||
|
|
||||||
- it: should mount cache PVC when enabled
|
|
||||||
template: deployment.yaml
|
|
||||||
set:
|
|
||||||
persistence.cache.enabled: true
|
|
||||||
persistence.cache.type: pvc
|
|
||||||
asserts:
|
|
||||||
- contains:
|
|
||||||
path: spec.template.spec.volumes
|
|
||||||
content:
|
|
||||||
name: cache
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: RELEASE-NAME-jellyfin-cache
|
|
||||||
|
|
||||||
- it: should mount cache from hostPath when configured
|
|
||||||
template: deployment.yaml
|
|
||||||
set:
|
|
||||||
persistence.cache.enabled: true
|
|
||||||
persistence.cache.type: hostPath
|
|
||||||
persistence.cache.hostPath: /mnt/jellyfin-cache
|
|
||||||
asserts:
|
|
||||||
- contains:
|
|
||||||
path: spec.template.spec.volumes
|
|
||||||
content:
|
|
||||||
name: cache
|
|
||||||
hostPath:
|
|
||||||
path: /mnt/jellyfin-cache
|
|
||||||
|
|
||||||
- it: should mount cache at correct path
|
|
||||||
template: deployment.yaml
|
|
||||||
asserts:
|
|
||||||
- contains:
|
|
||||||
path: spec.template.spec.containers[0].volumeMounts
|
|
||||||
content:
|
|
||||||
name: cache
|
|
||||||
mountPath: /cache
|
|
||||||
|
|
||||||
# PVC tests
|
|
||||||
- it: should not create cache PVC by default
|
|
||||||
template: persistentVolumeClaim.yaml
|
|
||||||
asserts:
|
|
||||||
- hasDocuments:
|
|
||||||
count: 2 # config and media only
|
|
||||||
|
|
||||||
- it: should create cache PVC when enabled
|
|
||||||
template: persistentVolumeClaim.yaml
|
|
||||||
set:
|
|
||||||
persistence.cache.enabled: true
|
|
||||||
persistence.cache.type: pvc
|
|
||||||
asserts:
|
|
||||||
- hasDocuments:
|
|
||||||
count: 3 # config, media, and cache
|
|
||||||
- contains:
|
|
||||||
path: metadata.name
|
|
||||||
content: RELEASE-NAME-jellyfin-cache
|
|
||||||
|
|
||||||
- it: should not create cache PVC when type is hostPath
|
|
||||||
template: persistentVolumeClaim.yaml
|
|
||||||
set:
|
|
||||||
persistence.cache.enabled: true
|
|
||||||
persistence.cache.type: hostPath
|
|
||||||
asserts:
|
|
||||||
- hasDocuments:
|
|
||||||
count: 2 # config and media only
|
|
||||||
|
|
||||||
- it: should not create cache PVC when type is emptyDir
|
|
||||||
template: persistentVolumeClaim.yaml
|
|
||||||
set:
|
|
||||||
persistence.cache.enabled: true
|
|
||||||
persistence.cache.type: emptyDir
|
|
||||||
asserts:
|
|
||||||
- hasDocuments:
|
|
||||||
count: 2
|
|
||||||
|
|
||||||
- it: should set cache PVC size correctly
|
|
||||||
template: persistentVolumeClaim.yaml
|
|
||||||
documentIndex: 2
|
|
||||||
set:
|
|
||||||
persistence.cache.enabled: true
|
|
||||||
persistence.cache.type: pvc
|
|
||||||
persistence.cache.size: 20Gi
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.resources.requests.storage
|
|
||||||
value: 20Gi
|
|
||||||
|
|
||||||
- it: should set cache PVC access mode
|
|
||||||
template: persistentVolumeClaim.yaml
|
|
||||||
documentIndex: 2
|
|
||||||
set:
|
|
||||||
persistence.cache.enabled: true
|
|
||||||
persistence.cache.type: pvc
|
|
||||||
persistence.cache.accessMode: ReadWriteMany
|
|
||||||
asserts:
|
|
||||||
- contains:
|
|
||||||
path: spec.accessModes
|
|
||||||
content: ReadWriteMany
|
|
||||||
|
|
||||||
- it: should set cache PVC storage class
|
|
||||||
template: persistentVolumeClaim.yaml
|
|
||||||
documentIndex: 2
|
|
||||||
set:
|
|
||||||
persistence.cache.enabled: true
|
|
||||||
persistence.cache.type: pvc
|
|
||||||
persistence.cache.storageClass: fast-ssd
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.storageClassName
|
|
||||||
value: fast-ssd
|
|
||||||
|
|
||||||
- it: should add annotations to cache PVC
|
|
||||||
template: persistentVolumeClaim.yaml
|
|
||||||
documentIndex: 2
|
|
||||||
set:
|
|
||||||
persistence.cache.enabled: true
|
|
||||||
persistence.cache.type: pvc
|
|
||||||
persistence.cache.annotations:
|
|
||||||
my-annotation: my-value
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: metadata.annotations.my-annotation
|
|
||||||
value: my-value
|
|
||||||
|
|
||||||
- it: should use existing claim when specified
|
|
||||||
template: deployment.yaml
|
|
||||||
set:
|
|
||||||
persistence.cache.enabled: true
|
|
||||||
persistence.cache.type: pvc
|
|
||||||
persistence.cache.existingClaim: my-existing-cache-claim
|
|
||||||
asserts:
|
|
||||||
- contains:
|
|
||||||
path: spec.template.spec.volumes
|
|
||||||
content:
|
|
||||||
name: cache
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: my-existing-cache-claim
|
|
||||||
|
|
||||||
- it: should not create PVC when existing claim used
|
|
||||||
template: persistentVolumeClaim.yaml
|
|
||||||
set:
|
|
||||||
persistence.cache.enabled: true
|
|
||||||
persistence.cache.type: pvc
|
|
||||||
persistence.cache.existingClaim: my-existing-cache-claim
|
|
||||||
asserts:
|
|
||||||
- hasDocuments:
|
|
||||||
count: 2 # config and media only, not cache
|
|
||||||
@@ -120,3 +120,151 @@ tests:
|
|||||||
- equal:
|
- equal:
|
||||||
path: spec.template.spec.containers[0].envFrom[0].configMapRef.name
|
path: spec.template.spec.containers[0].envFrom[0].configMapRef.name
|
||||||
value: jellyfin-config
|
value: jellyfin-config
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# EDGE CASES AND ADDITIONAL VALIDATIONS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- it: should handle empty envFrom array
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom: []
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.template.spec.containers[0].envFrom
|
||||||
|
|
||||||
|
- it: should support both configMapRef and secretRef with optional and prefix
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: my-config
|
||||||
|
optional: true
|
||||||
|
prefix: CFG_
|
||||||
|
- secretRef:
|
||||||
|
name: my-secret
|
||||||
|
optional: false
|
||||||
|
prefix: SEC_
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.containers[0].envFrom
|
||||||
|
count: 2
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].configMapRef.name
|
||||||
|
value: my-config
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].configMapRef.optional
|
||||||
|
value: true
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].prefix
|
||||||
|
value: CFG_
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[1].secretRef.name
|
||||||
|
value: my-secret
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[1].secretRef.optional
|
||||||
|
value: false
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[1].prefix
|
||||||
|
value: SEC_
|
||||||
|
|
||||||
|
- it: should support multiple ConfigMaps with different prefixes
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: config-1
|
||||||
|
prefix: APP1_
|
||||||
|
- configMapRef:
|
||||||
|
name: config-2
|
||||||
|
prefix: APP2_
|
||||||
|
- configMapRef:
|
||||||
|
name: config-3
|
||||||
|
prefix: APP3_
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.containers[0].envFrom
|
||||||
|
count: 3
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].prefix
|
||||||
|
value: APP1_
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[1].prefix
|
||||||
|
value: APP2_
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[2].prefix
|
||||||
|
value: APP3_
|
||||||
|
|
||||||
|
- it: should support multiple Secrets with different prefixes
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: secret-1
|
||||||
|
prefix: DB_
|
||||||
|
- secretRef:
|
||||||
|
name: secret-2
|
||||||
|
prefix: API_
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.containers[0].envFrom
|
||||||
|
count: 2
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].prefix
|
||||||
|
value: DB_
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[1].prefix
|
||||||
|
value: API_
|
||||||
|
|
||||||
|
- it: should not have prefix when not specified
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: no-prefix-config
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].prefix
|
||||||
|
|
||||||
|
- it: should not have optional field when not specified
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: required-config
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].configMapRef.optional
|
||||||
|
|
||||||
|
# Regression: verify envFrom doesn't interfere with other env settings
|
||||||
|
- it: should preserve JELLYFIN_PublishedServerUrl when envFrom is used
|
||||||
|
set:
|
||||||
|
jellyfin.env:
|
||||||
|
- name: JELLYFIN_PublishedServerUrl
|
||||||
|
value: https://jellyfin.example.com
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: extra-config
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.containers[0].env
|
||||||
|
content:
|
||||||
|
name: JELLYFIN_PublishedServerUrl
|
||||||
|
value: https://jellyfin.example.com
|
||||||
|
|
||||||
|
# Complex scenario with many sources
|
||||||
|
- it: should support large number of envFrom sources
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: config-1
|
||||||
|
- secretRef:
|
||||||
|
name: secret-1
|
||||||
|
- configMapRef:
|
||||||
|
name: config-2
|
||||||
|
prefix: PREFIX_
|
||||||
|
- secretRef:
|
||||||
|
name: secret-2
|
||||||
|
optional: true
|
||||||
|
- configMapRef:
|
||||||
|
name: config-3
|
||||||
|
optional: true
|
||||||
|
prefix: OPT_
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.containers[0].envFrom
|
||||||
|
count: 5
|
||||||
@@ -117,3 +117,134 @@ tests:
|
|||||||
content:
|
content:
|
||||||
name: new-way
|
name: new-way
|
||||||
image: alpine:3.18
|
image: alpine:3.18
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# EDGE CASES AND FULL SPECIFICATION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- it: should handle empty extraInitContainers array
|
||||||
|
set:
|
||||||
|
extraInitContainers: []
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.template.spec.initContainers
|
||||||
|
|
||||||
|
- it: should preserve full container specification with all fields
|
||||||
|
set:
|
||||||
|
extraInitContainers:
|
||||||
|
- name: full-spec-init
|
||||||
|
image: busybox:1.35
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command: ['sh', '-c']
|
||||||
|
args: ['echo complete']
|
||||||
|
env:
|
||||||
|
- name: ENV_VAR
|
||||||
|
value: test
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: init-config
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /config
|
||||||
|
- name: media
|
||||||
|
mountPath: /media
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 256Mi
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 0
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].imagePullPolicy
|
||||||
|
value: IfNotPresent
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].env[0].name
|
||||||
|
value: ENV_VAR
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].envFrom[0].configMapRef.name
|
||||||
|
value: init-config
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.initContainers[0].volumeMounts
|
||||||
|
count: 2
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].resources.requests.cpu
|
||||||
|
value: 100m
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].resources.limits.memory
|
||||||
|
value: 256Mi
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].securityContext.allowPrivilegeEscalation
|
||||||
|
value: false
|
||||||
|
|
||||||
|
- it: should verify merge order (deprecated first, then extra)
|
||||||
|
set:
|
||||||
|
initContainers:
|
||||||
|
- name: first-deprecated
|
||||||
|
image: busybox:1.35
|
||||||
|
extraInitContainers:
|
||||||
|
- name: second-extra
|
||||||
|
image: alpine:3.18
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].name
|
||||||
|
value: first-deprecated
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[1].name
|
||||||
|
value: second-extra
|
||||||
|
|
||||||
|
- it: should support three or more init containers
|
||||||
|
set:
|
||||||
|
extraInitContainers:
|
||||||
|
- name: init-1
|
||||||
|
image: busybox:1.35
|
||||||
|
- name: init-2
|
||||||
|
image: alpine:3.18
|
||||||
|
- name: init-3
|
||||||
|
image: ubuntu:22.04
|
||||||
|
- name: init-4
|
||||||
|
image: debian:12
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.initContainers
|
||||||
|
count: 4
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[2].name
|
||||||
|
value: init-3
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[3].name
|
||||||
|
value: init-4
|
||||||
|
|
||||||
|
# Regression: verify initContainers comes first when merged
|
||||||
|
- it: should always place deprecated initContainers before extraInitContainers
|
||||||
|
set:
|
||||||
|
initContainers:
|
||||||
|
- name: deprecated-init
|
||||||
|
image: busybox:1.35
|
||||||
|
- name: deprecated-init-2
|
||||||
|
image: busybox:1.36
|
||||||
|
extraInitContainers:
|
||||||
|
- name: extra-init
|
||||||
|
image: alpine:3.18
|
||||||
|
- name: extra-init-2
|
||||||
|
image: alpine:3.19
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.initContainers
|
||||||
|
count: 4
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].name
|
||||||
|
value: deprecated-init
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[1].name
|
||||||
|
value: deprecated-init-2
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[2].name
|
||||||
|
value: extra-init
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[3].name
|
||||||
|
value: extra-init-2
|
||||||
@@ -295,3 +295,216 @@ tests:
|
|||||||
- equal:
|
- equal:
|
||||||
path: spec.podSelector.matchLabels.app\.kubernetes\.io/instance
|
path: spec.podSelector.matchLabels.app\.kubernetes\.io/instance
|
||||||
value: RELEASE-NAME
|
value: RELEASE-NAME
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# EDGE CASES AND ADDITIONAL VALIDATIONS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# CIDR validations (IPv4 and IPv6)
|
||||||
|
- it: should accept valid IPv4 CIDR in allowedCIDRs
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.allowAllEgress: false
|
||||||
|
networkPolicy.egress.restrictedEgress:
|
||||||
|
allowedCIDRs:
|
||||||
|
- "10.0.0.0/8"
|
||||||
|
- "192.168.1.0/24"
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 10.0.0.0/8
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 192.168.1.0/24
|
||||||
|
|
||||||
|
- it: should accept valid IPv6 CIDR in allowedCIDRs
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.allowAllEgress: false
|
||||||
|
networkPolicy.egress.restrictedEgress:
|
||||||
|
allowedCIDRs:
|
||||||
|
- "2001:db8::/32"
|
||||||
|
- "fe80::/10"
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 2001:db8::/32
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: fe80::/10
|
||||||
|
|
||||||
|
- it: should accept mix of IPv4 and IPv6 CIDRs
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.allowAllEgress: false
|
||||||
|
networkPolicy.egress.restrictedEgress:
|
||||||
|
allowedCIDRs:
|
||||||
|
- "10.0.0.0/8"
|
||||||
|
- "2001:db8::/32"
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 10.0.0.0/8
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 2001:db8::/32
|
||||||
|
|
||||||
|
# Egress restricted scenarios
|
||||||
|
- it: should allow only metadata when restrictedEgress with allowMetadata only
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.allowAllEgress: false
|
||||||
|
networkPolicy.egress.restrictedEgress:
|
||||||
|
allowMetadata: true
|
||||||
|
allowInCluster: false
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 169.254.169.254/32
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
|
||||||
|
- it: should not allow in-cluster when allowInCluster is false
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.allowAllEgress: false
|
||||||
|
networkPolicy.egress.restrictedEgress:
|
||||||
|
allowMetadata: false
|
||||||
|
allowInCluster: false
|
||||||
|
asserts:
|
||||||
|
- notContains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- podSelector: {}
|
||||||
|
|
||||||
|
- it: should handle empty allowedCIDRs array
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.allowAllEgress: false
|
||||||
|
networkPolicy.egress.restrictedEgress:
|
||||||
|
allowedCIDRs: []
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.egress
|
||||||
|
|
||||||
|
# Custom ingress rules edge cases
|
||||||
|
- it: should support multiple custom ingress rules
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.ingress.customRules:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: frontend
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8096
|
||||||
|
- from:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: proxy
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8920
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.ingress
|
||||||
|
count: 3 # default + 2 custom (when metrics disabled)
|
||||||
|
|
||||||
|
# Regression: verify default egress behavior
|
||||||
|
- it: should have DNS egress by default
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: kube-system
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
k8s-app: kube-dns
|
||||||
|
ports:
|
||||||
|
- protocol: UDP
|
||||||
|
port: 53
|
||||||
|
- protocol: TCP
|
||||||
|
port: 53
|
||||||
|
|
||||||
|
# Regression: verify ingress port
|
||||||
|
- it: should expose correct port in ingress rules
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
service.port: 9096
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.ingress[0].ports
|
||||||
|
content:
|
||||||
|
protocol: TCP
|
||||||
|
port: 9096
|
||||||
|
|
||||||
|
# Combining all egress options
|
||||||
|
- it: should combine all egress options when all enabled
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.allowDNS: true
|
||||||
|
networkPolicy.egress.allowAllEgress: false
|
||||||
|
networkPolicy.egress.restrictedEgress:
|
||||||
|
allowMetadata: true
|
||||||
|
allowInCluster: true
|
||||||
|
allowedCIDRs:
|
||||||
|
- "10.0.0.0/8"
|
||||||
|
asserts:
|
||||||
|
# Should have DNS
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
ports:
|
||||||
|
- protocol: UDP
|
||||||
|
port: 53
|
||||||
|
- protocol: TCP
|
||||||
|
port: 53
|
||||||
|
# Should have metadata
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 169.254.169.254/32
|
||||||
|
# Should have in-cluster
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- podSelector: {}
|
||||||
|
# Should have custom CIDR
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 10.0.0.0/8
|
||||||
@@ -0,0 +1,663 @@
|
|||||||
|
suite: test persistence (config, media, cache)
|
||||||
|
templates:
|
||||||
|
- deployment.yaml
|
||||||
|
- persistentVolumeClaim.yaml
|
||||||
|
tests:
|
||||||
|
# =============================================================================
|
||||||
|
# CONFIG PERSISTENCE TESTS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Default behavior
|
||||||
|
- it: should create config PVC by default
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 2 # config and media (cache disabled by default)
|
||||||
|
|
||||||
|
- it: should set default config PVC size to 5Gi
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 0
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.resources.requests.storage
|
||||||
|
value: 5Gi
|
||||||
|
|
||||||
|
- it: should set default config PVC access mode to ReadWriteOnce
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 0
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.accessModes
|
||||||
|
content: ReadWriteOnce
|
||||||
|
|
||||||
|
- it: should mount config PVC by default
|
||||||
|
template: deployment.yaml
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: config
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: RELEASE-NAME-jellyfin-config
|
||||||
|
|
||||||
|
- it: should mount config at /config
|
||||||
|
template: deployment.yaml
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.containers[0].volumeMounts
|
||||||
|
content:
|
||||||
|
name: config
|
||||||
|
mountPath: /config
|
||||||
|
|
||||||
|
# Custom config PVC settings
|
||||||
|
- it: should set custom config PVC size
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 0
|
||||||
|
set:
|
||||||
|
persistence.config.size: 10Gi
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.resources.requests.storage
|
||||||
|
value: 10Gi
|
||||||
|
|
||||||
|
- it: should set custom config PVC access mode
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 0
|
||||||
|
set:
|
||||||
|
persistence.config.accessMode: ReadWriteMany
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.accessModes
|
||||||
|
content: ReadWriteMany
|
||||||
|
|
||||||
|
- it: should set custom config PVC storage class
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 0
|
||||||
|
set:
|
||||||
|
persistence.config.storageClass: fast-ssd
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.storageClassName
|
||||||
|
value: fast-ssd
|
||||||
|
|
||||||
|
- it: should add annotations to config PVC
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 0
|
||||||
|
set:
|
||||||
|
persistence.config.annotations:
|
||||||
|
backup: "true"
|
||||||
|
retention: "30d"
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: metadata.annotations.backup
|
||||||
|
value: "true"
|
||||||
|
- equal:
|
||||||
|
path: metadata.annotations.retention
|
||||||
|
value: "30d"
|
||||||
|
|
||||||
|
# Config with existing claim
|
||||||
|
- it: should use existing claim for config when specified
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.config.existingClaim: my-existing-config-claim
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: config
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: my-existing-config-claim
|
||||||
|
|
||||||
|
- it: should not create config PVC when existing claim used
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.config.existingClaim: my-existing-config-claim
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 1 # media only
|
||||||
|
|
||||||
|
# Config disabled (emptyDir fallback)
|
||||||
|
- it: should use emptyDir for config when disabled
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.config.enabled: false
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: config
|
||||||
|
emptyDir: {}
|
||||||
|
|
||||||
|
- it: should not create config PVC when disabled
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.config.enabled: false
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 1 # media only
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# MEDIA PERSISTENCE TESTS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Default behavior
|
||||||
|
- it: should create media PVC by default
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 1
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: metadata.name
|
||||||
|
value: RELEASE-NAME-jellyfin-media
|
||||||
|
|
||||||
|
- it: should set default media PVC size to 25Gi
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 1
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.resources.requests.storage
|
||||||
|
value: 25Gi
|
||||||
|
|
||||||
|
- it: should set default media PVC access mode to ReadWriteOnce
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 1
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.accessModes
|
||||||
|
content: ReadWriteOnce
|
||||||
|
|
||||||
|
- it: should mount media PVC by default
|
||||||
|
template: deployment.yaml
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: media
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: RELEASE-NAME-jellyfin-media
|
||||||
|
|
||||||
|
- it: should mount media at /media
|
||||||
|
template: deployment.yaml
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.containers[0].volumeMounts
|
||||||
|
content:
|
||||||
|
name: media
|
||||||
|
mountPath: /media
|
||||||
|
|
||||||
|
# Media with type: pvc (explicit)
|
||||||
|
- it: should create media PVC when type is pvc
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.media.type: pvc
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 2 # config and media
|
||||||
|
|
||||||
|
- it: should set custom media PVC size
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 1
|
||||||
|
set:
|
||||||
|
persistence.media.type: pvc
|
||||||
|
persistence.media.size: 100Gi
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.resources.requests.storage
|
||||||
|
value: 100Gi
|
||||||
|
|
||||||
|
- it: should set custom media PVC storage class
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 1
|
||||||
|
set:
|
||||||
|
persistence.media.type: pvc
|
||||||
|
persistence.media.storageClass: slow-hdd
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.storageClassName
|
||||||
|
value: slow-hdd
|
||||||
|
|
||||||
|
- it: should add annotations to media PVC
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 1
|
||||||
|
set:
|
||||||
|
persistence.media.type: pvc
|
||||||
|
persistence.media.annotations:
|
||||||
|
media-type: movies
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: metadata.annotations.media-type
|
||||||
|
value: movies
|
||||||
|
|
||||||
|
# Media with type: hostPath
|
||||||
|
- it: should mount media from hostPath when configured
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.media.type: hostPath
|
||||||
|
persistence.media.hostPath: /mnt/nas/media
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: media
|
||||||
|
hostPath:
|
||||||
|
path: /mnt/nas/media
|
||||||
|
|
||||||
|
- it: should not create media PVC when type is hostPath
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.media.type: hostPath
|
||||||
|
persistence.media.hostPath: /mnt/nas/media
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 1 # config only
|
||||||
|
|
||||||
|
# Media with type: emptyDir
|
||||||
|
- it: should mount media as emptyDir when type is emptyDir
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.media.type: emptyDir
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: media
|
||||||
|
emptyDir: {}
|
||||||
|
|
||||||
|
- it: should not create media PVC when type is emptyDir
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.media.type: emptyDir
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 1 # config only
|
||||||
|
|
||||||
|
# Media disabled
|
||||||
|
- it: should use emptyDir for media when disabled
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.media.enabled: false
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: media
|
||||||
|
emptyDir: {}
|
||||||
|
|
||||||
|
- it: should not create media PVC when disabled
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.media.enabled: false
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 1 # config only
|
||||||
|
|
||||||
|
# Media with existing claim
|
||||||
|
- it: should use existing claim for media when specified
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.media.type: pvc
|
||||||
|
persistence.media.existingClaim: my-existing-media-claim
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: media
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: my-existing-media-claim
|
||||||
|
|
||||||
|
- it: should not create media PVC when existing claim used
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.media.type: pvc
|
||||||
|
persistence.media.existingClaim: my-existing-media-claim
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 1 # config only
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# CACHE PERSISTENCE TESTS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Default behavior
|
||||||
|
- it: should mount cache as emptyDir by default
|
||||||
|
template: deployment.yaml
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
emptyDir: {}
|
||||||
|
|
||||||
|
- it: should not create cache PVC by default
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 2 # config and media only
|
||||||
|
|
||||||
|
- it: should mount cache at /cache
|
||||||
|
template: deployment.yaml
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.containers[0].volumeMounts
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
mountPath: /cache
|
||||||
|
|
||||||
|
# Cache with type: pvc
|
||||||
|
- it: should create cache PVC when enabled with type pvc
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 3 # config, media, and cache
|
||||||
|
|
||||||
|
- it: should mount cache PVC when enabled
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: RELEASE-NAME-jellyfin-cache
|
||||||
|
|
||||||
|
- it: should set cache PVC size correctly
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 2
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
persistence.cache.size: 20Gi
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.resources.requests.storage
|
||||||
|
value: 20Gi
|
||||||
|
|
||||||
|
- it: should set cache PVC access mode
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 2
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
persistence.cache.accessMode: ReadWriteMany
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.accessModes
|
||||||
|
content: ReadWriteMany
|
||||||
|
|
||||||
|
- it: should set cache PVC storage class
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 2
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
persistence.cache.storageClass: fast-ssd
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.storageClassName
|
||||||
|
value: fast-ssd
|
||||||
|
|
||||||
|
- it: should add annotations to cache PVC
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 2
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
persistence.cache.annotations:
|
||||||
|
my-annotation: my-value
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: metadata.annotations.my-annotation
|
||||||
|
value: my-value
|
||||||
|
|
||||||
|
# Cache with type: hostPath
|
||||||
|
- it: should mount cache from hostPath when configured
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: hostPath
|
||||||
|
persistence.cache.hostPath: /mnt/jellyfin-cache
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
hostPath:
|
||||||
|
path: /mnt/jellyfin-cache
|
||||||
|
|
||||||
|
- it: should not create cache PVC when type is hostPath
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: hostPath
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 2 # config and media only
|
||||||
|
|
||||||
|
# Cache with type: emptyDir
|
||||||
|
- it: should not create cache PVC when type is emptyDir
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: emptyDir
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 2
|
||||||
|
|
||||||
|
# Cache with existing claim
|
||||||
|
- it: should use existing claim for cache when specified
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
persistence.cache.existingClaim: my-existing-cache-claim
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: my-existing-cache-claim
|
||||||
|
|
||||||
|
- it: should not create PVC when existing cache claim used
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
persistence.cache.existingClaim: my-existing-cache-claim
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 2 # config and media only, not cache
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# EDGE CASES AND VALIDATIONS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# All persistence disabled
|
||||||
|
- it: should use emptyDir for all volumes when all persistence disabled
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.config.enabled: false
|
||||||
|
persistence.media.enabled: false
|
||||||
|
persistence.cache.enabled: false
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: config
|
||||||
|
emptyDir: {}
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: media
|
||||||
|
emptyDir: {}
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
emptyDir: {}
|
||||||
|
|
||||||
|
- it: should not create any PVCs when all persistence disabled
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.config.enabled: false
|
||||||
|
persistence.media.enabled: false
|
||||||
|
persistence.cache.enabled: false
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 0
|
||||||
|
|
||||||
|
# All persistence enabled as PVC
|
||||||
|
- it: should create all three PVCs when all enabled
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 3 # config, media, and cache
|
||||||
|
|
||||||
|
# Mix of persistence types
|
||||||
|
- it: should handle mix of pvc, hostPath, and emptyDir
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.config.enabled: true
|
||||||
|
persistence.media.type: hostPath
|
||||||
|
persistence.media.hostPath: /mnt/media
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: emptyDir
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: config
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: RELEASE-NAME-jellyfin-config
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: media
|
||||||
|
hostPath:
|
||||||
|
path: /mnt/media
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
emptyDir: {}
|
||||||
|
|
||||||
|
- it: should create only config PVC with mixed types
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.media.type: hostPath
|
||||||
|
persistence.media.hostPath: /mnt/media
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: emptyDir
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 1 # config only
|
||||||
|
|
||||||
|
# All access modes
|
||||||
|
- it: should support ReadWriteOnce access mode
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 0
|
||||||
|
set:
|
||||||
|
persistence.config.accessMode: ReadWriteOnce
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.accessModes
|
||||||
|
content: ReadWriteOnce
|
||||||
|
|
||||||
|
- it: should support ReadOnlyMany access mode
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 1
|
||||||
|
set:
|
||||||
|
persistence.media.accessMode: ReadOnlyMany
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.accessModes
|
||||||
|
content: ReadOnlyMany
|
||||||
|
|
||||||
|
- it: should support ReadWriteMany access mode
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 0
|
||||||
|
set:
|
||||||
|
persistence.config.accessMode: ReadWriteMany
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.accessModes
|
||||||
|
content: ReadWriteMany
|
||||||
|
|
||||||
|
- it: should support ReadWriteOncePod access mode
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 0
|
||||||
|
set:
|
||||||
|
persistence.config.accessMode: ReadWriteOncePod
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.accessModes
|
||||||
|
content: ReadWriteOncePod
|
||||||
|
|
||||||
|
# Empty storageClass (default provisioner)
|
||||||
|
- it: should not set storageClassName when storageClass is empty string
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 0
|
||||||
|
set:
|
||||||
|
persistence.config.storageClass: ''
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.storageClassName
|
||||||
|
|
||||||
|
# Multiple annotations
|
||||||
|
- it: should support multiple annotations on PVC
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 0
|
||||||
|
set:
|
||||||
|
persistence.config.annotations:
|
||||||
|
annotation1: value1
|
||||||
|
annotation2: value2
|
||||||
|
annotation3: value3
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: metadata.annotations.annotation1
|
||||||
|
value: value1
|
||||||
|
- equal:
|
||||||
|
path: metadata.annotations.annotation2
|
||||||
|
value: value2
|
||||||
|
- equal:
|
||||||
|
path: metadata.annotations.annotation3
|
||||||
|
value: value3
|
||||||
|
|
||||||
|
# Regression: verify all volume mounts are always present
|
||||||
|
- it: should always have all three volume mounts in container
|
||||||
|
template: deployment.yaml
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.containers[0].volumeMounts
|
||||||
|
count: 3
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.containers[0].volumeMounts
|
||||||
|
content:
|
||||||
|
name: config
|
||||||
|
mountPath: /config
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.containers[0].volumeMounts
|
||||||
|
content:
|
||||||
|
name: media
|
||||||
|
mountPath: /media
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.containers[0].volumeMounts
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
mountPath: /cache
|
||||||
|
|
||||||
|
# Regression: verify all volumes are always present
|
||||||
|
- it: should always have all three volumes defined
|
||||||
|
template: deployment.yaml
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
count: 3
|
||||||
@@ -0,0 +1,447 @@
|
|||||||
|
suite: test probes (startup, liveness, readiness)
|
||||||
|
templates:
|
||||||
|
- deployment.yaml
|
||||||
|
tests:
|
||||||
|
# =============================================================================
|
||||||
|
# STARTUP PROBE TESTS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- it: should have startup probe by default
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe
|
||||||
|
|
||||||
|
- it: should use tcpSocket for startup probe by default
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.tcpSocket
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.tcpSocket.port
|
||||||
|
value: http
|
||||||
|
|
||||||
|
- it: should have default startup probe timing values
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.initialDelaySeconds
|
||||||
|
value: 0
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.periodSeconds
|
||||||
|
value: 10
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.failureThreshold
|
||||||
|
value: 30
|
||||||
|
|
||||||
|
- it: should allow custom initialDelaySeconds for startup probe
|
||||||
|
set:
|
||||||
|
startupProbe.initialDelaySeconds: 5
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.initialDelaySeconds
|
||||||
|
value: 5
|
||||||
|
|
||||||
|
- it: should allow custom periodSeconds for startup probe
|
||||||
|
set:
|
||||||
|
startupProbe.periodSeconds: 15
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.periodSeconds
|
||||||
|
value: 15
|
||||||
|
|
||||||
|
- it: should allow custom failureThreshold for startup probe
|
||||||
|
set:
|
||||||
|
startupProbe.failureThreshold: 60
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.failureThreshold
|
||||||
|
value: 60
|
||||||
|
|
||||||
|
- it: should support httpGet for startup probe
|
||||||
|
set:
|
||||||
|
startupProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 0
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 30
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.httpGet
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.httpGet.path
|
||||||
|
value: /health
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.httpGet.port
|
||||||
|
value: http
|
||||||
|
|
||||||
|
- it: should support exec for startup probe
|
||||||
|
set:
|
||||||
|
startupProbe:
|
||||||
|
exec:
|
||||||
|
command: ['/bin/sh', '-c', 'curl -f http://localhost:8096/health']
|
||||||
|
initialDelaySeconds: 0
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 30
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.exec
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.exec.command
|
||||||
|
content: '/bin/sh'
|
||||||
|
|
||||||
|
- it: should support custom port for startup probe
|
||||||
|
set:
|
||||||
|
startupProbe.tcpSocket.port: 9000
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.tcpSocket.port
|
||||||
|
value: 9000
|
||||||
|
|
||||||
|
- it: should calculate correct startup timeout window
|
||||||
|
set:
|
||||||
|
startupProbe.periodSeconds: 10
|
||||||
|
startupProbe.failureThreshold: 30
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.periodSeconds
|
||||||
|
value: 10
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.failureThreshold
|
||||||
|
value: 30
|
||||||
|
# Total startup time allowed: 10 * 30 = 300 seconds (5 minutes)
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# LIVENESS PROBE TESTS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- it: should have liveness probe by default
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe
|
||||||
|
|
||||||
|
- it: should use httpGet for liveness probe by default
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.httpGet
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.httpGet.path
|
||||||
|
value: /health
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.httpGet.port
|
||||||
|
value: http
|
||||||
|
|
||||||
|
- it: should have default liveness probe initialDelaySeconds
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.initialDelaySeconds
|
||||||
|
value: 10
|
||||||
|
|
||||||
|
- it: should allow custom initialDelaySeconds for liveness probe
|
||||||
|
set:
|
||||||
|
livenessProbe.initialDelaySeconds: 30
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.initialDelaySeconds
|
||||||
|
value: 30
|
||||||
|
|
||||||
|
- it: should allow custom periodSeconds for liveness probe
|
||||||
|
set:
|
||||||
|
livenessProbe.periodSeconds: 20
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.periodSeconds
|
||||||
|
value: 20
|
||||||
|
|
||||||
|
- it: should allow custom failureThreshold for liveness probe
|
||||||
|
set:
|
||||||
|
livenessProbe.failureThreshold: 5
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.failureThreshold
|
||||||
|
value: 5
|
||||||
|
|
||||||
|
- it: should allow custom timeoutSeconds for liveness probe
|
||||||
|
set:
|
||||||
|
livenessProbe.timeoutSeconds: 5
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.timeoutSeconds
|
||||||
|
value: 5
|
||||||
|
|
||||||
|
- it: should allow custom successThreshold for liveness probe
|
||||||
|
set:
|
||||||
|
livenessProbe.successThreshold: 2
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.successThreshold
|
||||||
|
value: 2
|
||||||
|
|
||||||
|
- it: should support tcpSocket for liveness probe
|
||||||
|
set:
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.tcpSocket
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.tcpSocket.port
|
||||||
|
value: http
|
||||||
|
|
||||||
|
- it: should support exec for liveness probe
|
||||||
|
set:
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command: ['/bin/sh', '-c', 'pgrep jellyfin']
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.exec
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.exec.command
|
||||||
|
content: 'pgrep'
|
||||||
|
|
||||||
|
- it: should support custom httpGet path for liveness probe
|
||||||
|
set:
|
||||||
|
livenessProbe.httpGet.path: /custom/health
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.httpGet.path
|
||||||
|
value: /custom/health
|
||||||
|
|
||||||
|
- it: should support httpHeaders for liveness probe
|
||||||
|
set:
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
httpHeaders:
|
||||||
|
- name: X-Custom-Header
|
||||||
|
value: CustomValue
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.httpGet.httpHeaders[0].name
|
||||||
|
value: X-Custom-Header
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.httpGet.httpHeaders[0].value
|
||||||
|
value: CustomValue
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# READINESS PROBE TESTS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- it: should have readiness probe by default
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe
|
||||||
|
|
||||||
|
- it: should use httpGet for readiness probe by default
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.httpGet
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.httpGet.path
|
||||||
|
value: /health
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.httpGet.port
|
||||||
|
value: http
|
||||||
|
|
||||||
|
- it: should have default readiness probe initialDelaySeconds
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.initialDelaySeconds
|
||||||
|
value: 10
|
||||||
|
|
||||||
|
- it: should allow custom initialDelaySeconds for readiness probe
|
||||||
|
set:
|
||||||
|
readinessProbe.initialDelaySeconds: 15
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.initialDelaySeconds
|
||||||
|
value: 15
|
||||||
|
|
||||||
|
- it: should allow custom periodSeconds for readiness probe
|
||||||
|
set:
|
||||||
|
readinessProbe.periodSeconds: 15
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.periodSeconds
|
||||||
|
value: 15
|
||||||
|
|
||||||
|
- it: should allow custom failureThreshold for readiness probe
|
||||||
|
set:
|
||||||
|
readinessProbe.failureThreshold: 6
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.failureThreshold
|
||||||
|
value: 6
|
||||||
|
|
||||||
|
- it: should allow custom timeoutSeconds for readiness probe
|
||||||
|
set:
|
||||||
|
readinessProbe.timeoutSeconds: 3
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.timeoutSeconds
|
||||||
|
value: 3
|
||||||
|
|
||||||
|
- it: should allow custom successThreshold for readiness probe
|
||||||
|
set:
|
||||||
|
readinessProbe.successThreshold: 2
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.successThreshold
|
||||||
|
value: 2
|
||||||
|
|
||||||
|
- it: should support tcpSocket for readiness probe
|
||||||
|
set:
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.tcpSocket
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.tcpSocket.port
|
||||||
|
value: http
|
||||||
|
|
||||||
|
- it: should support exec for readiness probe
|
||||||
|
set:
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command: ['/bin/sh', '-c', 'curl -f http://localhost:8096/health']
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.exec
|
||||||
|
|
||||||
|
- it: should support custom httpGet path for readiness probe
|
||||||
|
set:
|
||||||
|
readinessProbe.httpGet.path: /ready
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.httpGet.path
|
||||||
|
value: /ready
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# EDGE CASES AND COMBINED SCENARIOS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- it: should allow all three probes with different configurations
|
||||||
|
set:
|
||||||
|
startupProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 0
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 60
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 20
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
periodSeconds: 10
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.failureThreshold
|
||||||
|
value: 60
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.initialDelaySeconds
|
||||||
|
value: 30
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.initialDelaySeconds
|
||||||
|
value: 15
|
||||||
|
|
||||||
|
- it: should support all timing parameters for all probes
|
||||||
|
set:
|
||||||
|
startupProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 0
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
successThreshold: 1
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 15
|
||||||
|
failureThreshold: 4
|
||||||
|
timeoutSeconds: 3
|
||||||
|
successThreshold: 1
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
timeoutSeconds: 2
|
||||||
|
successThreshold: 2
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.timeoutSeconds
|
||||||
|
value: 5
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.timeoutSeconds
|
||||||
|
value: 3
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.timeoutSeconds
|
||||||
|
value: 2
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.successThreshold
|
||||||
|
value: 2
|
||||||
|
|
||||||
|
# Regression: verify all three probes are always present
|
||||||
|
- it: should always have all three probes configured
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe
|
||||||
|
|
||||||
|
# Regression: verify default probe types
|
||||||
|
- it: should use correct probe types by default
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.tcpSocket
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.httpGet
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.httpGet
|
||||||
|
|
||||||
|
# Different probe types combination
|
||||||
|
- it: should support different probe types for each probe
|
||||||
|
set:
|
||||||
|
startupProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 0
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command: ['/bin/sh', '-c', 'test -f /tmp/ready']
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.tcpSocket
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].livenessProbe.httpGet
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].readinessProbe.exec
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
suite: test service ipv6 and dual-stack
|
|
||||||
templates:
|
|
||||||
- service.yaml
|
|
||||||
tests:
|
|
||||||
- it: should not set ipFamilyPolicy by default
|
|
||||||
asserts:
|
|
||||||
- isNull:
|
|
||||||
path: spec.ipFamilyPolicy
|
|
||||||
|
|
||||||
- it: should not set ipFamilies by default
|
|
||||||
asserts:
|
|
||||||
- isNull:
|
|
||||||
path: spec.ipFamilies
|
|
||||||
|
|
||||||
- it: should set ipFamilyPolicy when specified
|
|
||||||
set:
|
|
||||||
service.ipFamilyPolicy: PreferDualStack
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilyPolicy
|
|
||||||
value: PreferDualStack
|
|
||||||
|
|
||||||
- it: should support SingleStack policy
|
|
||||||
set:
|
|
||||||
service.ipFamilyPolicy: SingleStack
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilyPolicy
|
|
||||||
value: SingleStack
|
|
||||||
|
|
||||||
- it: should support RequireDualStack policy
|
|
||||||
set:
|
|
||||||
service.ipFamilyPolicy: RequireDualStack
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilyPolicy
|
|
||||||
value: RequireDualStack
|
|
||||||
|
|
||||||
- it: should set ipFamilies for IPv4 only
|
|
||||||
set:
|
|
||||||
service.ipFamilies:
|
|
||||||
- IPv4
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilies[0]
|
|
||||||
value: IPv4
|
|
||||||
|
|
||||||
- it: should set ipFamilies for IPv6 only
|
|
||||||
set:
|
|
||||||
service.ipFamilies:
|
|
||||||
- IPv6
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilies[0]
|
|
||||||
value: IPv6
|
|
||||||
|
|
||||||
- it: should set ipFamilies for dual-stack IPv4 primary
|
|
||||||
set:
|
|
||||||
service.ipFamilies:
|
|
||||||
- IPv4
|
|
||||||
- IPv6
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilies[0]
|
|
||||||
value: IPv4
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilies[1]
|
|
||||||
value: IPv6
|
|
||||||
|
|
||||||
- it: should set ipFamilies for dual-stack IPv6 primary
|
|
||||||
set:
|
|
||||||
service.ipFamilies:
|
|
||||||
- IPv6
|
|
||||||
- IPv4
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilies[0]
|
|
||||||
value: IPv6
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilies[1]
|
|
||||||
value: IPv4
|
|
||||||
|
|
||||||
- it: should work with PreferDualStack and both families
|
|
||||||
set:
|
|
||||||
service.ipFamilyPolicy: PreferDualStack
|
|
||||||
service.ipFamilies:
|
|
||||||
- IPv4
|
|
||||||
- IPv6
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilyPolicy
|
|
||||||
value: PreferDualStack
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilies[0]
|
|
||||||
value: IPv4
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilies[1]
|
|
||||||
value: IPv6
|
|
||||||
|
|
||||||
- it: should work with RequireDualStack and both families
|
|
||||||
set:
|
|
||||||
service.ipFamilyPolicy: RequireDualStack
|
|
||||||
service.ipFamilies:
|
|
||||||
- IPv6
|
|
||||||
- IPv4
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilyPolicy
|
|
||||||
value: RequireDualStack
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilies[0]
|
|
||||||
value: IPv6
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilies[1]
|
|
||||||
value: IPv4
|
|
||||||
|
|
||||||
- it: should work with SingleStack IPv6 only
|
|
||||||
set:
|
|
||||||
service.ipFamilyPolicy: SingleStack
|
|
||||||
service.ipFamilies:
|
|
||||||
- IPv6
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilyPolicy
|
|
||||||
value: SingleStack
|
|
||||||
- equal:
|
|
||||||
path: spec.ipFamilies[0]
|
|
||||||
value: IPv6
|
|
||||||
@@ -0,0 +1,465 @@
|
|||||||
|
suite: test service
|
||||||
|
templates:
|
||||||
|
- service.yaml
|
||||||
|
tests:
|
||||||
|
# =============================================================================
|
||||||
|
# BASIC SERVICE DEFAULTS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- it: should create Service by default
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 1
|
||||||
|
- isKind:
|
||||||
|
of: Service
|
||||||
|
- isAPIVersion:
|
||||||
|
of: v1
|
||||||
|
|
||||||
|
- it: should have correct default name
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: metadata.name
|
||||||
|
value: RELEASE-NAME-jellyfin
|
||||||
|
|
||||||
|
- it: should use ClusterIP type by default
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.type
|
||||||
|
value: ClusterIP
|
||||||
|
|
||||||
|
- it: should expose port 8096 by default
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].port
|
||||||
|
value: 8096
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].targetPort
|
||||||
|
value: http
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].protocol
|
||||||
|
value: TCP
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].name
|
||||||
|
value: http
|
||||||
|
|
||||||
|
- it: should have correct pod selector labels
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.selector.app\.kubernetes\.io/name
|
||||||
|
value: jellyfin
|
||||||
|
- equal:
|
||||||
|
path: spec.selector.app\.kubernetes\.io/instance
|
||||||
|
value: RELEASE-NAME
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# SERVICE TYPE TESTS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- it: should support ClusterIP type explicitly
|
||||||
|
set:
|
||||||
|
service.type: ClusterIP
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.type
|
||||||
|
value: ClusterIP
|
||||||
|
- isNull:
|
||||||
|
path: spec.clusterIP
|
||||||
|
|
||||||
|
- it: should support NodePort type
|
||||||
|
set:
|
||||||
|
service.type: NodePort
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.type
|
||||||
|
value: NodePort
|
||||||
|
|
||||||
|
- it: should support LoadBalancer type
|
||||||
|
set:
|
||||||
|
service.type: LoadBalancer
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.type
|
||||||
|
value: LoadBalancer
|
||||||
|
|
||||||
|
- it: should support ExternalName type
|
||||||
|
set:
|
||||||
|
service.type: ExternalName
|
||||||
|
service.externalName: jellyfin.example.com
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.type
|
||||||
|
value: ExternalName
|
||||||
|
- equal:
|
||||||
|
path: spec.externalName
|
||||||
|
value: jellyfin.example.com
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# PORT CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- it: should set custom port
|
||||||
|
set:
|
||||||
|
service.port: 9096
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].port
|
||||||
|
value: 9096
|
||||||
|
|
||||||
|
- it: should set custom nodePort when type is NodePort
|
||||||
|
set:
|
||||||
|
service.type: NodePort
|
||||||
|
service.nodePort: 30096
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].nodePort
|
||||||
|
value: 30096
|
||||||
|
|
||||||
|
- it: should not set nodePort when type is ClusterIP
|
||||||
|
set:
|
||||||
|
service.type: ClusterIP
|
||||||
|
service.nodePort: 30096
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.ports[0].nodePort
|
||||||
|
|
||||||
|
# Port range validation would be done by values.schema.json
|
||||||
|
# Here we just test that values are applied correctly
|
||||||
|
- it: should accept nodePort in valid range (30000-32767)
|
||||||
|
set:
|
||||||
|
service.type: NodePort
|
||||||
|
service.nodePort: 30000
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].nodePort
|
||||||
|
value: 30000
|
||||||
|
|
||||||
|
- it: should accept nodePort at upper range
|
||||||
|
set:
|
||||||
|
service.type: NodePort
|
||||||
|
service.nodePort: 32767
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].nodePort
|
||||||
|
value: 32767
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# LOADBALANCER CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- it: should set loadBalancerIP when specified
|
||||||
|
set:
|
||||||
|
service.type: LoadBalancer
|
||||||
|
service.loadBalancerIP: 203.0.113.42
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.loadBalancerIP
|
||||||
|
value: 203.0.113.42
|
||||||
|
|
||||||
|
- it: should set loadBalancerClass when specified
|
||||||
|
set:
|
||||||
|
service.type: LoadBalancer
|
||||||
|
service.loadBalancerClass: metallb
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.loadBalancerClass
|
||||||
|
value: metallb
|
||||||
|
|
||||||
|
- it: should set loadBalancerSourceRanges when specified
|
||||||
|
set:
|
||||||
|
service.type: LoadBalancer
|
||||||
|
service.loadBalancerSourceRanges:
|
||||||
|
- 10.0.0.0/8
|
||||||
|
- 192.168.0.0/16
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.loadBalancerSourceRanges
|
||||||
|
content: 10.0.0.0/8
|
||||||
|
- contains:
|
||||||
|
path: spec.loadBalancerSourceRanges
|
||||||
|
content: 192.168.0.0/16
|
||||||
|
|
||||||
|
- it: should not set loadBalancerIP when type is ClusterIP
|
||||||
|
set:
|
||||||
|
service.type: ClusterIP
|
||||||
|
service.loadBalancerIP: 203.0.113.42
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.loadBalancerIP
|
||||||
|
|
||||||
|
- it: should set all loadBalancer options together
|
||||||
|
set:
|
||||||
|
service.type: LoadBalancer
|
||||||
|
service.loadBalancerIP: 203.0.113.42
|
||||||
|
service.loadBalancerClass: metallb
|
||||||
|
service.loadBalancerSourceRanges:
|
||||||
|
- 10.0.0.0/8
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.loadBalancerIP
|
||||||
|
value: 203.0.113.42
|
||||||
|
- equal:
|
||||||
|
path: spec.loadBalancerClass
|
||||||
|
value: metallb
|
||||||
|
- contains:
|
||||||
|
path: spec.loadBalancerSourceRanges
|
||||||
|
content: 10.0.0.0/8
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ANNOTATIONS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- it: should not have annotations by default
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: metadata.annotations
|
||||||
|
|
||||||
|
- it: should add custom annotations
|
||||||
|
set:
|
||||||
|
service.annotations:
|
||||||
|
service.beta.kubernetes.io/aws-load-balancer-type: nlb
|
||||||
|
external-dns.alpha.kubernetes.io/hostname: jellyfin.example.com
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: metadata.annotations.service\.beta\.kubernetes\.io/aws-load-balancer-type
|
||||||
|
value: nlb
|
||||||
|
- equal:
|
||||||
|
path: metadata.annotations.external-dns\.alpha\.kubernetes\.io/hostname
|
||||||
|
value: jellyfin.example.com
|
||||||
|
|
||||||
|
- it: should support empty annotations object
|
||||||
|
set:
|
||||||
|
service.annotations: {}
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: metadata.annotations
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# IPv4/IPv6 DUAL-STACK TESTS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
- it: should not set ipFamilyPolicy by default
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
|
||||||
|
- it: should not set ipFamilies by default
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.ipFamilies
|
||||||
|
|
||||||
|
- it: should set ipFamilyPolicy when specified
|
||||||
|
set:
|
||||||
|
service.ipFamilyPolicy: PreferDualStack
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
value: PreferDualStack
|
||||||
|
|
||||||
|
- it: should support SingleStack policy
|
||||||
|
set:
|
||||||
|
service.ipFamilyPolicy: SingleStack
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
value: SingleStack
|
||||||
|
|
||||||
|
- it: should support RequireDualStack policy
|
||||||
|
set:
|
||||||
|
service.ipFamilyPolicy: RequireDualStack
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
value: RequireDualStack
|
||||||
|
|
||||||
|
- it: should set ipFamilies for IPv4 only
|
||||||
|
set:
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv4
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv4
|
||||||
|
|
||||||
|
- it: should set ipFamilies for IPv6 only
|
||||||
|
set:
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv6
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv6
|
||||||
|
|
||||||
|
- it: should set ipFamilies for dual-stack IPv4 primary
|
||||||
|
set:
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv4
|
||||||
|
- IPv6
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv4
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[1]
|
||||||
|
value: IPv6
|
||||||
|
|
||||||
|
- it: should set ipFamilies for dual-stack IPv6 primary
|
||||||
|
set:
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv6
|
||||||
|
- IPv4
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv6
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[1]
|
||||||
|
value: IPv4
|
||||||
|
|
||||||
|
- it: should work with PreferDualStack and both families
|
||||||
|
set:
|
||||||
|
service.ipFamilyPolicy: PreferDualStack
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv4
|
||||||
|
- IPv6
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
value: PreferDualStack
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv4
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[1]
|
||||||
|
value: IPv6
|
||||||
|
|
||||||
|
- it: should work with RequireDualStack and both families
|
||||||
|
set:
|
||||||
|
service.ipFamilyPolicy: RequireDualStack
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv6
|
||||||
|
- IPv4
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
value: RequireDualStack
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv6
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[1]
|
||||||
|
value: IPv4
|
||||||
|
|
||||||
|
- it: should work with SingleStack IPv6 only
|
||||||
|
set:
|
||||||
|
service.ipFamilyPolicy: SingleStack
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv6
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
value: SingleStack
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv6
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# EDGE CASES AND VALIDATIONS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# LoadBalancer without explicit IP (valid use case)
|
||||||
|
- it: should create LoadBalancer without loadBalancerIP
|
||||||
|
set:
|
||||||
|
service.type: LoadBalancer
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.type
|
||||||
|
value: LoadBalancer
|
||||||
|
- isNull:
|
||||||
|
path: spec.loadBalancerIP
|
||||||
|
|
||||||
|
# NodePort without explicit nodePort (auto-assign)
|
||||||
|
- it: should create NodePort without explicit nodePort
|
||||||
|
set:
|
||||||
|
service.type: NodePort
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.type
|
||||||
|
value: NodePort
|
||||||
|
- isNull:
|
||||||
|
path: spec.ports[0].nodePort
|
||||||
|
|
||||||
|
# ExternalName requires externalName field
|
||||||
|
- it: should set externalName for ExternalName type
|
||||||
|
set:
|
||||||
|
service.type: ExternalName
|
||||||
|
service.externalName: external.service.com
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.type
|
||||||
|
value: ExternalName
|
||||||
|
- equal:
|
||||||
|
path: spec.externalName
|
||||||
|
value: external.service.com
|
||||||
|
|
||||||
|
# Multiple loadBalancerSourceRanges
|
||||||
|
- it: should support multiple loadBalancerSourceRanges
|
||||||
|
set:
|
||||||
|
service.type: LoadBalancer
|
||||||
|
service.loadBalancerSourceRanges:
|
||||||
|
- 10.0.0.0/8
|
||||||
|
- 172.16.0.0/12
|
||||||
|
- 192.168.0.0/16
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.loadBalancerSourceRanges
|
||||||
|
count: 3
|
||||||
|
|
||||||
|
# Regression: verify service always has one port
|
||||||
|
- it: should always have exactly one port defined
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.ports
|
||||||
|
count: 1
|
||||||
|
|
||||||
|
# Regression: verify port name is always http
|
||||||
|
- it: should always name port as http
|
||||||
|
set:
|
||||||
|
service.port: 9096
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].name
|
||||||
|
value: http
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].targetPort
|
||||||
|
value: http
|
||||||
|
|
||||||
|
# Combining multiple settings
|
||||||
|
- it: should combine custom port with NodePort and annotations
|
||||||
|
set:
|
||||||
|
service.type: NodePort
|
||||||
|
service.port: 9096
|
||||||
|
service.nodePort: 31096
|
||||||
|
service.annotations:
|
||||||
|
custom: annotation
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.type
|
||||||
|
value: NodePort
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].port
|
||||||
|
value: 9096
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].nodePort
|
||||||
|
value: 31096
|
||||||
|
- equal:
|
||||||
|
path: metadata.annotations.custom
|
||||||
|
value: annotation
|
||||||
|
|
||||||
|
# Regression: verify protocol is always TCP
|
||||||
|
- it: should always use TCP protocol
|
||||||
|
set:
|
||||||
|
service.port: 9096
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ports[0].protocol
|
||||||
|
value: TCP
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
suite: test startup probe
|
|
||||||
templates:
|
|
||||||
- deployment.yaml
|
|
||||||
tests:
|
|
||||||
- it: should have startup probe by default
|
|
||||||
asserts:
|
|
||||||
- isNotNull:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe
|
|
||||||
|
|
||||||
- it: should use tcpSocket by default
|
|
||||||
asserts:
|
|
||||||
- isNotNull:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.tcpSocket
|
|
||||||
- equal:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.tcpSocket.port
|
|
||||||
value: http
|
|
||||||
|
|
||||||
- it: should have default timing values
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.initialDelaySeconds
|
|
||||||
value: 0
|
|
||||||
- equal:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.periodSeconds
|
|
||||||
value: 10
|
|
||||||
- equal:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.failureThreshold
|
|
||||||
value: 30
|
|
||||||
|
|
||||||
- it: should allow custom initialDelaySeconds
|
|
||||||
set:
|
|
||||||
startupProbe.initialDelaySeconds: 5
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.initialDelaySeconds
|
|
||||||
value: 5
|
|
||||||
|
|
||||||
- it: should allow custom periodSeconds
|
|
||||||
set:
|
|
||||||
startupProbe.periodSeconds: 15
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.periodSeconds
|
|
||||||
value: 15
|
|
||||||
|
|
||||||
- it: should allow custom failureThreshold
|
|
||||||
set:
|
|
||||||
startupProbe.failureThreshold: 60
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.failureThreshold
|
|
||||||
value: 60
|
|
||||||
|
|
||||||
- it: should support httpGet probe
|
|
||||||
set:
|
|
||||||
startupProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /health
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: 0
|
|
||||||
periodSeconds: 10
|
|
||||||
failureThreshold: 30
|
|
||||||
asserts:
|
|
||||||
- isNotNull:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.httpGet
|
|
||||||
- equal:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.httpGet.path
|
|
||||||
value: /health
|
|
||||||
- equal:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.httpGet.port
|
|
||||||
value: http
|
|
||||||
|
|
||||||
- it: should support custom port
|
|
||||||
set:
|
|
||||||
startupProbe.tcpSocket.port: 9000
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.tcpSocket.port
|
|
||||||
value: 9000
|
|
||||||
|
|
||||||
- it: should calculate correct timeout window
|
|
||||||
set:
|
|
||||||
startupProbe.periodSeconds: 10
|
|
||||||
startupProbe.failureThreshold: 30
|
|
||||||
asserts:
|
|
||||||
- equal:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.periodSeconds
|
|
||||||
value: 10
|
|
||||||
- equal:
|
|
||||||
path: spec.template.spec.containers[0].startupProbe.failureThreshold
|
|
||||||
value: 30
|
|
||||||
# Total startup time allowed: 10 * 30 = 300 seconds (5 minutes)
|
|
||||||
Reference in new issue
Block a user