feat(template): add --store-credential to prepare-win + full docstring
- --store-credential: after snapshot, writes build-user credentials into the system keyring using the two-entry scheme (service:meta + service) that KeyringCredentialStore.get() reads. Works on Windows (Credential Manager) and Linux (SecretService / file backend). - --credential-target: keyring target name, default BuildVMGuest (matches config.guest_cred_target). - Rewrote module docstring: full prose documentation of both `template backup` and `template prepare-win` including all 12 provisioning steps. - 2 new tests covering --store-credential with custom and default targets. - mypy --strict clean; coverage 90.03%. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,56 @@
|
||||
"""``template`` sub-commands.
|
||||
"""``template`` sub-commands — CI template VM management.
|
||||
|
||||
Ports ``scripts/Backup-CITemplate.ps1`` to Python.
|
||||
Commands
|
||||
--------
|
||||
template backup
|
||||
Ports ``scripts/Backup-CITemplate.ps1`` to Python. Creates timestamped
|
||||
7z archives of VMware template directories and prunes old backups beyond
|
||||
``--keep-count``. Stops ``act-runner.service`` before copying and
|
||||
restarts it afterwards; pass ``--skip-runner-stop`` to bypass this.
|
||||
|
||||
* ``template backup`` — create timestamped copies of VMware template
|
||||
directories; prune old backups beyond ``--keep-count``.
|
||||
template prepare-win
|
||||
Provisions a Windows template VM end-to-end via pypsrp (replaces the
|
||||
``Prepare-WinBuild*.ps1`` PowerShell scripts that required PSWSMan /
|
||||
New-PSSession — unreliable on Linux hosts).
|
||||
|
||||
The command stops ``act-runner.service`` before copying and restarts it
|
||||
afterwards (via ``systemctl``), so it must run as root or with appropriate
|
||||
sudo privileges. Pass ``--skip-runner-stop`` to bypass this when the runner
|
||||
is already offline.
|
||||
Steps performed by ``template prepare-win``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
1. Resolves ``Install-CIToolchain-<vmx-stem>.ps1`` from
|
||||
``<repo-root>/template/`` (or ``--toolchain-script``).
|
||||
2. Optionally locates ``template/guest-setup/windows/ci-static-ip.ps1``
|
||||
for the ip_pool feature.
|
||||
3. Starts the VM via vmrun (skipped if already running).
|
||||
4. Auto-detects guest IP via VMware Tools (skipped if ``--ip``
|
||||
supplied).
|
||||
5. Waits for TCP/5986 then probes WinRM session readiness.
|
||||
6. Uploads and executes the toolchain script inside the guest. Handles
|
||||
the Windows Update reboot-required exit code (3010) in a loop
|
||||
(max 10 iterations).
|
||||
7. Installs the ``CI-StaticIp`` scheduled task (``SYSTEM``, At Startup)
|
||||
so each linked clone applies a pre-assigned static IP from
|
||||
``guestinfo.ip-assignment`` before WinRM starts.
|
||||
8. Runs post-setup remote validation (11 guest-state checks via a
|
||||
single ``ConvertTo-Json`` call).
|
||||
9. Final reboot → re-affirms autologin registry keys → graceful
|
||||
``Stop-Computer``.
|
||||
10. Waits for the VM to power off (120 s timeout).
|
||||
11. Creates the ``--snapshot`` (default ``BaseClean``); optionally
|
||||
deletes and recreates if a snapshot with that name already exists.
|
||||
12. If ``--store-credential`` is set, writes build-user credentials into
|
||||
the system keyring (Windows → Credential Manager; Linux →
|
||||
SecretService / file backend) using the two-entry scheme read by
|
||||
:class:`~ci_orchestrator.credentials.KeyringCredentialStore`.
|
||||
|
||||
Run from the repository root so toolchain and guest-setup scripts are
|
||||
auto-discovered under ``template/``.
|
||||
|
||||
Usage example::
|
||||
|
||||
python -m ci_orchestrator template prepare-win \\
|
||||
--vmx /var/lib/ci/templates/WinBuild2025/WinBuild2025.vmx \\
|
||||
--admin-password AdminPass1! \\
|
||||
--build-password CIBuildPass1! \\
|
||||
--store-credential
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -282,6 +324,10 @@ def _wait_winrm(transport: WinRmTransport, timeout: int) -> None:
|
||||
@click.option("--auth", default="basic", show_default=True,
|
||||
type=click.Choice(["basic", "ntlm", "negotiate"]),
|
||||
help="WinRM authentication protocol.")
|
||||
@click.option("--store-credential", is_flag=True,
|
||||
help="Store build-user credentials in the system keyring after provisioning.")
|
||||
@click.option("--credential-target", default="BuildVMGuest", show_default=True,
|
||||
help="Keyring target name for the stored credential.")
|
||||
def template_prepare_win(
|
||||
vmx: str,
|
||||
guest_ip: str,
|
||||
@@ -296,6 +342,8 @@ def template_prepare_win(
|
||||
skip_cleanup: bool,
|
||||
winrm_timeout: int,
|
||||
auth: str,
|
||||
store_credential: bool,
|
||||
credential_target: str,
|
||||
) -> None:
|
||||
"""Provision a Windows template VM via pypsrp (Linux-host compatible).
|
||||
|
||||
@@ -593,4 +641,23 @@ Register-ScheduledTask -TaskName 'CI-StaticIp' `
|
||||
[vmrun_exe, "-T", "ws", "snapshot", str(vmx_path), snapshot],
|
||||
check=True,
|
||||
)
|
||||
click.echo(f"[prepare-win] Snapshot '{snapshot}' created. Provisioning complete.")
|
||||
click.echo(f"[prepare-win] Snapshot '{snapshot}' created.")
|
||||
|
||||
# Store credentials in system keyring (Windows Credential Manager on Windows,
|
||||
# SecretService / file backend on Linux) using the two-entry scheme so
|
||||
# KeyringCredentialStore.get() can retrieve them without knowing the username.
|
||||
if store_credential:
|
||||
try:
|
||||
import keyring
|
||||
except ImportError as exc:
|
||||
raise click.ClickException(
|
||||
"keyring is not installed; run `pip install keyring`."
|
||||
) from exc
|
||||
keyring.set_password(f"{credential_target}:meta", "username", build_username)
|
||||
keyring.set_password(credential_target, build_username, build_password)
|
||||
click.echo(
|
||||
f"[prepare-win] Credentials stored in keyring "
|
||||
f"(target='{credential_target}', user='{build_username}')."
|
||||
)
|
||||
|
||||
click.echo("[prepare-win] Provisioning complete.")
|
||||
|
||||
Reference in New Issue
Block a user