Skip to content

Instantly share code, notes, and snippets.

@bcoca
Created April 25, 2025 14:25
Show Gist options
  • Save bcoca/ba3d8dc74d52120e8595a8dec50a85c1 to your computer and use it in GitHub Desktop.
Save bcoca/ba3d8dc74d52120e8595a8dec50a85c1 to your computer and use it in GitHub Desktop.
# This play is an ansibe-pull substitute, will prompt for options or can bypass by passing as extra vars
- name: ansible-pull
hosts: localhost
gather_subset: min
vars:
now: >-
{{ lookup('pipe', 'date +"%F %T"') }}
vars_prompt:
- name: repo_url
prompt: URL of the playbook repository
private: false
- name: work_dir
prompt: The path to the directory into which the repository checkout will be done
private: false
- name: repo_action
prompt: Repository action name, which ansible will use to check out the repo. Choices are 'git', 'subversion', 'hg', 'bzr'.
default: git
private: false
- name: checkout_version
prompt: branch/tag/commit to checkout. Defaults to behavior of repository module
private: false
- name: playbooks
prompt: Which playbook(s) to run from the checkout directory, if none specified one matchin the current host or 'local.yml' will be attempted.
private: false
- name: playbook_options
prompt: Extra command line options to pass to ansible-playbook
private: false
- name: accept_host_key
prompt: If needed, adds the hostkey for the repo url if not already added
default: false
private: false
- name: private_key_file
prompt: File with private key required to access the repo, if needed.
private: false
- name: only_changed
prompt: Do you want to only run the playbook if the repository has been updated?
default: false
private: false
- name: sleep
prompt: >-
How long should Ansible sleep for random interval (between 0 and n number of seconds) before starting?
This is a useful way to disperse git requests.
default: 0
private: false
- name: force
prompt: Run the playbook even if the repo update fails.
default: false
private: false
- name: full_clone
prompt: Do a full clone, instead of a shallow one
default: false
private: false
- name: verify
prompt: |-
Verify GPG signature of checked out commit, if it fails abort running the playbook.
This needs the corresponding repo action to support such an operation.
default: false
private: false
- name: purge
prompt: Do you want to purge checkout after playbook run?
default: false
private: false
- name: clean
prompt: Should modified files in the working repository be discarded
default: false
private: false
- name: track_subs
prompt: Submodules will track the latest changes. This is equivalent to specifying the --remote flag to git submodule update
default: false
private: false
tasks:
- name: Ensure I have everything I need
block:
- name: The bare minimum needed
assert:
that:
- work_dir is defined
- repo_url is defined
# TODO: add vars + values?
- name: I'm starting!!!
debug:
msg: "Starting Pull at {{now}}"
- name: Do the repo checkout
block:
- name: check workdir
stat:
path: work_dir
register: local_workdir
# ignore permission issues, those will be clear on checkout
- name: Create, in case repo action cannot
file:
path: work_dir
state: directory
when: not local_workdir['stat']['exists']
- name: git pull
git:
name: '{{repo_url}}'
dest: '{{work_dir}}'
version: '{{checkout_version|default(omit)}}'
accept_hostkey: '{{accept_host_key}}'
verify_commit: '{{verify}}'
depth: '{{fullclone|ternary(omit, 1)}}'
track_submodules: '{{track_submodules|default(omit)}}'
key_file: '{{private_key_file|default(omit)}}'
force: '{{clean|default(omit)}}'
when: repo_action in ('git',)
register: checkout
ignore_errors: '{[force}}'
- name: other pulls
fail:
msg: 'I did not implement {{repo_action}} ... just use git!'
when: repo_action in ('subversion', 'hg', 'bzr')
- name: Execute the playbook
when:
- not only_changed or only_changed == checkout['changed']
block:
- name: get playbooks, since none specified
set_fact:
playbooks: "{{ lookup('first_found', files=*candidates, paths=work_dir) }}"
vars:
candidates:
- "{{ansible_facts['fqdn']}}.yml"
- "{{ansible_facts['hostname']}}.yml"
- local.yml
when: playbooks is undefined
- name: actually do stuff
shell: ansible-playbook {{playbooks}} {{playbook_options}}
register: pull_result
ignore_errors: true
- name: Cleanup
when: purge
block:
- name: PURGE!
file:
path: work_dir
state: absent
register: next_day
ignore_errors: true
- name: purge thwarted!
debug:
msg: 'Unable to purge: {{ next_day["msg"] }}'.
when: next_day is failed
- name: Notify/log
block:
- name: show results (TODO: add options for mail/im/api call)
debug:
var: pull_result
- name: passthrough failure status for caller (cron/inotify/intern)
fail:
msg: playbook execution ended in error
when: pull_result is failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment