From 9bea4c4a6dce3be428df0341a431ac7e0471fd9d Mon Sep 17 00:00:00 2001 From: joshsiv-mulga Date: Mon, 18 May 2026 13:16:35 +1000 Subject: [PATCH] feat(ansible): dev-deploy playbook for in-place artifact swap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- Makefile | 5 +- scripts/ansible/README.md | 10 ++ scripts/ansible/playbooks/dev-deploy.yml | 14 ++ scripts/ansible/roles/deploy/tasks/main.yml | 148 ++++++++++++++++++++ 4 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 scripts/ansible/playbooks/dev-deploy.yml create mode 100644 scripts/ansible/roles/deploy/tasks/main.yml diff --git a/Makefile b/Makefile index 8e6ebf91b..9e36e88ba 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/scripts/ansible/README.md b/scripts/ansible/README.md index 41ba6e1a5..9e408540b 100644 --- a/scripts/ansible/README.md +++ b/scripts/ansible/README.md @@ -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`: diff --git a/scripts/ansible/playbooks/dev-deploy.yml b/scripts/ansible/playbooks/dev-deploy.yml new file mode 100644 index 000000000..123f46b29 --- /dev/null +++ b/scripts/ansible/playbooks/dev-deploy.yml @@ -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 diff --git a/scripts/ansible/roles/deploy/tasks/main.yml b/scripts/ansible/roles/deploy/tasks/main.yml new file mode 100644 index 000000000..3c24d890d --- /dev/null +++ b/scripts/ansible/roles/deploy/tasks/main.yml @@ -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.