Files
JamesBhattarai 7fea4a5bcc Chore: Move services into core
- Move app/, worker/, websocket_server/, migrations/, tests and the services to core/, which becomes a self-contained root
- .gitmodules path for the novnc submodule rewritten by git mv.
- Initial Step to split into core and cloud/community
2026-08-17 22:15:19 +05:45
..
2026-08-17 22:15:19 +05:45
2026-08-17 22:15:19 +05:45
2026-08-17 22:15:19 +05:45
2026-08-17 22:15:19 +05:45

External smoke test runner (playbook-driven)

Overview This tool simulates a customer calling the API and validates both control-plane and data-plane behavior:

  • Creates containers (new pod or add to existing pod) and waits for scheduling and running status.
  • Retrieves ingress info (DNS hostname and/or external IP:port) from the pod API and probes connectivity.
  • Validates HTTP responses for expected content.
  • Performs teardown and verifies deletion at the control plane.
  • Includes a negative case for a bogus image that should fail to launch.

Key server routes the tool relies on:

Project files

Install

  • Python 3.10+
  • Dependencies:
    • requests (already required by the API client)
    • pyyaml (for YAML playbooks)

Install PyYAML: pip install pyyaml

Usage

  1. Set required environment variables or edit the playbook:
  • API_BASE_URL (default http://172.17.0.1:5000/api)
  • API_KEY
  • VDC_ID (target Virtual Data Center UUID)
  • WEBSOCKET_SERVER_URL (optional; informational)
  • DNS_REQUIRED=true (the example playbook enforces DNS checks)
  1. Adjust smoke/playbook.example.yaml:
  • api.base_url: the API endpoint (defaults match local dev)
  • api.api_key: provide your API key
  • api.vdc_id: paste a valid VDC UUID
  • defaults.dns_required: keep true to enforce DNS resolution
  • scenarios: three are provided by default:
    • create-nginx (new pod with nginx)
    • add-second-container (adds to the previous pod)
    • negative-image (bogus image expected to fail)
  1. Run the runner: python smoke/runner.py --playbook smoke/playbook.example.yaml --report smoke/out/report.json

  2. Check the summary and report file:

  • Console shows scenarios total/passed/failed.
  • The JSON report contains:
    • scenario-level timings (started_at, allocated_at, running_at, deleted_at)
    • ingress endpoints discovered
    • endpoint probe results (DNS, TCP, HTTP)
    • final pass/fail

Scenarios implemented

  1. create-nginx
  • Creates a new pod with one nginx container exposing internal:80 with external:0 (allocator chooses) and use_dns:true.
  • Waits for allocated → running status.
  • Fetches pod and probes:
    • DNS resolve if dns_required
    • TCP connect to external IP:port (or hostname)
    • HTTP GET / expecting 200 with substring "nginx"
  • Teardown: delete container and wait for deletion.
  1. add-second-container
  • Adds a second container (default nginx) to the pod created in scenario 1.
  • Waits for allocation and running.
  • Probes the new container, and probes the first container still works.
  • Teardown: deletes only the new container.
  1. negative-image
  • Attempts to create a container using a bogus image (thisdoesnotexist.invalid:never).
  • Expects final status launch_failed.
  • Asserts no ingress is assigned.
  • Teardown: deletes the failed container record.

Configuration model (Playbook)

  • See smoke/config.py for the full schema and environment overrides.
  • Playbook keys:
    • api: base_url, api_key, websocket_url, vdc_id
    • defaults: happy_image, alt_image, dns_required, default_domain, cleanup mode, timeouts
    • execution: concurrency, stop_on_first_failure, tags include/exclude
    • scenarios: list of test steps:
      • type: create_container | add_container_to_pod | negative_image
      • image, container_name_prefix, ports, use_existing_pod, expect.{final_status,http}

Notes and next steps

  • The runner validates control-plane and data-plane behaviors. For deeper teardown assertions (e.g., confirm port_forwardings removed post-delete), add an extra step in runner to re-read the pod and assert the deleted container has no remaining port mappings and that TCP fails to connect. The scaffolding makes this straightforward.
  • Container lifecycle validation (restart) can leverage def container_lifecycle_action() via IaaSClient.container_lifecycle() and then assert the worker-reported transition (e.g., pending-restart → running) plus a data-plane blip/resume as needed.
  • To expand coverage: storage volumes, additional networks, VM workflows, pod lifecycle actions, and performance timings.

Example CI invocation

  • Prepare a job with secrets for API_KEY and VDC_ID.
  • Run: export API_KEY=; export VDC_ID=; python smoke/runner.py -p smoke/playbook.example.yaml -r smoke/out/report.json
  • Upload smoke/out/report.json as an artifact.