From 21cd4b1e7ec557531f403116836f581e906ccfc4 Mon Sep 17 00:00:00 2001 From: Ari Kalfus Date: Fri, 19 Jan 2024 17:56:48 -0500 Subject: [PATCH] fix: ensure compatibility with ansible's 'free' strategy (#417) * fix: ensure playbook is compatible with free ansible strategy * run multiple disros in strategy-free scenario * fix oauth variables after CI refactor * remove temporary trigger --- .github/workflows/molecule.yml | 21 ++- .github/workflows/pull_request_target.yml | 149 ++++++------------ Makefile | 8 + README.md | 74 ++++++--- molecule/default/prepare.yml | 12 +- molecule/oauth/converge.yml | 2 +- molecule/oauth/init_tailscale_vars.yml | 22 --- molecule/oauth/molecule.yml | 2 + molecule/oauth/prepare.yml | 26 --- .../cleanup.yml | 0 .../converge.yml | 0 .../molecule.yml | 2 +- .../verify.yml | 0 molecule/strategy-free/cleanup.yml | 8 + molecule/strategy-free/converge.yml | 13 ++ molecule/strategy-free/molecule.yml | 80 ++++++++++ molecule/strategy-free/verify.yml | 15 ++ tasks/install.yml | 4 +- 18 files changed, 247 insertions(+), 191 deletions(-) delete mode 100644 molecule/oauth/init_tailscale_vars.yml delete mode 100644 molecule/oauth/prepare.yml rename molecule/{state-present => state-idempotency}/cleanup.yml (100%) rename molecule/{state-present => state-idempotency}/converge.yml (100%) rename molecule/{state-present => state-idempotency}/molecule.yml (97%) rename molecule/{state-present => state-idempotency}/verify.yml (100%) create mode 100644 molecule/strategy-free/cleanup.yml create mode 100644 molecule/strategy-free/converge.yml create mode 100644 molecule/strategy-free/molecule.yml create mode 100644 molecule/strategy-free/verify.yml diff --git a/.github/workflows/molecule.yml b/.github/workflows/molecule.yml index 9c39200c..8c3f51d8 100644 --- a/.github/workflows/molecule.yml +++ b/.github/workflows/molecule.yml @@ -4,11 +4,15 @@ name: Run Molecule Test on: workflow_call: inputs: - image: + scenario: required: true type: string + image: + required: false + type: string + default: 'ghcr.io/artis3n/docker-ubuntu2204-ansible:latest' command: - required: true + required: false type: string runner: required: false @@ -24,8 +28,8 @@ env: ANSIBLE_FORCE_COLOR: '1' jobs: - run-molecule: - name: "Run Molecule" + run-scenario: + name: "Run Molecule Scenario - ${{ inputs.image }} / ${{ inputs.scenario }}" runs-on: ${{ inputs.runner }} environment: E2E @@ -48,14 +52,7 @@ jobs: run: poetry install --no-interaction - name: Default scenario - run: poetry run molecule test --scenario-name default - env: - MOLECULE_DISTRO: "${{ inputs.image }}" - MOLECULE_COMMAND: "${{ inputs.command }}" - TAILSCALE_CI_KEY: "${{ secrets.tailscale_key }}" - - - name: Uninstall scenario - run: poetry run molecule test --scenario-name state-absent + run: poetry run molecule test --scenario-name "${{ inputs.scenario }}" env: MOLECULE_DISTRO: "${{ inputs.image }}" MOLECULE_COMMAND: "${{ inputs.command }}" diff --git a/.github/workflows/pull_request_target.yml b/.github/workflows/pull_request_target.yml index 6aea7b09..11d53aae 100644 --- a/.github/workflows/pull_request_target.yml +++ b/.github/workflows/pull_request_target.yml @@ -17,7 +17,7 @@ env: jobs: molecule: - name: "Test Distro" + name: "Test Distros" strategy: fail-fast: false matrix: @@ -47,12 +47,13 @@ jobs: with: image: ${{ matrix.image }} command: ${{ matrix.command }} + scenario: 'default' secrets: tailscale_key: ${{ secrets.TAILSCALE_CI_KEY }} # Systems that aren't working with cgroups v2 on ubuntu 22.04, but works on ubuntu 20.04 molecule-legacy: - name: "Test Legacy Distro" + name: "Test Legacy Distros" strategy: fail-fast: false matrix: @@ -74,119 +75,58 @@ jobs: with: image: ${{ matrix.image }} command: ${{ matrix.command }} + scenario: 'default' runner: ubuntu-20.04 secrets: tailscale_key: ${{ secrets.TAILSCALE_CI_KEY }} - molecule-skip-auth: - name: "Test Skip Authentication" - runs-on: ubuntu-22.04 - environment: E2E - - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Install dependency manager - run: pipx install poetry - - - name: Set up Python 3.x - id: setup-python - uses: actions/setup-python@v5.0.0 - with: - python-version-file: pyproject.toml - cache: 'poetry' - - - name: Install packages - run: poetry install --no-interaction + molecule-state-absent: + name: "Run Molecule Scenario: state-absent" + uses: ./.github/workflows/molecule.yml + with: + scenario: 'state-absent' + secrets: + tailscale_key: ${{ secrets.TAILSCALE_CI_KEY }} - - name: Molecule - Skip Authentication - run: poetry run molecule test --scenario-name skip-authentication + molecule-skip-auth: + name: "Run Molecule Scenario: skip-authentication" + uses: ./.github/workflows/molecule.yml + with: + scenario: 'skip-authentication' + secrets: + tailscale_key: ${{ secrets.TAILSCALE_CI_KEY }} molecule-args: - name: "Test Up Args" - runs-on: ubuntu-22.04 - environment: E2E - - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Install dependency manager - run: pipx install poetry - - - name: Set up Python 3.x - id: setup-python - uses: actions/setup-python@v5.0.0 - with: - python-version-file: pyproject.toml - cache: 'poetry' - - - name: Install packages - run: poetry install --no-interaction - - - name: Molecule - Custom Arguments Validation - run: poetry run molecule test --scenario-name args - env: - TAILSCALE_CI_KEY: "${{ secrets.TAILSCALE_CI_KEY }}" + name: "Run Molecule Scenario: args" + uses: ./.github/workflows/molecule.yml + with: + scenario: 'args' + secrets: + tailscale_key: ${{ secrets.TAILSCALE_CI_KEY }} molecule-state-present: - name: "Test State Idempotency" - runs-on: ubuntu-22.04 - environment: E2E - - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Install dependency manager - run: pipx install poetry - - - name: Set up Python 3.x - id: setup-python - uses: actions/setup-python@v5.0.0 - with: - python-version-file: pyproject.toml - cache: 'poetry' - - - name: Install packages - run: poetry install --no-interaction - - - name: Molecule - State Present - run: poetry run molecule test --scenario-name state-present - env: - TAILSCALE_CI_KEY: "${{ secrets.TAILSCALE_CI_KEY }}" - - molecule-state-oauth: - name: "Test OAuth key support" - runs-on: ubuntu-22.04 - environment: E2E - - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Install dependency manager - run: pipx install poetry - - - name: Set up Python 3.x - id: setup-python - uses: actions/setup-python@v5.0.0 - with: - python-version-file: pyproject.toml - cache: 'poetry' + name: "Run Molecule Scenario: state-idempotency" + uses: ./.github/workflows/molecule.yml + with: + scenario: 'state-idempotency' + secrets: + tailscale_key: ${{ secrets.TAILSCALE_CI_KEY }} - - name: Install packages - run: poetry install --no-interaction + molecule-oauth: + name: "Run Molecule Scenario: oauth" + uses: ./.github/workflows/molecule.yml + with: + scenario: 'oauth' + secrets: + tailscale_key: ${{ secrets.TAILSCALE_OAUTH_CLIENT_SECRET }} - - name: Molecule - State Present - run: poetry run molecule test --scenario-name oauth - env: - TAILSCALE_OAUTH_CLIENT_SECRET: "${{ secrets.TAILSCALE_OAUTH_CLIENT_SECRET }}" + molecule-strategy-free: + name: "Run Molecule Scenario: strategy-free" + uses: ./.github/workflows/molecule.yml + with: + scenario: 'strategy-free' + secrets: + tailscale_key: ${{ secrets.TAILSCALE_CI_KEY }} molecule-headscale: name: "Test Headscale Compatibility" @@ -199,6 +139,7 @@ jobs: - default - state-absent - idempotent-up + - strategy-free steps: - uses: actions/checkout@v4 diff --git a/Makefile b/Makefile index 748dbfc1..4323ca9e 100644 --- a/Makefile +++ b/Makefile @@ -76,6 +76,14 @@ else poetry run molecule test --scenario-name oauth endif +.PHONY: test-strategy-free +test-strategy-free: +ifndef TAILSCALE_CI_KEY + $(error TAILSCALE_CI_KEY is not set) +else + poetry run molecule test --scenario-name strategy-free +endif + .PHONY: test-headscale test-headscale: USE_HEADSCALE=true poetry run molecule test --scenario-name default diff --git a/README.md b/README.md index af4a516a..f84f4c46 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,12 @@ See the [CI worfklow](https://github.com/artis3n/ansible-role-tailscale/blob/mai # State Tracking -This role will create an `artis3n-tailscale` directory in the target's [`XDG_STATE_HOME`](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) directory, or `$HOME/.local/state` if the variable is not present, in order to maintain a concept of state from the configuration of the arguments passed to `tailscale up`. +This role will create an `artis3n-tailscale` directory in the target's [`XDG_STATE_HOME`](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) directory, +or `$HOME/.local/state` if the variable is not present, +in order to maintain a concept of state from the configuration of the arguments passed to `tailscale up`. This allows the role to idempotently update a Tailscale node's configuration when needed. -Deleting this directory will lead to this role re-configuring Tailscale when it is not needed, but will not otherwise break anything. +Deleting this directory will lead to this role re-configuring Tailscale when it is not needed, +but will not otherwise break anything. However, it is recommended that you let this Ansible role manage this directory and its contents. Note that: @@ -47,7 +50,8 @@ Note that: > > ... > -> In Tailscale v1.8 or later, if you forget to specify a flag you added before, the CLI will warn you and provide a copyable command that includes all existing flags. +> In Tailscale v1.8 or later, if you forget to specify a flag you added before, +> the CLI will warn you and provide a copyable command that includes all existing flags. @@ -55,7 +59,8 @@ Note that: -This role will bubble up any stderr messages from the Tailscale binary to resolve any end-user configuration errors with `tailscale up` arguments. +This role will bubble up any stderr messages from the Tailscale binary +to resolve any end-user configuration errors with `tailscale up` arguments. The `--authkey=` value will be redacted unless [`insecurely_log_authkey`](#insecurely_log_authkey) is set to `true`. ![logged stderr](docs/images/printed_stderr.png) @@ -67,7 +72,8 @@ The `--authkey=` value will be redacted unless [`insecurely_log_authkey`](#insec One of `tailscale_authkey` or `tailscale_up_skip` must be present. In most cases you will use `tailscale_authkey`. -If you are uninstalling Tailscale (`state: absent`), neither `tailscale_authkey` nor `tailscale_up_skip` is required. +If you are uninstalling Tailscale (`state: absent`), +neither `tailscale_authkey` nor `tailscale_up_skip` is required. If you are authenticating with an OAuth key, you must also set `tailscale_tags` (see below). @@ -83,9 +89,14 @@ A Node Authorization key can be generated under your Tailscale account. The role - OAuth key (`tskey-client-XXX-YYYY`) > [!IMPORTANT] -> Using an OAuth key requires additionally setting the following variables: `tailscale_tags` (must be provided), `tailscale_oauth_ephemeral` (defaults to `true`) and `tailscale_oauth_preauthorized` (defaults to `false`). +> Using an OAuth key requires additionally setting the following variables: +> `tailscale_tags` (must be provided), +> `tailscale_oauth_ephemeral` (defaults to `true`), +> and `tailscale_oauth_preauthorized` (defaults to `false`). -Note that auth keys expire up to a maximum of 90 days after they are generated. OAuth secrets do not expire unless revoked, and the generated OAuth access token expires after 1 hour. +Note that auth keys expire up to a maximum of 90 days after they are generated. +OAuth secrets do not expire unless revoked, +and the generated OAuth access token expires after 1 hour. For more information, see Tailscale's [OAuth clients](https://tailscale.com/kb/1215/oauth-clients) page, especially [Generating long-lived auth keys](https://tailscale.com/kb/1215/oauth-clients#generating-long-lived-auth-keys). @@ -117,7 +128,8 @@ Skip [manual device approval](https://tailscale.com/kb/1099/device-approval), if **Default**: `[]` -Apply supplied tags to the Tailscale nodes configured by this role (via the `--advertise-tags` flag to `tailscale up`). +Apply supplied tags to the Tailscale nodes configured by this role +(via the `--advertise-tags` flag to `tailscale up`). For more information, see [What are tags?](https://tailscale.com/kb/1068/acl-tags?q=acl%20tag#what-are-acl-tags) > [!NOTE] @@ -135,7 +147,8 @@ For example, `tailscale_args: ['worker']` translates to `--advertise-tags=tag:wo **Default**: `false` Whether to install and configure Tailscale as a service but skip running `tailscale up`. -Helpful when packaging up a Tailscale installation into a build process such as AMI creation when the server should not yet authenticate to your Tailscale network. +Helpful when packaging up a Tailscale installation into a build process, such as AMI creation, +when the server should not yet authenticate to your Tailscale network. ## Optional @@ -143,12 +156,16 @@ Helpful when packaging up a Tailscale installation into a build process such as **Default**: `false` -If set to `true`, the "Bring Tailscale Up" command will include the raw value of the Tailscale authkey when logging any errors encountered during `tailscale up`. -By default, the authkey is not logged in successful task completions and is redacted in the `stderr` output by this role if an error occurs. +If set to `true`, the "Bring Tailscale Up" command will include the raw value of the Tailscale authkey +when logging any errors encountered during `tailscale up`. +By default, the authkey is not logged in successful task completions +and is redacted in the `stderr` output by this role if an error occurs. ![redacted authkey](docs/images/redacted_authkey.png) -If you are encountering an error bringing Tailscale up and want the "Bring Tailscale Up" task to _not_ redact the value of the authkey, set this variable to `true`. +If you are encountering an error bringing Tailscale up +and want the "Bring Tailscale Up" task to _not_ redact the value of the authkey, +set this variable to `true`. Regardless, if the authkey is invalid, the role will relay Tailscale's error message on that fact: @@ -175,9 +192,12 @@ Whether to use the Tailscale stable or unstable track. Whether to install or uninstall Tailscale. If defined, `state` must be either `latest`, `present`, or `absent`. -This role uses `latest` by default to help ensure your software remains up-to-date and incorporates the latest security and product features. -For users who desire more control over configuration drift, `present` will not update Tailscale if it is already installed. -Changes to [`tailscale_args`](#tailscale_args) will be applied under both `latest` and `present`; this parameter only impacts the version of Tailscale installed to the target system. +This role uses `latest` by default to help ensure your software remains up-to-date +and incorporates the latest security and product features. +For users who desire more control over configuration drift, +`present` will not update Tailscale if it is already installed. +Changes to [`tailscale_args`](#tailscale_args) will be applied under both `latest` and `present`; +this parameter only impacts the version of Tailscale installed to the target system. If set to `absent`, this role will de-register the Tailscale node (if already authenticated) and clean up or disable all Tailscale artifacts added to the system. @@ -188,7 +208,8 @@ Note that neither `tailscale_authkey` nor `tailscale_up_skip` is required if `st Pass any additional command-line arguments to `tailscale up`. -Note that the [command][ansible.builtin.command] module is used, which does not support subshell expressions (`$()`) or bash operations like `;` and `&`. +Note that the [command][ansible.builtin.command] module is used, +which does not support subshell expressions (`$()`) or bash operations like `;` and `&`. Only `tailscale up` arguments can be passed in. > [!CAUTION] @@ -201,7 +222,9 @@ Only `tailscale up` arguments can be passed in. > **Do not use this for `--timeout`.** > Use the `tailscale_up_timeout` variable instead. -Any stdout/stderr output from the `tailscale` binary will be printed. Since the tasks move quickly in this section, a 5 second pause is introduced to grant more time for users to realize a message was printed. +Any stdout/stderr output from the `tailscale` binary will be printed. +Since the tasks move quickly in this section, a 5 second pause is introduced +to grant more time for users to realize a message was printed. ![printed stdout](docs/images/printed_stdout.png) @@ -334,14 +357,21 @@ Ari Kalfus ([@artis3n](https://www.artis3nal.com/)) This GitHub repository uses a dedicated "test" Tailscale account to authenticate Tailscale during CI runs. Each Docker container creates a new authorized machine in that test account. -The machines are authorized with [ephemeral auth keys][] and are automatically cleaned up within 30 minutes-48 hours. +The machines are authorized with [ephemeral auth keys][] +and are automatically cleaned up within 30 minutes-48 hours. This value is stored in a [GitHub Action secret][] with the name `TAILSCALE_CI_KEY`. To test OAuth authkey compatibility, a Tailscale OAuth client secret is stored as `TAILSCALE_OAUTH_CLIENT_SECRET`. -To test this role locally, store the Tailscale ephemeral auth key in a `TAILSCALE_CI_KEY` env var and, if running the `oauth` Molecule scenario, add an OAuth client secret in a `TAILSCALE_OAUTH_CLIENT_SECRET` env var. -If you are a Collaborator on this repository, you can open a GitHub CodeSpace and these secrets will be pre-populated for you into the environment. - -Alternatively for Molecule testing, you can use a [Headscale][] container that is spun up as part of the create/prepare steps. To do this, set a `USE_HEADSCALE` env variable. For example: +To test this role locally, store the Tailscale ephemeral auth key in a `TAILSCALE_CI_KEY` env var +and, if running the `oauth` Molecule scenario, +add an OAuth client secret in a `TAILSCALE_OAUTH_CLIENT_SECRET` env var. +If you are a Collaborator on this repository, +you can open a GitHub CodeSpace and these secrets will be pre-populated for you into the environment. + +Alternatively for Molecule testing, +you can use a [Headscale][] container that is spun up as part of the create/prepare steps. +To do this, set a `USE_HEADSCALE` env variable. +For example: ```bash USE_HEADSCALE=true molecule test diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml index 5ae2d73c..eae142a6 100644 --- a/molecule/default/prepare.yml +++ b/molecule/default/prepare.yml @@ -18,8 +18,18 @@ name: headscale register: headscale_info + - name: Fetch Headscale network info + community.docker.docker_network_info: + name: headscale + register: headscale_network + + - name: Get instance names + ansible.builtin.set_fact: + instance_names: "{{ headscale_network.network.Containers | dict2items | selectattr('value.Name', 'match', '^instance') | map(attribute='value.Name') | list }}" + - name: Set hosts override for Headscale - delegate_to: instance + delegate_to: "{{ item }}" + loop: "{{ instance_names }}" ansible.builtin.lineinfile: path: /etc/hosts line: "{{ headscale_info.container.NetworkSettings.Networks.headscale.IPAddress }} headscale" diff --git a/molecule/oauth/converge.yml b/molecule/oauth/converge.yml index f1f87be6..ba253400 100644 --- a/molecule/oauth/converge.yml +++ b/molecule/oauth/converge.yml @@ -3,7 +3,7 @@ hosts: instance tasks: - name: Init tailscale credentials variables - ansible.builtin.include_tasks: init_tailscale_vars.yml + ansible.builtin.include_tasks: ../default/init_tailscale_vars.yml - name: "Include artis3n.tailscale" ansible.builtin.include_role: diff --git a/molecule/oauth/init_tailscale_vars.yml b/molecule/oauth/init_tailscale_vars.yml deleted file mode 100644 index 498bd4bd..00000000 --- a/molecule/oauth/init_tailscale_vars.yml +++ /dev/null @@ -1,22 +0,0 @@ ---- -- name: Use tailscale service - ansible.builtin.set_fact: - tailscale_authkey: "{{ lookup('ansible.builtin.env', 'TAILSCALE_OAUTH_CLIENT_SECRET') }}" - when: not lookup('ansible.builtin.env', 'USE_HEADSCALE', default=false) - -- name: Fetch headscale preauth key - delegate_to: localhost - changed_when: false - community.docker.docker_container_exec: - container: headscale - command: headscale preauthkeys list -u test -o json - register: preauth_list - when: lookup('ansible.builtin.env', 'USE_HEADSCALE', default=false) - -- name: Use headscale service - vars: - combined_args: "{{ tailscale_args|default('') }} --login-server=http://headscale:8080" - ansible.builtin.set_fact: - tailscale_authkey: "{{ (preauth_list.stdout|from_json)[0].key }}" - tailscale_args: "{{ combined_args }}" - when: lookup('ansible.builtin.env', 'USE_HEADSCALE', default=false) diff --git a/molecule/oauth/molecule.yml b/molecule/oauth/molecule.yml index 9d505403..ecf10e3a 100644 --- a/molecule/oauth/molecule.yml +++ b/molecule/oauth/molecule.yml @@ -29,6 +29,8 @@ platforms: - "${MOLECULE_PROJECT_DIRECTORY}/molecule/default/headscale.config.yaml:/etc/headscale/config.yaml" provisioner: name: ansible + playbooks: + prepare: ../default/prepare.yml verifier: name: ansible scenario: diff --git a/molecule/oauth/prepare.yml b/molecule/oauth/prepare.yml deleted file mode 100644 index 5ae2d73c..00000000 --- a/molecule/oauth/prepare.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- -- name: Prepare - hosts: localhost - gather_facts: false - tasks: - - name: Create Headscale user - community.docker.docker_container_exec: - container: headscale - command: headscale users create test - - - name: Create preauth key - community.docker.docker_container_exec: - container: headscale - command: headscale preauthkeys create -u test --reusable - - - name: Fetch Headscale container info - community.docker.docker_container_info: - name: headscale - register: headscale_info - - - name: Set hosts override for Headscale - delegate_to: instance - ansible.builtin.lineinfile: - path: /etc/hosts - line: "{{ headscale_info.container.NetworkSettings.Networks.headscale.IPAddress }} headscale" - unsafe_writes: true # Hosts file in the docker container can't be written to atomically diff --git a/molecule/state-present/cleanup.yml b/molecule/state-idempotency/cleanup.yml similarity index 100% rename from molecule/state-present/cleanup.yml rename to molecule/state-idempotency/cleanup.yml diff --git a/molecule/state-present/converge.yml b/molecule/state-idempotency/converge.yml similarity index 100% rename from molecule/state-present/converge.yml rename to molecule/state-idempotency/converge.yml diff --git a/molecule/state-present/molecule.yml b/molecule/state-idempotency/molecule.yml similarity index 97% rename from molecule/state-present/molecule.yml rename to molecule/state-idempotency/molecule.yml index f322b738..3ae982cf 100644 --- a/molecule/state-present/molecule.yml +++ b/molecule/state-idempotency/molecule.yml @@ -34,7 +34,7 @@ provisioner: verifier: name: ansible scenario: - name: state-present + name: state-idempotency test_sequence: - dependency - destroy diff --git a/molecule/state-present/verify.yml b/molecule/state-idempotency/verify.yml similarity index 100% rename from molecule/state-present/verify.yml rename to molecule/state-idempotency/verify.yml diff --git a/molecule/strategy-free/cleanup.yml b/molecule/strategy-free/cleanup.yml new file mode 100644 index 00000000..b650329e --- /dev/null +++ b/molecule/strategy-free/cleanup.yml @@ -0,0 +1,8 @@ +--- +- name: Cleanup + hosts: instances + tasks: + - name: De-register Tailscale node + become: true + ansible.builtin.command: tailscale logout + changed_when: false diff --git a/molecule/strategy-free/converge.yml b/molecule/strategy-free/converge.yml new file mode 100644 index 00000000..5809eb0e --- /dev/null +++ b/molecule/strategy-free/converge.yml @@ -0,0 +1,13 @@ +--- +- name: Converge + hosts: instances + strategy: free + tasks: + - name: Init tailscale credentials variables + ansible.builtin.include_tasks: ../default/init_tailscale_vars.yml + + - name: "Include artis3n.tailscale" + ansible.builtin.include_role: + name: artis3n.tailscale + vars: + verbose: true diff --git a/molecule/strategy-free/molecule.yml b/molecule/strategy-free/molecule.yml new file mode 100644 index 00000000..726e1d43 --- /dev/null +++ b/molecule/strategy-free/molecule.yml @@ -0,0 +1,80 @@ +--- +dependency: + name: galaxy + options: + requirements-file: requirements.yml +driver: + name: docker +platforms: + - name: instance-1 + groups: + - instances + image: ${MOLECULE_DISTRO:-geerlingguy/docker-ubuntu2204-ansible:latest} + command: ${MOLECULE_COMMAND:-/usr/sbin/init} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + docker_networks: + - name: headscale + networks: + - name: bridge + - name: headscale + cgroupns_mode: host + privileged: true + pre_build_image: true + - name: instance-2 + groups: + - instances + image: 'ghcr.io/artis3n/docker-amazonlinux2023-ansible:latest' + command: ${MOLECULE_COMMAND:-/usr/sbin/init} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + docker_networks: + - name: headscale + networks: + - name: bridge + - name: headscale + cgroupns_mode: host + privileged: true + pre_build_image: true + - name: instance-3 + groups: + - instances + image: 'cisagov/docker-debian12-ansible:latest' + command: ${MOLECULE_COMMAND:-/usr/sbin/init} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + docker_networks: + - name: headscale + networks: + - name: bridge + - name: headscale + cgroupns_mode: host + privileged: true + pre_build_image: true + - name: headscale + image: ${HEADSCALE_IMAGE:-headscale/headscale:latest} + command: headscale serve + pre_build_image: true + networks: + - name: headscale + volumes: + - "${MOLECULE_PROJECT_DIRECTORY}/molecule/default/headscale.config.yaml:/etc/headscale/config.yaml" +provisioner: + name: ansible + playbooks: + prepare: ../default/prepare.yml +verifier: + name: ansible +scenario: + name: strategy-free + test_sequence: + - dependency + - destroy + - syntax + - create + - prepare + - converge + - idempotence + - verify + - cleanup + - destroy diff --git a/molecule/strategy-free/verify.yml b/molecule/strategy-free/verify.yml new file mode 100644 index 00000000..4fb07b8d --- /dev/null +++ b/molecule/strategy-free/verify.yml @@ -0,0 +1,15 @@ +--- +- name: Verify + hosts: instances + tasks: + - name: Get Tailscale status + become: true + ansible.builtin.command: tailscale status + changed_when: false + register: tailscale_status + + - name: Assertions + ansible.builtin.assert: + that: + - "'Logged out.' not in tailscale_status.stdout" + - "'not logged in' not in tailscale_status.stdout" diff --git a/tasks/install.yml b/tasks/install.yml index 2a081358..86dbd773 100644 --- a/tasks/install.yml +++ b/tasks/install.yml @@ -154,8 +154,8 @@ register: nonsensitive_stdout - name: Install | Pausing to highlight stdout message above - ansible.builtin.pause: - seconds: 5 + ansible.builtin.wait_for: + timeout: 5 when: nonsensitive_stdout is not skipped - name: Install | Clear State Upon Error