- name: Deploy+Verify 04-12 nodejs TLS Ingress hosts: k3s_server become: true run_once: true vars: k3s_kubeconfig: /etc/rancher/k3s/k3s.yaml verify_teardown: "{{ (VERIFY_TEARDOWN | default('1')) | string }}" nodejs_manifest_src: "{{ playbook_dir }}/../../files/04-12/04-12-nodejs-demo.yaml" nodejs_manifest_dest: /tmp/nodejs-demo-04-12.yaml # extra var 或环境变量(与 04-07 一致) _nodejs_tls_entry_base: "{{ NODEJS_TLS_ENTRY_BASE | default(lookup('env', 'NODEJS_TLS_ENTRY_BASE') | default('', true), true) | trim }}" _nodejs_tls_host: "{{ NODEJS_TLS_HOST | default(lookup('env', 'NODEJS_TLS_HOST') | default('', true), true) | trim }}" create_nodejs_demo_tls_secret: "{{ (lookup('env', 'CREATE_NODEJS_DEMO_TLS_SECRET') | default('0', true) | trim) == '1' }}" # 与清单 Ingress 默认 host 对齐;未 export NODEJS_TLS_* 时仍可用自签 + 默认 host nodejs_verify_entry_base: "{{ (_nodejs_tls_entry_base | length > 0) | ternary(_nodejs_tls_entry_base, 'https://app.example.local') }}" nodejs_verify_path: "/api/" nodejs_verify_host: "{{ (_nodejs_tls_host | length > 0) | ternary(_nodejs_tls_host, 'app.example.local') }}" # 自签实验室路径或显式 NODEJS_TLS_* 时跑 openssl/curl nodejs_http_check_enabled: "{{ (create_nodejs_demo_tls_secret | bool) or ((_nodejs_tls_entry_base | length > 0) and (_nodejs_tls_host | length > 0)) }}" _nodejs_tls_authority: "{{ nodejs_verify_entry_base | trim | regex_replace('^https?://', '') | regex_replace('/.*$', '') }}" nodejs_tls_connect_host: "{{ _nodejs_tls_authority | regex_replace(':([0-9]+)$', '') }}" nodejs_tls_connect_port: "{{ (_nodejs_tls_authority | regex_replace('^[^:]*:', '') | int) if (':' in _nodejs_tls_authority) else 443 }}" tasks: - name: Check TLS secret exists (nodejs-demo-tls) ansible.builtin.shell: | set -e KUBECONFIG={{ k3s_kubeconfig }} kubectl -n default get secret nodejs-demo-tls args: executable: /bin/bash changed_when: false failed_when: false register: nodejs_tls_secret_check - name: Create self-signed nodejs-demo-tls (lab opt-in, matches Ingress host in manifest) when: - nodejs_tls_secret_check.rc != 0 - create_nodejs_demo_tls_secret | bool ansible.builtin.shell: | set -euo pipefail export KUBECONFIG={{ k3s_kubeconfig }} HOST={{ nodejs_verify_host | quote }} TMP=$(mktemp -d) trap 'rm -rf "$TMP"' EXIT echo "[OC-ASSERT] assertion=nodejs_tls_selfsigned phase=cluster probe=openssl_san host=${HOST}" if openssl req -help 2>&1 | grep -q -- -addext; then openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout "$TMP/tls.key" -out "$TMP/tls.crt" \ -subj "/CN=${HOST}" \ -addext "subjectAltName=DNS:${HOST}" else : >"$TMP/cnf" printf '%s\n' '[req]' 'distinguished_name = req_distinguished_name' 'x509_extensions = v3_ca' 'prompt = no' >>"$TMP/cnf" printf '%s\n' '[req_distinguished_name]' "CN = ${HOST}" >>"$TMP/cnf" printf '%s\n' '[v3_ca]' 'subjectAltName = @alt_names' '[alt_names]' "DNS.1 = ${HOST}" >>"$TMP/cnf" openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout "$TMP/tls.key" -out "$TMP/tls.crt" \ -config "$TMP/cnf" -extensions v3_ca fi kubectl create secret tls nodejs-demo-tls \ --cert="$TMP/tls.crt" --key="$TMP/tls.key" -n default \ --dry-run=client -o yaml | kubectl apply -f - args: executable: /bin/bash register: nodejs_tls_autocreate changed_when: true - name: Remember autocreated TLS secret for teardown ansible.builtin.set_fact: nodejs_tls_secret_autocreated: true when: - create_nodejs_demo_tls_secret | bool - nodejs_tls_autocreate is defined - not (nodejs_tls_autocreate.skipped | default(false)) - (nodejs_tls_autocreate.rc | default(1)) == 0 - name: Re-read TLS secret (after optional create) ansible.builtin.shell: | set -e KUBECONFIG={{ k3s_kubeconfig }} kubectl -n default get secret nodejs-demo-tls args: executable: /bin/bash changed_when: false failed_when: false register: nodejs_tls_secret_check - name: Gate when TLS secret missing when: nodejs_tls_secret_check.rc != 0 ansible.builtin.include_role: name: verify_common tasks_from: gate-debug-end-play.yml vars: verify_gate_message: "[GATE] skipped doc_id=04-12 reason=missing_tls_secret secret=nodejs-demo-tls namespace=default hint=export CREATE_NODEJS_DEMO_TLS_SECRET=1 or kubectl create secret tls" - name: Copy nodejs demo manifest ansible.builtin.copy: src: "{{ nodejs_manifest_src }}" dest: "{{ nodejs_manifest_dest }}" mode: "0644" - name: Apply nodejs demo manifest ansible.builtin.shell: | set -e KUBECONFIG={{ k3s_kubeconfig }} kubectl apply -f {{ nodejs_manifest_dest }} args: executable: /bin/bash changed_when: true - name: Rollout status nodejs-demo ansible.builtin.include_role: name: verify_common tasks_from: kubectl-rollout-status.yml vars: verify_rollout_ref: deployment/nodejs-demo - name: Assert Service targetPort matches expected (optional) when: nodejs_expected_target_port is defined and (nodejs_expected_target_port | int) > 0 ansible.builtin.shell: | set -euo pipefail exp="{{ nodejs_expected_target_port | int }}" got=$(KUBECONFIG={{ k3s_kubeconfig }} kubectl get svc nodejs-demo -n default -o jsonpath='{.spec.ports[0].targetPort}') echo "svc/nodejs-demo targetPort=$got expected=$exp" test "$got" = "$exp" args: executable: /bin/bash changed_when: false - name: Assert Endpoints exist ansible.builtin.include_role: name: verify_common tasks_from: kubectl-endpoints-ready.yml vars: verify_endpoints_service: nodejs-demo verify_endpoints_assertion_label: nodejs_demo_endpoints - name: TLS SNI + certificate subject (openssl) when: nodejs_http_check_enabled | default(false) ansible.builtin.include_role: name: verify_common tasks_from: tls-openssl-sni.yml vars: verify_tls_connect_host: "{{ nodejs_tls_connect_host }}" verify_tls_port: "{{ nodejs_tls_connect_port }}" verify_tls_servername: "{{ nodejs_verify_host }}" verify_tls_expect_subject_substring: "{{ nodejs_verify_host }}" verify_tls_assertion_label: nodejs_demo_tls_sni_handshake - name: HTTPS check nodejs demo (path/host) when: nodejs_http_check_enabled | default(false) ansible.builtin.include_role: name: verify_common tasks_from: http-curl-expect.yml vars: verify_http_entry_base: "{{ nodejs_verify_entry_base }}" verify_http_path: "{{ nodejs_verify_path | default('/api/') }}" verify_http_host_header: "{{ nodejs_verify_host }}" verify_http_assertion_label: nodejs_tls_ingress_entry_http verify_http_tls_insecure: "{{ (create_nodejs_demo_tls_secret | bool) or ((lookup('env', 'NODEJS_TLS_CURL_INSECURE') | default('0', true) | trim) == '1') }}" - name: Teardown when VERIFY_TEARDOWN=1 when: verify_teardown == "1" ansible.builtin.shell: | set -e KUBECONFIG={{ k3s_kubeconfig }} kubectl delete -f {{ nodejs_manifest_dest }} --ignore-not-found=true args: executable: /bin/bash changed_when: true - name: Delete autocreated TLS secret on teardown when: - verify_teardown == "1" - nodejs_tls_secret_autocreated | default(false) | bool ansible.builtin.shell: | set -e KUBECONFIG={{ k3s_kubeconfig }} kubectl delete secret nodejs-demo-tls -n default --ignore-not-found=true args: executable: /bin/bash changed_when: true