Files
cozystack/packages/apps/vm-instance/tests/resources_values_test.yaml
Aleksei Sviridkin 35df310de1 fix(vm-instance)!: refuse guest memory below KubeVirt's 1M floor
The memory guard refused only zero and negative amounts, while KubeVirt
admission refuses a non-zero amount below 1M. A value such as 500m or
1Ki rendered cleanly and then failed when the VirtualMachine was
applied, two hops away from the value that caused it. The render now
refuses it with the reason.

This is breaking: a memory above zero and below 1M rendered before and
no longer does. Such a VM could not be admitted by KubeVirt either.

Assisted-by: LLM
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-09-29 12:45:08 +03:00

442 lines
12 KiB
YAML

suite: vm-instance resources values
# resources.cpu and resources.sockets are typed as quantities, but they land in
# domain.cpu.cores and domain.cpu.sockets, which KubeVirt declares as uint32.
# Only a whole number has a meaning there, so anything else has to stop the
# render rather than truncate to 0 and leave KubeVirt to boot one core. Memory
# is a quantity on the KubeVirt side too, but KubeVirt admission refuses a
# non-zero amount below 1M and a zero or negative amount sizes nothing, so
# both stop the render as well.
templates:
- templates/vm.yaml
release:
name: test-vm
namespace: tenant-test
set:
fullnameOverride: test-vm
_cluster: {}
instanceType: ""
instanceProfile: ""
tests:
- it: renders a quoted whole cpu as an integer core count
set:
resources:
cpu: "2"
sockets: 1
memory: 8Gi
asserts:
- equal:
path: spec.template.spec.domain.cpu.cores
value: 2
- it: renders an unquoted integer cpu as the same core count
set:
resources:
cpu: 4
sockets: 1
memory: 8Gi
asserts:
- equal:
path: spec.template.spec.domain.cpu.cores
value: 4
- it: renders a whole float cpu as an integer core count
set:
resources:
cpu: 2.0
sockets: 1
memory: 8Gi
asserts:
- equal:
path: spec.template.spec.domain.cpu.cores
value: 2
- it: renders a quoted whole decimal cpu as the same core count
set:
resources:
cpu: "2.0"
sockets: 1
memory: 8Gi
asserts:
- equal:
path: spec.template.spec.domain.cpu.cores
value: 2
- it: renders an explicit plus sign on cpu as the same core count
set:
resources:
cpu: "+2"
sockets: 1
memory: 8Gi
asserts:
- equal:
path: spec.template.spec.domain.cpu.cores
value: 2
- it: renders an exponent spelling of cpu as the core count it decodes to
set:
resources:
cpu: "1e1"
sockets: 1
memory: 8Gi
asserts:
- equal:
path: spec.template.spec.domain.cpu.cores
value: 10
- it: renders a trailing-dot spelling of cpu as the core count it decodes to
set:
resources:
cpu: "2."
sockets: 1
memory: 8Gi
asserts:
- equal:
path: spec.template.spec.domain.cpu.cores
value: 2
- it: refuses a millicore cpu instead of truncating it to no cores
set:
resources:
cpu: 500m
sockets: 1
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.cpu \(500m\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.cores,'
- it: refuses a millicore spelling of whole cores
set:
resources:
cpu: 2000m
sockets: 1
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.cpu \(2000m\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.cores,'
- it: refuses a fractional cpu
set:
resources:
cpu: "1.5"
sockets: 1
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.cpu \(1\.5\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.cores,'
- it: refuses an unquoted zero cpu instead of treating it as unset
set:
resources:
cpu: 0
sockets: 1
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.cpu \(read as 0\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.cores,'
- it: refuses a quoted zero cpu
set:
resources:
cpu: "0"
sockets: 1
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.cpu \(0\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.cores,'
- it: refuses a negative cpu
set:
resources:
cpu: "-2"
sockets: 1
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.cpu \(-2\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.cores,'
- it: refuses a cpu with a leading zero, which YAML reads as octal
set:
resources:
cpu: "010"
sockets: 1
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.cpu \(010\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.cores,'
- it: renders the largest cpu that fits in uint32
set:
resources:
cpu: "4294967295"
sockets: 1
memory: 8Gi
asserts:
- equal:
path: spec.template.spec.domain.cpu.cores
value: 4294967295
- it: refuses a cpu past the uint32 range
set:
resources:
cpu: "4294967296"
sockets: 1
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.cpu \(4294967296\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.cores,'
- it: renders a quoted whole sockets as an integer socket count
set:
resources:
cpu: 4
sockets: "2"
memory: 8Gi
asserts:
- equal:
path: spec.template.spec.domain.cpu.sockets
value: 2
- it: renders a whole float sockets as an integer socket count
set:
resources:
cpu: 4
sockets: 2.0
memory: 8Gi
asserts:
- equal:
path: spec.template.spec.domain.cpu.sockets
value: 2
- it: refuses a millicore sockets instead of truncating it to none
set:
resources:
cpu: 4
sockets: 500m
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.sockets \(500m\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.sockets,'
- it: refuses a fractional sockets
set:
resources:
cpu: 4
sockets: "1.5"
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.sockets \(1\.5\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.sockets,'
- it: refuses an unquoted zero sockets
set:
resources:
cpu: 4
sockets: 0
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.sockets \(read as 0\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.sockets,'
- it: refuses a sockets with a leading zero
set:
resources:
cpu: 4
sockets: "010"
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.sockets \(010\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.sockets,'
- it: refuses a negative sockets
set:
resources:
cpu: 4
sockets: "-2"
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.sockets \(-2\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.sockets,'
- it: refuses a sockets past the uint32 range
set:
resources:
cpu: 4
sockets: "4294967296"
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.sockets \(4294967296\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.sockets,'
- it: refuses a suffixed cpu even when it is a whole count
set:
resources:
cpu: 1k
sockets: 1
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.cpu \(1k\) must be a positive whole number, such as 2\. It becomes the VM''s domain\.cpu\.cores,'
- it: passes a binary-suffixed memory through unchanged
set:
resources:
cpu: 4
sockets: 1
memory: 8Gi
asserts:
- equal:
path: spec.template.spec.domain.resources.requests.memory
value: 8Gi
- it: passes a fractional memory quantity through unchanged
set:
resources:
cpu: 4
sockets: 1
memory: 1.5Gi
asserts:
- equal:
path: spec.template.spec.domain.resources.requests.memory
value: 1.5Gi
- it: passes an unquoted byte count through unchanged
set:
resources:
cpu: 4
sockets: 1
memory: 8589934592
asserts:
- equal:
path: spec.template.spec.domain.resources.requests.memory
value: 8589934592
- it: refuses a quoted zero memory instead of requesting none
set:
resources:
cpu: 4
sockets: 1
memory: "0"
asserts:
- failedTemplate:
errorPattern: '^resources\.memory \(0\) must be at least 1M'
- it: refuses an unquoted zero memory instead of treating it as unset
set:
resources:
cpu: 4
sockets: 1
memory: 0
asserts:
- failedTemplate:
errorPattern: '^resources\.memory \(read as 0\) must be at least 1M'
- it: refuses a zero memory written with a suffix
set:
resources:
cpu: 4
sockets: 1
memory: 0Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.memory \(0Gi\) must be at least 1M'
- it: refuses a negative memory
set:
resources:
cpu: 4
sockets: 1
memory: "-1Gi"
asserts:
- failedTemplate:
errorPattern: '^resources\.memory \(-1Gi\) must be at least 1M'
- it: refuses a millibyte memory that KubeVirt admission would refuse
set:
resources:
cpu: 4
sockets: 1
memory: 500m
asserts:
- failedTemplate:
errorPattern: '^resources\.memory \(500m\) must be at least 1M, such as 8Gi\. KubeVirt refuses a non-zero amount below 1M,'
- it: refuses a binary-suffixed memory below 1M
set:
resources:
cpu: 4
sockets: 1
memory: 976Ki
asserts:
- failedTemplate:
errorPattern: '^resources\.memory \(976Ki\) must be at least 1M'
- it: refuses an unquoted byte count one below 1M
set:
resources:
cpu: 4
sockets: 1
memory: 999999
asserts:
- failedTemplate:
errorPattern: '^resources\.memory \(read as 999999\) must be at least 1M'
- it: renders memory of exactly 1M
set:
resources:
cpu: 4
sockets: 1
memory: 1M
asserts:
- equal:
path: spec.template.spec.domain.resources.requests.memory
value: 1M
- it: renders a binary-suffixed memory of exactly 1M
set:
resources:
cpu: 4
sockets: 1
memory: 976.5625Ki
asserts:
- equal:
path: spec.template.spec.domain.resources.requests.memory
value: 976.5625Ki
- it: renders an unquoted byte count of exactly 1M
set:
resources:
cpu: 4
sockets: 1
memory: 1000000
asserts:
- equal:
path: spec.template.spec.domain.resources.requests.memory
value: 1000000
# An unquoted number reaches the chart already decoded, so its spelling is
# gone. The error says so, and prints the number in plain digits rather than
# the exponent form a large float formats to.
- it: prints a large unquoted cpu in plain digits
set:
resources:
cpu: 4294967296
sockets: 1
memory: 8Gi
asserts:
- failedTemplate:
errorPattern: '^resources\.cpu \(read as 4294967296\) must be a positive whole number'
# A cpu or sockets on its own emits no domain.cpu, so beside an instance type
# it used to be ignored whatever it held. A value that cannot be a count is
# refused there as well, before it can wait for the day sockets is filled in.
- it: refuses a millicore cpu on its own beside an instance type
set:
instanceType: u1.medium
resources:
cpu: 500m
asserts:
- failedTemplate:
errorPattern: '^resources\.cpu \(500m\) must be a positive whole number'