feat(ansible): dev-deploy playbook for in-place artifact swap

Fills the gap between ansible-dev-install (skips when already installed)
and ansible-dev-reset (full teardown + reinstall + smoketest). Mirrors
Makefile `deploy` target: rebuild + replace binaries and microvm
artifacts on a running node, restart spinifex.target, wait for awsgw.

Skips setup.sh (no user/dir/systemd-unit changes) and smoketest so
iteration is fast. Use ansible-dev-reset when changing systemd units,
helper scripts, logrotate, or setup.sh itself.

Adds:
- roles/deploy/tasks/main.yml — install spx + nbdkit plugin + microvm
  artifacts, with plugindir auto-detection via `nbdkit --dump-config`.
- playbooks/dev-deploy.yml — chains build + deploy roles.
- Makefile ansible-dev-deploy target.
- README playbook table + "when to use which" guidance.
This commit is contained in:
joshsiv-mulga
2026-05-18 13:16:35 +10:00
parent b59fc4b433
commit 9bea4c4a6d
4 changed files with 176 additions and 1 deletions
+4 -1
View File
@@ -275,9 +275,12 @@ ansible-dev-install:
ansible-dev-reset:
cd scripts/ansible && ansible-playbook playbooks/dev-reset.yml
ansible-dev-deploy:
cd scripts/ansible && ansible-playbook playbooks/dev-deploy.yml
.PHONY: build build-ui build-installer build-lb-agent build-system-image build-lb-image build-microvm-image install-microvm go_build go_run preflight test test-cover test-race diff-coverage bench run \
deploy reinstall clean \
install-system install-go install-aws quickinstall \
lint fix govulncheck \
distro distro-amd64 distro-arm64 distro-clean \
ansible-dev-preflight ansible-dev-teardown ansible-dev-install ansible-dev-reset
ansible-dev-preflight ansible-dev-teardown ansible-dev-install ansible-dev-reset ansible-dev-deploy
+10
View File
@@ -31,6 +31,7 @@ inventory and roles relative to CWD.
| `playbooks/dev-teardown.yml` | Wipe state only (no reinstall) | `reset-dev-env.sh` §teardown |
| `playbooks/dev-install.yml` | Build + install + init + smoketest on clean box | `dev-install.sh` |
| `playbooks/dev-reset.yml` | Capture settings → teardown → build → install → init → smoketest | `reset-dev-env.sh` (full) |
| `playbooks/dev-deploy.yml` | Rebuild + swap binaries/microvm artifacts + restart (no setup.sh, no smoketest) | `make deploy` |
Upcoming (not yet implemented):
@@ -44,6 +45,7 @@ ansible-playbook playbooks/dev-preflight.yml
ansible-playbook playbooks/dev-teardown.yml
ansible-playbook playbooks/dev-install.yml
ansible-playbook playbooks/dev-reset.yml
ansible-playbook playbooks/dev-deploy.yml
```
Or via `make` (from `spinifex/`):
@@ -53,8 +55,16 @@ make ansible-dev-preflight
make ansible-dev-teardown
make ansible-dev-install
make ansible-dev-reset
make ansible-dev-deploy
```
### When to use which
- First-time / clean box → `ansible-dev-install`
- Iterate on Go code, microvm initramfs, lb-agent → `ansible-dev-deploy` (fast)
- Changed systemd units, helper scripts, logrotate, setup.sh → `ansible-dev-reset` (slow, full rebuild)
- Need a clean slate without reinstall → `ansible-dev-teardown`
## Variable overrides
Defaults in `vars/defaults.yml`. Override per run with `-e`:
+14
View File
@@ -0,0 +1,14 @@
---
# In-place artifact swap: rebuilds + replaces binaries/microvm artifacts on
# an already-installed node, then restarts spinifex.target. Use when iterating
# on code without altering systemd units, users, dirs, or running the full
# smoketest. For first-time or unit/script changes use dev-install / dev-reset.
- name: Dev deploy — build + swap binaries + restart (no setup.sh, no smoketest)
hosts: localhost
gather_facts: true
vars_files:
- ../vars/defaults.yml
roles:
- build
- deploy
+148
View File
@@ -0,0 +1,148 @@
---
# In-place artifact swap for an already-installed spinifex node. Mirrors
# `make deploy`: replace binaries + microvm artifacts, restart services.
# Does NOT run setup.sh (no user/dir/systemd-unit changes) or smoketest.
- name: deploy — fail fast if spinifex isn't already installed
ansible.builtin.stat:
path: "{{ spinifex_config_file }}"
register: deploy_installed_stat
failed_when: not deploy_installed_stat.stat.exists
- name: deploy — assert config present
ansible.builtin.assert:
that: deploy_installed_stat.stat.exists
fail_msg: |
{{ spinifex_config_file }} missing — this playbook only updates an
existing install. Run ansible-dev-install or ansible-dev-reset first.
- name: deploy — verify build artifacts present
ansible.builtin.stat:
path: "{{ item }}"
register: deploy_artifacts
loop:
- "{{ spinifex_root }}/bin/spx"
- "{{ mulga_root }}/viperblock/lib/nbdkit-viperblock-plugin.so"
- name: deploy — assert artifacts exist after build role
ansible.builtin.assert:
that: item.stat.exists
fail_msg: "Build artifact missing: {{ item.item }} — build role should have produced it"
loop: "{{ deploy_artifacts.results }}"
loop_control:
label: "{{ item.item }}"
- name: deploy — detect microvm artifacts (direct-boot branches only)
ansible.builtin.stat:
path: "{{ spinifex_root }}/build/microvm/{{ item }}"
register: deploy_microvm_stat
loop:
- vmlinuz
- initramfs.cpio.gz
- name: deploy — set microvm presence fact
ansible.builtin.set_fact:
deploy_microvm_present: "{{ deploy_microvm_stat.results | map(attribute='stat.exists') | min }}"
- name: deploy — detect nbdkit plugin directory
ansible.builtin.shell: |
set -e
nbdkit --dump-config | awk -F= '/^plugindir=/{print $2; exit}'
register: deploy_plugindir_cmd
changed_when: false
- name: deploy — set plugin path fact
ansible.builtin.set_fact:
deploy_plugindir: "{{ deploy_plugindir_cmd.stdout | trim }}"
- name: deploy — assert plugindir resolved
ansible.builtin.assert:
that: deploy_plugindir | length > 0
fail_msg: "Could not detect nbdkit plugin directory via `nbdkit --dump-config`"
- name: deploy — stop spinifex.target before binary swap
become: true
ansible.builtin.systemd:
name: spinifex.target
state: stopped
failed_when: false
- name: deploy — install spx binary
become: true
ansible.builtin.copy:
src: "{{ spinifex_root }}/bin/spx"
dest: /usr/local/bin/spx
mode: "0755"
owner: root
group: root
- name: deploy — install viperblock nbdkit plugin
become: true
ansible.builtin.copy:
src: "{{ mulga_root }}/viperblock/lib/nbdkit-viperblock-plugin.so"
dest: "{{ deploy_plugindir }}/nbdkit-viperblock-plugin.so"
mode: "0755"
owner: root
group: root
- name: deploy — ensure microvm dir
become: true
ansible.builtin.file:
path: /usr/share/spinifex/microvm
state: directory
mode: "0755"
owner: root
group: root
when: deploy_microvm_present
- name: deploy — install microvm kernel
become: true
ansible.builtin.copy:
src: "{{ spinifex_root }}/build/microvm/vmlinuz"
dest: /usr/share/spinifex/microvm/vmlinuz
mode: "0644"
owner: root
group: root
when: deploy_microvm_present
- name: deploy — install microvm initramfs
become: true
ansible.builtin.copy:
src: "{{ spinifex_root }}/build/microvm/initramfs.cpio.gz"
dest: /usr/share/spinifex/microvm/initramfs.cpio.gz
mode: "0644"
owner: root
group: root
when: deploy_microvm_present
- name: deploy — daemon-reload (covers any unit changes shipped via setup.sh later)
become: true
ansible.builtin.systemd:
daemon_reload: true
- name: deploy — start spinifex.target
become: true
ansible.builtin.systemd:
name: spinifex.target
state: started
- name: deploy — wait for awsgw to respond
become: true
become_user: "{{ spinifex_invoking_user }}"
environment:
AWS_PROFILE: spinifex
ansible.builtin.command: aws ec2 describe-regions
register: deploy_awsgw
retries: 15
delay: 2
until: deploy_awsgw.rc == 0
changed_when: false
- name: deploy — summary
ansible.builtin.debug:
msg: |
Deployed:
spx → /usr/local/bin/spx
nbdkit plugin → {{ deploy_plugindir }}/nbdkit-viperblock-plugin.so
microvm → {{ '/usr/share/spinifex/microvm/{vmlinuz,initramfs.cpio.gz}' if deploy_microvm_present else 'skipped (not built on this branch)' }}
spinifex.target restarted; awsgw responding.