feat(scenarios): add test_mattermost scenario (vm_ids 1003/3003, port 8065) - #92
Closed
t0kubetsu wants to merge 133 commits into
Closed
feat(scenarios): add test_mattermost scenario (vm_ids 1003/3003, port 8065)#92t0kubetsu wants to merge 133 commits into
t0kubetsu wants to merge 133 commits into
Conversation
…es isolation Implements the network isolation design from issue #20. Adds `scenarios/demo_lab_network/` — a self-contained scenario based on demo_lab that enforces zone separation between the admin (vmbr142) and CTF (vmbr144) bridges via iptables FORWARD chain rules on the Proxmox host. New: 05_network_isolation/stage_00/proxmox_forward_rules.yml - Installs iptables-persistent on pve01 - ACCEPT: admin → ctf (management access) - ACCEPT: ctf → wazuh :1514/:1515 (agent reporting) - DROP: ctf → admin (zone isolation) - DROP: ctf → vmbr0/WAN (air-gap) - Rules are idempotent and persist across reboots via netfilter-persistent All rules implemented as Ansible tasks (not Python API calls), per hyde-repo's recommendation in the issue discussion. Two-zone design (admin/ctf) chosen over three-zone; the dedicated management bridge alternative is documented in README.md as a future option. Closes #20
ansible_connection: local on the proxmox host targets the deployer machine, which doesn't have iptables. Switch to proxmox-cli (SSH to pve01 as root) where iptables is available.
…ress discovery warning
…d packages can reach internet Before this fix, the CTF→WAN FORWARD DROP rule was already in place when the CTF VMs were deployed, blocking DNS and NTP during cloud-init and package installation. This caused the deployment to hang (30-60s DNS timeouts) and ultimately fail at the NTP sync step. New lift/restore pattern: 1. lift_ctf_airgap.yml removes the DROP rule before CTF infrastructure runs 2. 04_ctf_infrastructure/_main.yml runs with internet access 3. 05_network_isolation/_main.yml re-installs the DROP rule after setup Both main.yml and main_vms_only.yml updated. lift_ctf_airgap.yml handles both DROP and REJECT variants (idempotent, state=absent).
…, tcpdump) INSTALL_PACKAGES_UTILS_NETWORK was hardcoded to NO for the vuln-box stage, blocking installation of nmap, tcpdump, net-tools and iputils-ping even though iputils-ping was added to the role. Set to YES so all network diagnostic tools are available on vuln-boxes.
…ir-gap rules
netfilter-persistent can save rules with a newline embedded in the comment
("r42: ctf\n air-gap"), which ansible.builtin.iptables state=absent cannot
match. Add a second comment-based pass for duplicates, then a shell fallback
that loops iptables -D until no more DROP rules on vmbr144→vmbr0 remain.
Introduces the r42topo package skeleton in the playbooks repo: a pure, framework-agnostic pydantic v2 core consumed by the backend API, r42topo's own CLI/TUI, and the (rewrite-in-progress) range42 deployment CLI/TUI. - core/models.py: Topology schema tree (Subnet/Zone/Box/Attachment/ NetworkPolicyRef), extra=forbid, security deny-list guards - core/constants.py: scenario-name regex (matches backend resolver, no dots), catalog-ref/bridge/IP patterns, vm_id bounds, octet rule, injection deny-list - core/io.py: deterministic atomic JSON load/dump (sorted keys, round-trip) - core/errors.py: framework-free exception hierarchy - pyproject.toml: pydantic+pyyaml core deps; typer/textual/dev as extras - tests: 14 tests, RED->GREEN, 94% coverage on core - docs/r42topo-plan.md: full architecture + phased build order Deploy path is _universal-only (rewrite-aligned): the compiler emits topology.json + artifacts; deployment runs via _universal Plan B (external prerequisite), not a materialized scenario dir.
Adds the catalog-template layer and global vm_id/IP allocation validation. - core/catalog_models.py: BoxTemplate, NetworkPolicyTemplate (symbolic zones, services, allow/deny matrix, defaults), SubnetLayout — all extra=forbid - core/catalog.py: load_catalog() resolves <category>/<id>/vX.Y.Z/template.yml, picks highest version, validates, records version+sha256; path posture mirrors backend checks_playbooks.py (regex + strict resolve + is_relative_to + symlink guard) - core/idalloc.py: ReservedIndex parses JSONL _reserved.json; validate_allocation() enforces octet rule, intra-topology dup vm_id/IP, and cross-scenario collisions (own-scenario re-deploy allowed). Read-only/pure. - core/constants.py: TEMPLATE_ID_RE, VERSION_DIR_RE, topology-layer dir/category names - tests: +16 (catalog loader incl. shipped-template validation; idalloc rules) - suite: 30 passing, 93% core coverage
First end-to-end vertical slice: author -> compile -> _universal.
- core/validate.py: semantic checks (zone/subnet refs, IP-in-subnet,
dangling catalog refs)
- core/compiler/network_policy.py: compile symbolic policy + topology bindings
into deterministically ordered FORWARD rules via weight bands (ESTABLISHED ->
service -> zone-accept -> intra -> zone-drop -> air-gap -> default); plus
lint_segmentation() fail-closed checks (FORWARD-only/host-SSH-safe, established
precedes drops, no ACCEPT shadows a deny, air-gap present, terminal default-deny)
- core/compiler/{inventory,scenario_vms,stages}.py: hosts.yml (range42 nested
groups), scenario_vms.json (demo_lab shape), per-zone attachment dispatch
(template defaults + box attachments, deduped)
- core/compiler/__init__.py: compile_topology() orchestrator -> CompileResult
- core/extravars.py: resolve_universal_extravars() — typed r42_* allow-list
- api.py: load_catalog/author_topology/validate_topology/compile_topology/
resolve_universal_extravars — pure adapter for backend + CLI/TUI consumers
- tests: +26 (56 total), 93% coverage
Verified: compiling against the REAL range42-catalog 05_topology_layer and
running the actual _universal stub (origin/feature/gamenet-authoring-v1) passes
green; generated FORWARD table reproduces demo_lab_network's isolation rules.
Thin frontends over the pure core, plus a shared scaffolding helper. - core/scaffold.py: scaffold_topology() builds a minimal valid topology from a subnet_layout + policy (one box per role-matched zone, octet-rule vm_id/IP) — pure, reused by both CLI and TUI - cli.py: Typer app — author / validate / compile / show (--rules); maps core errors to exit codes; console_script `r42topo` - tui/controller.py: pure, framework-free façade (choices, scaffold, validate, save, summary, rules) — unit-tested without the event loop - tui/app.py: Textual view over the controller; console_script `r42topo-tui` - pyproject: add r42topo-tui entry point - tests: +12 (68 total, 90% coverage) incl. CliRunner + headless Textual mount Verified: `r42topo author --layout default-3zone --policy air-gap-ctf` against the real catalog scaffolds a 3-box topology; `show --rules` renders the compiled FORWARD table.
Security (from security-reviewer): - C3 (CRITICAL): close the segmentation-linter bypass — wildcard-source DROP rules were skipped, so `accept ctf->admin` + `drop *->admin` passed clean. Rewrote lint_segmentation to check every compiled DROP (interface-aware, so air-gap rules don't false-positive) against earlier ACCEPTs; excludes the terminal catch-all. Added regression test (bypass caught, air-gap still clean). - C1: deny-list now applied recursively to Attachment.params and NetworkPolicyRef.overrides (Jinja/SSTI surface) via reject_injection_nested - C2: validate wan_interface (IFACE_RE) and service *_ip (ipaddress) overrides; missing/invalid service IP now fails closed instead of broadening the rule to "any destination". CompiledRule interface/port fields gain patterns. - H1/H2/H3: injection guards on Topology.scenario/description/proxmox_node; PROXMOX_NODE_RE requires leading alnum (no empty/leading-dash) - H4: extravars allow-list uses explicit raise, not assert (-O strips asserts) - H5: air-gap zone absent from topology is now flagged (was silently skipped) - M1/M2: MatrixRule src/dst patterns + comment guard; linter terminal-rule check covers reject as well as drop - M4: CLI warns when --reserved is omitted (collision checks disabled) Python quality (from python-reviewer): - load_topology + api.author_topology wrap pydantic.ValidationError as TopologyError (no raw traceback leaks to the CLI) - _fail typed NoReturn; schema_version pinned Literal[1] - scenario_vms.json vms sorted by vm_id (full determinism) - scaffold avoids dup vm_id/IP for repeated roles; drops redundant model_dump - TUI handlers catch TopologyError/ValueError, not bare Exception - idalloc docstring documents the TOCTOU window Suite: 78 tests, 90% coverage.
ECC blueprint skill output — a cold-start plan for r42playbooks, the msfvenom-style scenario generator (list catalog modules -> compose -> generate a demo_lab-shaped scenarios/<name>/). 10 steps (S0 housekeeping, S1 rename r42topo->r42playbooks, S2 spec model, S3 catalog pick/validate, S4 alloc+manifest, S5b verbatim tree, S5a generated-from-manifest + API freeze, S6 CLI, S7 TUI, S8 importable API, S9 ECC review). Adversarially reviewed (architect/opus); CRITICAL+HIGH folded in: secrets/ symlink contract, generated-vs-copied templates/*.j2, populate manifest templates[], resolved template-selection + role->section decisions, name-reference (not copy) catalog contract.
Mechanical rename of the scenario-authoring package to its real identity (what r42deploy/r42runtime will import). Behaviour unchanged. - git mv r42topo -> r42playbooks (all modules + tui + tests imports) - pyproject: name, readme, [project.scripts] (r42playbooks / r42playbooks-tui), packages.find include - update docstrings, README, and the plan's REUSE table paths - .gitignore module comment Suite green (78 passed); import r42playbooks + cli/tui/api entrypoints OK. Step 1 of docs/r42playbooks-plan.md.
Step 2 of docs/r42playbooks-plan.md. The reproducible msfvenom-style 'options' artifact a user composes, written verbatim into every generated scenario. - core/spec.py: ScenarioSpec + BoxSpec (extra='forbid', deny-list guards on free-text name/notes/vars), load_spec / dump_spec_atomic (YAML, deterministic). - core/io.py: extract atomic_write_text helper (reused by spec IO); dump_topology now delegates to it (byte-identical output preserved). - constants.py: BOX_COUNT_MAX bound on count expansion. - BoxSpec.template_vm_id optional override (per plan §7.1, unblocks S4). - tests/test_spec.py (15 cases) + conftest valid_spec_dict/spec_factory fixtures. Full suite green.
Step 3 of docs/r42playbooks-plan.md. The list/validate source of truth. - catalog.py: list_roles() scans 02_ansible_layer/**/roles/ names; list_containers() scans 03_container_layer/docker/_ctf/ for compose-bearing dirs (ref = path under _ctf/). Both read-only with symlink-escape guards; empty when a layer is absent. - Catalog gains roles/containers sets, populated by load_catalog. - validate_refs(spec, catalog): typo guard reporting unknown subnet_layout / network_policy / box template / role / container refs (gamification skipped). - constants.py: 02/03 layer + compose-filename constants. - tests/test_catalog_pick.py (10 cases) + fake_catalog fixture extended with 02/03 layers (real range42-catalog is a separate gitignored repo, never in checkout). Full suite green (103).
Step 4 of docs/r42playbooks-plan.md (Renderer A). Turn a ScenarioSpec into a concrete VM list honouring the project invariants. - core/templates_table.py: the fixed 12-row 9xxx Proxmox template table (verbatim from demo_lab manifest templates[]); select_template() picks lowest matching vm_id for a box spec, with explicit template_vm_id override (§7.1 / H2). - core/allocate.py: place each box in its role's subnet, fill octets from a per-role base, assign vm_id=band*1000+octet (bands 1..8; 9xxx reserved for templates) so the octet rule holds by construction; expand count>1 to <template>-00..; merge template default_attachments + spec additions (names only, §2); skip ids/IPs owned by other scenarios in _reserved.json. manifest_dict/manifest_json emit the demo_lab shape with a populated templates[] (H1: old compiler hard-coded []). - constants.py: ROLE_SUBNET_NAME / ROLE_BASE_OCTET / vm_id band bounds (team defaults to the student subnet per §7.1). - tests/test_allocate.py (19 cases); fake_catalog gains a student-box template. Full suite green (120).
Step 0 housekeeping: re-add /topology.json, /hosts.yml, /expanded.json scratch ignores (present on feat/r42topo-canonical-schema, absent on this branch).
Plan §4.3 prerequisite: the explicit `find scenarios/demo_lab` baseline (110 files) the S5b/S5a golden tests assert the generated tree against. Captured now so the renderer step has a frozen reference shape to mirror.
Render a composed Allocation + ScenarioSpec into scenarios/<name>/ mirroring the demo_lab shape, emitting only the class-(B) files (plan §4.1): per-box stage_00 clone playbooks, stage_01 plays that list catalog roles BY NAME (the catalog↔playbooks name-reference contract, §2), per-box devkits, per-section reinstall scripts, top-level setup/delete/reset scripts, the class-B templates/ files, the vendored 01_init_proxmox/ template-creation subtree (H3), and the originating scenario.r42.yml. Resolved decisions (plan §8 mutation protocol, MUTATED 2026-06-03): - H3: copy a single canonical 01_init_proxmox/ vendored as a package asset (sourced from blank_scenario_2_subnets, matching TEMPLATE_TABLE's vmbr140 management subnet) into every scenario; main.yml imports its two playbooks. - Richness: generate a uniform per-box structure only — NOT demo_lab's group playbooks / group devkits / _testing/ / builder_* (KISS/YAGNI). Does NOT emit (left to S5a class-A): each section's _main.yml, templates/*.j2, manifest/scenario_vms.json. Never creates secrets/ (deploy-time symlink, §4.2). Pure + deterministic: all writes via core.io.atomic_write_text; output depends only on the Allocation + spec. New: core/render.py, core/render_assets.py, assets/scenario/01_init_proxmox/. tests/test_render.py (15 tests). 135 green.
…ss A) Layer the class-(A) files that must reflect THIS composition (never copied from demo_lab) on top of the S5b boilerplate: - manifest/scenario_vms.json (vms[] + populated templates[], H1) - templates/ansible-inventory.j2: per-composition groups (box.inventory_group) + member hosts r42.<vm_name>; proxmox/-cli groups kept verbatim - templates/ssh-config.j2: one Host/Hostname block per VM (M5 naming) + a shared r42.* user/key/ProxyJump block - each section's _main.yml: stage_00 imports with per-VM global_* overrides, then stage_01 imports FREEZE the public API surface (gates S6 ∥ S7): api.render_scenario(spec, *, catalog, dest, reserved=None) -> Path (allocates then renders), plus exported allocate / load_spec / list_roles / list_containers / validate_refs / ScenarioSpec. M5 invariant covered by a golden test: every concrete stage_01 `hosts: r42.<x>` resolves in the generated inventory. New tests/test_render_classa.py (10 tests). 145 green.
Replace the legacy topology-compiler CLI (validate/compile/author/show on a topology.json) with the scenario-generator surface over the frozen api.py: - list <boxes|subnets|policies|roles|containers|scenarios> — enumerate pickable catalog modules, or existing generated scenarios under -o - show <module> — auto-detect + describe one box/subnet/policy/role/container - new <name> --subnet … --policy … --box admin-wazuh --box vuln-box:count=5 [--spec scenario.r42.yml] [-o scenarios/] — compose a ScenarioSpec (flags or --spec, positional name wins) and render a deployable tree; prints the path Thin shell only: validate_refs typo-guards before rendering, TopologyError -> exit 1, no business logic in the CLI. The parked topology compiler stays reachable via api.py for back-compat; it's just no longer a CLI subcommand (pivot: r42playbooks is the generator, not the canonical engine). tests/test_cli.py rewritten for the generator commands (11 tests). 156 green.
Replace the legacy topology-scaffold TUI with the msfvenom-style composer, all logic in the pure (Textual-free) controller so it unit-tests headless: - ScenarioComposerController: layouts/policies/box_templates/roles/containers choices; set_name/set_subnet/set_policy; add_box(template, count)/remove_box/ clear_boxes; build_spec (raises TopologyError if incomplete/invalid); validate() (structural gaps + validate_refs); preview() (allocation preview); generate(dest) -> Path via api.render_scenario. - ScenarioComposerApp: thin view — name + layout/policy selects, add-box row (template + count), Preview/Generate/Clear, output pane. Keeps #scenario / #output ids; errors surfaced in-pane. tests/test_tui.py rewritten (8 tests: controller compose+validate+preview+ generate + mount smoke). core/ stays pure (no textual/typer imports). 155 green.
Make `import r42playbooks` drive generation by import alone (for r42deploy/ r42runtime and the range42 deployment CLI/TUI): - __init__.py re-exports the frozen generator surface from api.py: load_catalog, list_roles, list_containers, validate_refs, load_spec, dump_spec_atomic, allocate, render_scenario, ScenarioSpec, Allocation, Catalog, ReservedIndex (+ legacy Topology, __version__). - README rewritten generator-first: install extras, list/show/new CLI, TUI, and an import-only library example; documents the generated tree + the name-reference contract (secrets/ not generated). - pyproject description updated (generator, not "topology compiler"). tests/test_package_api.py: pins the top-level export contract + import-only roundtrip + core-error propagation (4 tests). 159 green.
ECC python-reviewer + code-reviewer + security-reviewer pass over S1–S8.
Fixes (CRITICAL: none; HIGH + security MEDIUMs resolved):
- render: STAGE01_PLACEHOLDER emitted a bare `[]` that `import_playbook`
rejects ("a play must contain hosts/import_playbook/roles/tasks") — a no-role
box would break the deploy. Now a valid no-op play (hosts + tasks: []).
- render: box `vars` from the spec were validated + carried to AllocatedBox but
silently dropped — now emitted into the stage_01 play `vars:` block.
- render: SCENARIO_NAME_RE permits '/', which spawned malformed nested file
paths (ctf/web1.setup.sh). File prefixes now use the leaf; dir tree keeps the
full name. No write ever escaped dest ('..' was already deny-listed.)
- render_assets.fill(): raise on any leftover @@sentinel@@ (catches a misspelled
key before it ships into a generated file).
- security: Attachment.catalog_ref had no deny-list (CATALOG_REF_RE admits '..');
it is written verbatim as an Ansible role name. Added reject_injection guard.
- catalog: validate_refs now also checks each box template's default_attachments
(the renderer emits them) — closes a silent typo-guard gap.
- catalog: resolved_version/hash raise CatalogNotFoundError not raw KeyError;
_load_category narrows `except Exception` to pydantic ValidationError;
_resolved is field(init=False).
- allocate: AllocatedBox.box_vars is now MappingProxyType (frozen-safe);
manifest_dict -> dict[str, Any].
- cli: default --catalog ../range42-catalog (matches workspace layout, per
user request); _build_spec uses try/else so `data` is always bound.
- spec: dump_spec_atomic/load_spec typed (Path); module-level Path import.
- tui: remove_box rebuilds the list immutably.
- api.render_scenario: docstring notes callers should validate_refs first.
Tests: +9 (placeholder no-op play, box_vars render, slash-name leaf prefix,
fill sentinel guard, catalog_ref traversal reject, validate_refs default-attach
gap, list scenarios CLI, tightened allocator raises to typed errors). 165 green.
Noted for a later step (pre-existing, out of S9 scope): TEMPLATE_TABLE does not
cover every real-catalog box spec (e.g. admin-wazuh 2cpu/4gb/32gb) — surfaces as
a clean ValidationError, not a crash.
Role lives in range42-catalog which is not checked out in CI; stub it so ansible-lint syntax-check passes.
- yaml[indentation]: fix 6-space vars_files indent in stage_00/mon_wazuh.yml
- schema[playbook]: remove null name key in stage_01/deployer_ui.yml
- yaml[truthy]: replace become: yes with become: true in stage_01/mon_wazuh.yml
- key-order[task]: move when: before block: in _r42_admin, _r42_student_box_group, _r42_vuln_box_group
- vars null: revert vars: {} -> vars: in vuln_box_02/03/04 stage_00 (had real vars below)
- vars null: fix vars: -> vars: {} in stage_00 files with comments-only after vars:
- add .ansible/roles/ stubs to work around ansible-lint 26.x mock_roles bug for 3-part dotted role names
# Conflicts: # .gitignore
….1.1
Every scenario (and the render_assets.py generator templates) hardcoded
vm_ci_dns_ips: "1.1.1.1". On lab networks that firewall 1.1.1.1, template
first-boot warm-up can't resolve apt mirrors and 'range42-context deploy'
hangs at the cloud-init auto-poweroff wait.
Use vm_ci_dns_ips: "{{ default_vm_ci_dns_ips | default('1.1.1.1') }}" (same
pattern as the adjacent vm_ci_user/vm_ci_password lines). The default is set
by range42-init.py from the Proxmox node resolver; 1.1.1.1 remains the
fallback for environments where it isn't set.
Scenarios consume vm_ci_dns_ips via {{ default_vm_ci_dns_ips | default('1.1.1.1') }}.
Define that default in the scenario templates so it lands in the right scope:
- ansible-vars.yml -> group_vars/<scenario>/vars.yml (site.yml deploy path)
- vault-example.yml -> the operator-built vault (workspace deploy path, which is
what range42-context deploy actually loads)
Ships 1.1.1.1 as the portable fallback; range42-init.py substitutes the detected
Proxmox node resolver at workspace creation.
Dual-lan test scenario exercising the new admin-rocketchat box template (range42-catalog): a lan1 admin-rocketchat box + a lan2 debian-jump box, generated by the scenario generator. For deploy-testing the Rocket.Chat bootstrap (software.install.rocketchat) on the deployer.
Rebuild the aggregated reservation file from all per-scenario manifests so it includes test_rocketchat (and back-fills demo_lab_network, test_apt_cacher, test_apt_mirror, which were missing — the committed file was stale). test_rocketchat VMs (1002/.150.2, 3002/.151.2) are collision-free. Pre-existing cross-scenario collisions surfaced by the now-in-sync file (test_apt_cacher vs test_apt_mirror, demo_lab vs demo_lab_network, blank_scenario_4 vs demo_lab_network) are NOT addressed here — flagged for separate cleanup.
…lates
The template-create plays read {{ default_vm_ci_dns_ips | default('1.1.1.1') }},
but the generator's ANSIBLE_VARS_YML / VAULT_EXAMPLE_YML templates never defined
the var — so freshly generated scenarios fell back to 1.1.1.1. On networks where
1.1.1.1 is firewalled, cloud-init can't resolve, the template never auto-powers
off, and deploy hangs at "WAIT for cloud-init to auto-poweroff".
Define default_vm_ci_dns_ips in both generator templates (range42-init.py
substitutes the node resolver at workspace creation), matching the hand-fixed
scenarios. Also backfill the already-generated test_rocketchat scenario.
…rrored)
Template build IPs were derived as {template_subnet_prefix}.{box_octet}. Two
boxes in different lab subnets can legitimately share a host octet (e.g. dual-lan
.150.2 + .151.2), which mapped their two DISTINCT templates onto the same
template-subnet IP (both .140.2). The templates boot concurrently during
01_init_proxmox, so the shared IP collided on the bridge: the loser's cloud-init
couldn't reach the network, its apt-get update stalled, the VM never
auto-powered-off, and the deploy hung at "WAIT for cloud-init to auto-poweroff"
(intermittently small vs medium, an ARP race).
Allocate each distinct template a unique octet on the template subnet via
_next_free_octet (skipping the gateway) instead of mirroring the box octet.
- allocate.py: sequential collision-free template IPs (+ _TEMPLATE_IP_BASE)
- tests/test_allocate.py: regression — two boxes sharing an octet across subnets
must yield distinct template IPs
- regenerate test_rocketchat (small template 9321 .140.2 -> .140.3) + _reserved.json
…nct template IPs) Apply the allocate.py template-IP fix to the two apt scenarios: their templates previously shared a build IP (box-octet mirroring), colliding on concurrent boot. Regenerated so each scenario's templates get distinct template-subnet IPs (cacher .140.2/.3; mirror .140.2/.3/.4) + refreshed _reserved.json. Cross-scenario template-subnet overlap (distinct scenarios reusing low .140.x) remains by design — scenarios deploy one at a time (delete-everything between), so it does not cause the concurrent-boot collision that hung deploys.
…ir-gapped range) Regenerate against the updated admin-rocketchat box template, which no longer sets INSTALL_PACKAGES_NTP_AND_UPDATE_TIME. In an egress-filtered range udp/123 is blocked (even the Proxmox node shows clock unsynchronized), so the basic_packages role's hard "wait for NTPSynchronized == yes" can never succeed and failed stage_01. VMs take host (kvm-clock) time instead.
…/3003 Adds the test_mattermost scenario (dual-LAN, admin-mattermost BoxTemplate, port 8065) mirroring the test_nextcloud/test_rocketchat pattern. Registers vm_ids 1003 (lan1-admin-mattermost-00, 192.168.150.3) and 3003 (lan2-debian-jump-00, 192.168.151.3) in _reserved.json.
Contributor
Author
|
Closing: branch was based on dev_ada, carries unrelated dev_ada commits. Replaced by a clean cherry-pick PR. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
scenarios/test_mattermost/— dual-LAN scenario using theadmin-mattermostBoxTemplatelan1-admin-mattermost-00: vm_id 1003, IP 192.168.150.3, vmbr150, port 8065lan2-debian-jump-00: vm_id 3003, IP 192.168.151.3, vmbr151 (jump box)scenarios/_reserved.jsonTest plan
test_mattermost.setup.shon Proxmoxdocker compose ps)