I add a role by copying the template and leaving the dispatcher alone. The times I edited main.yml I ended up with the install steps in the file that is only supposed to pick present or absent.
cp -r roles/_template roles/configure_example
grep -rl rolename roles/configure_example | xargs sed -i 's/rolename/configure_example/g'
The name is the job: install_, configure_, verify_, or stage_. tasks/is_present.yml puts the thing in place. Running it twice should change nothing. tasks/is_absent.yml takes it away and keeps data unless a purge flag says otherwise. tasks/main.yml includes one of those two from desired_state, which defaults to present. Started and stopped are commented out in the template. I do not uncomment them to mean installed.
Module names stay qualified. ansible.builtin.copy, not copy. I got bitten by a short name resolving to a collection I did not mean, on a host that had no route to install that collection.
Anything the role installs comes from the environment’s own repositories or from a transfer under artifact_staging. Not from the internet. The air-gap kit is built that way because the registry host cannot fetch the installer when the play runs.
Defaults go in defaults/main.yml with a prefix for the component and a one-line comment. A hostname or a password does not get a fake default. The playbook checks that it is set. Inventory placement is the other half:
- every server in the environment:
inventories/<env>/group_vars/all/ - every server in one group:
inventories/<env>/group_vars/<group>/main.yml - one server:
inventories/<env>/host_vars/<host>.yml
The public example inventory is inventories/dev. I do not add qa and prod as empty copies of the same files.
That is the whole addition. The present-side details for Harbor are a different file, roles/install_harbor/tasks/is_present.yml. I do not paste them here.
github.com/noahfarshad/harbor-airgap-kit, docs/ADDING_A_ROLE.md and roles/_template/tasks/main.yml.
