Day-0 console¶
Console automation fits pipelines that must validate or bootstrap nodes before management networking exists. No SSH, IP address, or jump host is required — only agent HTTPS and a running node console.
Example pipeline¶
Generic CLI prompt patterns; adjust regexp and steps for your NOS.
# .gitlab-ci.yml (illustrative)
stages: [deploy, bootstrap, verify]
variables:
EVE_IAC_URL: "https://eve.example:8787"
LAB: "./IaC/day0-lab"
deploy_lab:
stage: deploy
script:
- eve-iac --url "$EVE_IAC_URL" --ca-file ca.pem login --username "$EVE_USER" --password "$EVE_PASS"
- eve-iac deploy "$LAB"
- eve-iac exec "$LAB" start --node n_1
bootstrap_console:
stage: bootstrap
script:
- python3 ci/day0_console.py # createConsoleSession → wait → run → close
verify_operational:
stage: verify
script:
- OUT=$(eve-iac console exec "$LAB" n_1 "show version" --json)
- echo "$OUT" | jq -e '.data.text | test("Version")' || exit 1
For production CI, create sessions with create_console_session (Python SDK) or equivalent — not background CLI attach. Always pin TLS with --ca-file / ca_pem — never --insecure.
Example bootstrap script¶
ci/day0_console.py (illustrative):
#!/usr/bin/env python3
import os, sys
from eveiac import (
CreateConsoleSessionRequest, WaitConsoleRequest, RunConsoleRequest,
CloseConsoleSessionRequest, ConsoleRunStep, EveIacClient, pack_lab,
)
packed = pack_lab(os.environ["LAB"])
client = EveIacClient(url=os.environ["EVE_IAC_URL"], token=os.environ["EVE_IAC_TOKEN"], ca_pem=open("ca.pem").read())
base = packed.payload
sess = client.create_console_session(CreateConsoleSessionRequest(**{**base, "node": "n_1", "mode": "interact"}))
sid = sess.session_id
waited = client.wait_console(WaitConsoleRequest(**{**base, "node": "n_1", "session_id": sid, "pattern": r"Router>|Switch>", "timeout_ms": 300_000}))
if waited.timed_out:
sys.exit("boot prompt timeout")
ran = client.run_console(RunConsoleRequest(**{**base, "node": "n_1", "session_id": sid, "steps": [...]})) # load from YAML
if ran.failed_step is not None and ran.failed_step >= 0:
sys.exit(f"bootstrap failed at step {ran.failed_step}")
client.close_console_session(CloseConsoleSessionRequest(**{**base, "session_id": sid}))
Day-0 bootstrap YAML¶
ci/day0-bootstrap.yaml:
steps:
- expect: "Press RETURN"
send: ""
- expect: "Router>"
send: "enable"
- expect: "Password:"
send_secret: "${ENABLE_SECRET}" # inject via CI secret store, not Git
- expect: "Router#"
send: "terminal length 0"
- expect: "Router#"
send: "write mem"
Use send: "" to press RETURN. Omit send entirely on expect-only steps.
Why console in CI¶
| Traditional gap | Console automation |
|---|---|
| Node booting, no MGMT IP yet | Serial/console is available as soon as EVE starts the node |
| SSH keys / NETCONF not configured | No management stack required |
| Jump host not routed | Agent runs on the EVE host and owns the console path |
Console checks validate operational state. Desired configuration still lives in Git (topology.yml, configs/) and is applied through deploy/reconcile.
Security and non-goals: Console security. CLI flags: CLI configuration.