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.