test/e2e/policies.test-suite/balloons/n4c16/test01-basic-placement/code.var.sh
# Test placing containers with and without annotations to correct balloons
# reserved and shared CPUs.

helm-terminate
helm_config=${TEST_DIR}/../../helm-config.yaml helm-launch balloons

cleanup() {
    vm-command "kubectl delete pods -n kube-system pod0; kubectl delete pods -n three --all --now; kubectl delete pods --all --now; kubectl delete namespace three"
    return 0
}

cleanup

# pod0: run on reserved CPUs
CPUREQ="" RESERVED_CPU=1 namespace=kube-system CONTCOUNT=2 create balloons-busybox
report allowed
verify 'cpus["pod0c0"] == cpus["pod0c1"]' \
       'len(cpus["pod0c0"]) == 1'

# pod1: run on the same two-cpu balloon (running containers of a pod
# on the same balloon takes precedence creating new balloons).
CPUREQ="100m" MEMREQ="100M" CPULIM="100m" MEMLIM="100M"
POD_ANNOTATION="balloon.balloons.resource-policy.nri.io: two-cpu" CONTCOUNT=2 create balloons-busybox
report allowed
verify 'cpus["pod1c0"] == cpus["pod1c1"]' \
       'len(cpus["pod1c0"]) == 2'

# pod2: run on a different two-cpu balloon than pod1 (new balloon
# creation is preferred).
CPUREQ="100m" MEMREQ="100M" CPULIM="100m" MEMLIM="100M"
POD_ANNOTATION="balloon.balloons.resource-policy.nri.io: two-cpu" CONTCOUNT=1 create balloons-busybox
report allowed
verify 'len(cpus["pod2c0"]) == 2' \
       'disjoint_sets(cpus["pod2c0"], cpus["pod1c0"])'

# pod3: fits exactly on a single three-cpu instance. No need to create
# new balloon even if spreading pods is preferred.
CPUREQ="1500m" MEMREQ="100M" CPULIM="1500m" MEMLIM="100M"
vm-command "kubectl create namespace three"
namespace="three" CONTCOUNT=2 create balloons-busybox
report allowed
verify 'cpus["pod3c0"] == cpus["pod3c1"]' \
       'len(cpus["pod3c0"]) == 3'

cleanup

# pod4: first two containers to the first instance, 3rd to new four-cpu instance
CPUREQ="3" MEMREQ="" CPULIM="3" MEMLIM=""
POD_ANNOTATION=(
    "balloon.balloons.resource-policy.nri.io: four-cpu"
    "hide-hyperthreads.resource-policy.nri.io/container.pod4c1: \"true\""
)
CONTCOUNT=3 create balloons-busybox
unset POD_ANNOTATION
report allowed
verify 'cpus["pod4c1"].issubset(cpus["pod4c0"])' \
       'disjoint_sets(cpus["pod4c2"], cpus["pod4c0"])' \
       'len(cpus["pod4c0"]) == 6' \
       'len(cpus["pod4c1"]) == 3' \
       'len(cpus["pod4c2"]) == 4'

cleanup

# pod5: all spread containers to their own balloon instances
CPUREQ="1250m" MEMREQ="" CPULIM="" MEMLIM=""
POD_ANNOTATION="balloon.balloons.resource-policy.nri.io: five-cpu" CONTCOUNT=3 create balloons-busybox
report allowed
verify 'disjoint_sets(cpus["pod5c0"], cpus["pod5c1"], cpus["pod5c2"])' \
       'len(cpus["pod5c0"]) == 2' \
       'len(cpus["pod5c1"]) == 2' \
       'len(cpus["pod5c2"]) == 2'

# pod6: ensure that new balloons are created to best effort containers
# when the balloon type prefers new balloons. First, each container
# gets its own balloon, even if there is only one best effort
# container running in an existing balloon.
CPUREQ="" MEMREQ="" CPULIM="" MEMLIM=""
POD_ANNOTATION="balloon.balloons.resource-policy.nri.io: five-cpu" CONTCOUNT=4 create balloons-busybox
report allowed

verify 'set([len(cpus[ctr]) for ctr in cpus if ctr.startswith("pod6c")]) == {1}' \
       'disjoint_sets(*[cpus[ctr] for ctr in cpus if ctr.startswith("pod6c")])' \
       'disjoint_sets(
          set.union(*[cpus[ctr] for ctr in cpus if ctr.startswith("pod6c")]),
          set.union(*[cpus[ctr] for ctr in cpus if ctr.startswith("pod5c")]))'

# pod7: ...continuing the previous: when it's not possible to create
# anymore new balloons to new best effort containers. Start filling
# existing balloons. Balloons of pod5c* containers have only 750 mCPU
# free, so they should not be used. Balloons of pod6c* containers have
# 1000 mCPU free, so pod7c* containers should be spread evenly into
# them.
CPUREQ="" MEMREQ="" CPULIM="" MEMLIM=""
POD_ANNOTATION="balloon.balloons.resource-policy.nri.io: five-cpu" CONTCOUNT=4 create balloons-busybox
report allowed

verify 'set([len(cpus[ctr]) for ctr in cpus if ctr.startswith("pod7c")]) == {1}' \
       'disjoint_sets(cpus["pod7c0"], cpus["pod7c1"], cpus["pod7c2"], cpus["pod7c3"])' \
       'max([len(cpuset) for pod, cpuset in cpus.items()]) == 2' \
       'disjoint_sets(
          set.union(*[cpus[ctr] for ctr in cpus if ctr.startswith("pod7c")]),
          set.union(*[cpus[ctr] for ctr in cpus if ctr.startswith("pod5c")]))'

cleanup

helm-terminate
