# CI values for the stalwart install-test. # # WHAT THIS TEST CAN AND CANNOT PROVE — read this before trusting a green run. # # It CANNOT prove a working mail server, and no install-test here could. Since # v0.16 every listener, the blob store, the in-memory store, the TLS object and # the cluster roles live in Stalwart's DATABASE and are created by a human in # the WebUI. Against an empty database there is no SMTP service to test, so a # green run says nothing about mail. # # What it DOES prove is the part that is the chart's own responsibility, and the # first item is the reason this chart is tested rather than excluded: # # 1. THE CONTAINER EXECS AT ALL. The image carries # "setcap cap_net_bind_service=+ep" on its binary, which makes the kernel # fail execve itself when the capability is not in the bounding set. The # first draft of this chart had capabilities.drop: [ALL] with nothing # added and would have failed with "operation not permitted" in every # install - caught by reading the Dockerfile, but exactly the class of # failure an install-test exists to catch rather than reason about. # 2. readOnlyRootFilesystem: true holds with the two image volumes plus /tmp # as emptyDirs, and the init container really can write config.json into # the /etc/stalwart emptyDir. # 3. The rendered config.json parses AS STALWART READS IT, not just as JSON: # the server opens the data store, which means "@type": "PostgreSql", the # integer-millisecond timeout and the authSecret EnvironmentVariable # indirection are all accepted. This is the one check that the password # really arrives without ever being in the ConfigMap. # 4. The Secret key names match what the templates reference, the ConfigMap # mount works, the NodePorts can be allocated, the resource quantities are # valid, the schema accepts a realistic (non-default) values file, and the # NetworkPolicy objects are accepted without cutting off the probes. # # RECOVERY MODE IS ON, and that is not a shortcut - it is the only mode that can # work here. The bootstrap wizard appears only when config.json is ABSENT, and # this chart always renders one; upstream's documented path for a templated # config.json is to start once with STALWART_RECOVERY_MODE=1. Recovery mode # brings up the management HTTP endpoint and keeps the mail ports closed, which # is precisely the reachable surface the probes use. # # THE ONE THING THIS FILE COULD NOT BE VERIFIED AGAINST: whether /healthz/live # and /healthz/ready are served on the RECOVERY listener. The source shows them # handled in the general HTTP request path with no auth and no network # restriction, but recovery mode binds a single listener and skips most config # parsing, and there is no cluster in the authoring environment to try it on. # If the install-test goes red with the pods never becoming Ready, that is the # reason, and the fix is either an exec probe or an entry in # ci/excluded-charts.txt - see the PR for #65. bootstrap: enabled: true logLevel: debug dataStore: postgres: host: postgres database: stalwart username: stalwart tls: # OFF, against the chart's own default of true. The throwaway Postgres in # fixtures.yaml serves no TLS, and the alternative - allowInvalidCerts - # would be worse: it would pass whether or not TLS worked, so a chart # change that broke the TLS path would still go green. A deviation that # fails loudly beats one that hides. enable: false allowInvalidCerts: false secrets: # Materialized by ci/stalwart/fixtures.yaml as ci-stalwart-datastore-secret. dataStoreSecretRef: op://ci/stalwart-datastore # Both deliberately unset: neither is needed to bring a pod up, and leaving # them out exercises the conditional env and OnePasswordItem blocks in the # "absent" direction, which is the shape a minimal install really has. recoveryAdminSecretRef: null s3SecretRef: null ingress: # Left ON although no ingress controller answers in CI: the point is that the # object is accepted and that the per-group http Service it names actually # exists - a selector typo there is otherwise invisible until someone opens # the URL. enabled: true domain: stalwart.ci.example.com clusterIssuer: ci-selfsigned nodeGroup: full certificate: # On, against a STUB CRD (fixtures.yaml). Nothing issues the Secret it names, # which is the interesting case: the volume is mounted optional, so the pods # must start without it. That is what every real first install looks like # before cert-manager has answered the challenge. enabled: true clusterIssuer: ci-selfsigned networkPolicy: # Left ON. probeSources stays empty, so the http rule renders without a # "from" selector - the configuration this chart ships. Whether the policy # actually FILTERS is a property of the cluster's CNI and is not claimed by # this test; what is claimed is that the objects are accepted and that they # do not keep the kubelet's probes from working. enabled: true nodes: full: replicas: 1 exposedPorts: [smtp, submissions, imaps, http] resources: # Small, to stay inside the runner's budget, while still exercising the # limit derivation: 256Mi x limitFactor 3 = 768Mi. requests: cpu: 100m memory: 256Mi ephemeral-storage: 64Mi mx: # Stays at 0, which is also the chart default. Two reasons rather than one: # a second node would need an in-memory store (the render aborts without # one), and the "mx" ClusterRole does not exist in an empty database, so a # running mx pod would fail-open into a second full node and the two would # fight over the same NodePort-backed SMTP Service. The StatefulSet is # still created and the harness still waits on it - a 0-replica rollout # completes immediately, so this covers the explicit-zero path of the # replicas helper. replicas: 0 exposedPorts: [smtp, http]