diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 659ad8c..3b8adbf 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -8,3 +8,17 @@ # These folks own any files in the .github directory at the root of # the repository and any of its subdirectories. /.github/ @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj + +# These folks own all linting configuration files. +/.ansible-lint @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/.bandit.yml @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/.flake8 @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/.isort.cfg @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/.mdl_config.yaml @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/.pre-commit-config.yaml @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/.prettierignore @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/.yamllint @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/requirements.txt @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/requirements-dev.txt @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/requirements-test.txt @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/setup-env @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 867f572..e112ceb 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -19,6 +19,8 @@ updates: - dependency-name: hashicorp/setup-terraform - dependency-name: mxschmitt/action-tmate - dependency-name: step-security/harden-runner + # Managed by cisagov/skeleton-ansible-role + - dependency-name: github/codeql-action package-ecosystem: github-actions schedule: interval: weekly @@ -27,7 +29,7 @@ updates: ignore: # Managed by cisagov/skeleton-ansible-role - dependency-name: ansible - - dependency-name: ansible-lint + - dependency-name: ansible-core package-ecosystem: pip schedule: interval: weekly diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2a79d87..b57fa87 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,16 +2,31 @@ name: build on: - push: + merge_group: + types: + - checks_requested pull_request: + push: repository_dispatch: - types: [apb] + types: + - apb + +# Set a default shell for any run steps. The `-Eueo pipefail` sets errtrace, +# nounset, errexit, and pipefail. The `-x` will print all commands as they are +# run. Please see the GitHub Actions documentation for more information: +# https://docs.github.com/en/actions/using-jobs/setting-default-values-for-jobs +defaults: + run: + shell: bash -Eueo pipefail -x {0} env: CURL_CACHE_DIR: ~/.cache/curl PIP_CACHE_DIR: ~/.cache/pip PRE_COMMIT_CACHE_DIR: ~/.cache/pre-commit RUN_TMATE: ${{ secrets.RUN_TMATE }} + TERRAFORM_DOCS_REPO_BRANCH_NAME: improvement/support_atx_closed_markdown_headers + TERRAFORM_DOCS_REPO_DEPTH: 1 + TERRAFORM_DOCS_REPO_URL: https://github.com/mcdonnnj/terraform-docs.git jobs: diagnostics: @@ -27,7 +42,7 @@ jobs: egress-policy: audit - id: github-status name: Check GitHub status - uses: crazy-max/ghaction-github-status@v3 + uses: crazy-max/ghaction-github-status@v4 - id: dump-context name: Dump context uses: crazy-max/ghaction-dump-context@v2 @@ -45,20 +60,20 @@ jobs: uses: cisagov/setup-env-github-action@develop - uses: actions/checkout@v4 - id: setup-python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: ${{ steps.setup-env.outputs.python-version }} # We need the Go version and Go cache location for the actions/cache step, # so the Go installation must happen before that. - id: setup-go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: # There is no expectation for actual Go code so we disable caching as # it relies on the existence of a go.sum file. cache: false - go-version: "1.20" - - name: Lookup Go cache directory - id: go-cache + go-version: ${{ steps.setup-env.outputs.go-version }} + - id: go-cache + name: Lookup Go cache directory run: | echo "dir=$(go env GOCACHE)" >> $GITHUB_OUTPUT - uses: actions/cache@v3 @@ -69,6 +84,10 @@ jobs: packer${{ steps.setup-env.outputs.packer-version }}-\ tf${{ steps.setup-env.outputs.terraform-version }}-" with: + key: "${{ env.BASE_CACHE_KEY }}\ + ${{ hashFiles('**/requirements-test.txt') }}-\ + ${{ hashFiles('**/requirements.txt') }}-\ + ${{ hashFiles('**/.pre-commit-config.yaml') }}" # Note that the .terraform directory IS NOT included in the # cache because if we were caching, then we would need to use # the `-upgrade=true` option. This option blindly pulls down the @@ -80,10 +99,6 @@ jobs: ${{ env.PRE_COMMIT_CACHE_DIR }} ${{ env.CURL_CACHE_DIR }} ${{ steps.go-cache.outputs.dir }} - key: "${{ env.BASE_CACHE_KEY }}\ - ${{ hashFiles('**/requirements-test.txt') }}-\ - ${{ hashFiles('**/requirements.txt') }}-\ - ${{ hashFiles('**/.pre-commit-config.yaml') }}" restore-keys: | ${{ env.BASE_CACHE_KEY }} - name: Setup curl cache @@ -101,7 +116,7 @@ jobs: ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" sudo mv /usr/local/bin/packer /usr/local/bin/packer-default sudo ln -s /opt/packer/packer /usr/local/bin/packer - - uses: hashicorp/setup-terraform@v2 + - uses: hashicorp/setup-terraform@v3 with: terraform_version: ${{ steps.setup-env.outputs.terraform-version }} - name: Install go-critic @@ -109,26 +124,38 @@ jobs: PACKAGE_URL: github.com/go-critic/go-critic/cmd/gocritic PACKAGE_VERSION: ${{ steps.setup-env.outputs.go-critic-version }} run: go install ${PACKAGE_URL}@${PACKAGE_VERSION} + - name: Install goimports + env: + PACKAGE_URL: golang.org/x/tools/cmd/goimports + PACKAGE_VERSION: ${{ steps.setup-env.outputs.goimports-version }} + run: go install ${PACKAGE_URL}@${PACKAGE_VERSION} - name: Install gosec env: PACKAGE_URL: github.com/securego/gosec/v2/cmd/gosec PACKAGE_VERSION: ${{ steps.setup-env.outputs.gosec-version }} run: go install ${PACKAGE_URL}@${PACKAGE_VERSION} - - name: Install shfmt - env: - PACKAGE_URL: mvdan.cc/sh/v3/cmd/shfmt - PACKAGE_VERSION: ${{ steps.setup-env.outputs.shfmt-version }} - run: go install ${PACKAGE_URL}@${PACKAGE_VERSION} - name: Install staticcheck env: PACKAGE_URL: honnef.co/go/tools/cmd/staticcheck PACKAGE_VERSION: ${{ steps.setup-env.outputs.staticcheck-version }} run: go install ${PACKAGE_URL}@${PACKAGE_VERSION} - - name: Install Terraform-docs - env: - PACKAGE_URL: github.com/terraform-docs/terraform-docs - PACKAGE_VERSION: ${{ steps.setup-env.outputs.terraform-docs-version }} - run: go install ${PACKAGE_URL}@${PACKAGE_VERSION} + # TODO: https://github.com/cisagov/skeleton-generic/issues/165 + # We are temporarily using @mcdonnnj's forked branch of terraform-docs + # until his PR: https://github.com/terraform-docs/terraform-docs/pull/745 + # is approved. This temporary fix will allow for ATX header support when + # terraform-docs is run during linting. + - name: Clone ATX headers branch from terraform-docs fork + run: | + git clone \ + --branch $TERRAFORM_DOCS_REPO_BRANCH_NAME \ + --depth $TERRAFORM_DOCS_REPO_DEPTH \ + --single-branch \ + $TERRAFORM_DOCS_REPO_URL /tmp/terraform-docs + - name: Build and install terraform-docs binary + run: | + go build \ + -C /tmp/terraform-docs \ + -o $(go env GOPATH)/bin/terraform-docs - name: Install dependencies run: | python -m pip install --upgrade pip setuptools wheel @@ -155,11 +182,13 @@ jobs: uses: step-security/harden-runner@v2 with: egress-policy: audit + - id: setup-env + uses: cisagov/setup-env-github-action@develop - uses: actions/checkout@v4 - id: setup-python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: ${{ steps.setup-env.outputs.python-version }} - uses: actions/cache@v3 env: BASE_CACHE_KEY: "${{ github.job }}-${{ runner.os }}-\ diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7493256..cfba96f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -7,6 +7,9 @@ name: CodeQL on: + merge_group: + types: + - checks_requested push: # Dependabot triggered push events have read-only access, but uploading code # scanning requires write access. @@ -20,8 +23,27 @@ on: - cron: '0 2 * * 6' jobs: + diagnostics: + name: Run diagnostics + runs-on: ubuntu-latest + steps: + # Note that a duplicate of this step must be added at the top of + # each job. + - id: harden-runner + name: Harden the runner + uses: step-security/harden-runner@v2 + with: + egress-policy: audit + - id: github-status + name: Check GitHub status + uses: crazy-max/ghaction-github-status@v3 + - id: dump-context + name: Dump context + uses: crazy-max/ghaction-dump-context@v2 analyze: name: Analyze + needs: + - diagnostics runs-on: ubuntu-latest permissions: # required for all workflows @@ -48,7 +70,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} @@ -56,7 +78,7 @@ jobs: # Java). If this step fails, then you should remove it and run the build # manually (see below). - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +92,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 44e8e19..5a20438 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -11,7 +11,26 @@ permissions: contents: read jobs: + diagnostics: + name: Run diagnostics + runs-on: ubuntu-latest + steps: + # Note that a duplicate of this step must be added at the top of + # each job. + - id: harden-runner + name: Harden the runner + uses: step-security/harden-runner@v2 + with: + egress-policy: audit + - id: github-status + name: Check GitHub status + uses: crazy-max/ghaction-github-status@v3 + - id: dump-context + name: Dump context + uses: crazy-max/ghaction-dump-context@v2 labeler: + needs: + - diagnostics permissions: # actions/checkout needs this to fetch code contents: read @@ -19,6 +38,11 @@ jobs: issues: write runs-on: ubuntu-latest steps: + - id: harden-runner + name: Harden the runner + uses: step-security/harden-runner@v2 + with: + egress-policy: audit - uses: actions/checkout@v4 - name: Sync repository labels if: success() diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index efe389b..48846e6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ default_language_version: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-case-conflict - id: check-executables-have-shebangs @@ -31,17 +31,24 @@ repos: # Text file hooks - repo: https://github.com/igorshubovych/markdownlint-cli - rev: v0.36.0 + rev: v0.39.0 hooks: - id: markdownlint args: - --config=.mdl_config.yaml - repo: https://github.com/pre-commit/mirrors-prettier - rev: v3.0.3 + # This is the last version of v3 available from the mirror. We should hold + # here until v4, which is currently in alpha, is more stable. + rev: v3.1.0 hooks: - id: prettier + # This is the latest version of v3 available from NPM. The pre-commit + # mirror does not pull tags for old major versions once a new major + # version tag is published. + additional_dependencies: + - prettier@3.2.5 - repo: https://github.com/adrienverge/yamllint - rev: v1.32.0 + rev: v1.35.1 hooks: - id: yamllint args: @@ -49,14 +56,14 @@ repos: # GitHub Actions hooks - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.26.3 + rev: 0.28.0 hooks: - id: check-github-actions - id: check-github-workflows # pre-commit hooks - repo: https://github.com/pre-commit/pre-commit - rev: v3.4.0 + rev: v3.6.2 hooks: - id: validate_manifest @@ -78,7 +85,11 @@ repos: - id: go-vet-repo-mod # GoSec - id: go-sec-repo-mod - + # goimports + - id: go-imports-repo + args: + # Write changes to files + - -w # Nix hooks - repo: https://github.com/nix-community/nixpkgs-fmt rev: v1.3.0 @@ -86,28 +97,32 @@ repos: - id: nixpkgs-fmt # Shell script hooks - - repo: https://github.com/cisagov/pre-commit-shfmt - rev: v0.0.2 + - repo: https://github.com/scop/pre-commit-shfmt + rev: v3.7.0-4 hooks: - id: shfmt args: + # List files that will be formatted + - --list + # Write result to file instead of stdout + - --write # Indent by two spaces - - -i - - '2' + - --indent + - "2" # Binary operators may start a line - - -bn + - --binary-next-line # Switch cases are indented - - -ci + - --case-indent # Redirect operators are followed by a space - - -sr - - repo: https://github.com/detailyang/pre-commit-shell - rev: 1.0.5 + - --space-redirects + - repo: https://github.com/shellcheck-py/shellcheck-py + rev: v0.9.0.6 hooks: - - id: shell-lint + - id: shellcheck # Python hooks - repo: https://github.com/PyCQA/bandit - rev: 1.7.5 + rev: 1.7.7 hooks: - id: bandit # Bandit complains about the use of assert() in tests @@ -115,38 +130,38 @@ repos: args: - --config=.bandit.yml - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.9.1 + rev: 24.2.0 hooks: - id: black - repo: https://github.com/PyCQA/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 additional_dependencies: - flake8-docstrings - repo: https://github.com/PyCQA/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.5.1 + rev: v1.8.0 hooks: - id: mypy - repo: https://github.com/asottile/pyupgrade - rev: v3.10.1 + rev: v3.15.1 hooks: - id: pyupgrade # Ansible hooks - repo: https://github.com/ansible/ansible-lint - rev: v6.19.0 + rev: v24.2.0 hooks: - id: ansible-lint # files: molecule/default/playbook.yml # Terraform hooks - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.83.2 + rev: v1.88.0 hooks: - id: terraform_fmt - id: terraform_validate diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7f5af64..928fbfd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,9 +46,13 @@ There are a few ways to do this, but we prefer to use create and manage a Python virtual environment specific to this project. -If you already have `pyenv` and `pyenv-virtualenv` configured you can -take advantage of the `setup-env` tool in this repo to automate the -entire environment configuration process. +We recommend using the `setup-env` script located in this repository, +as it automates the entire environment configuration process. The +dependencies required to run this script are +[GNU `getopt`](https://github.com/util-linux/util-linux/blob/master/misc-utils/getopt.1.adoc), +[`pyenv`](https://github.com/pyenv/pyenv), and [`pyenv-virtualenv`](https://github.com/pyenv/pyenv-virtualenv). +If these tools are already configured on your system, you can simply run the +following command: ```console ./setup-env @@ -57,13 +61,18 @@ entire environment configuration process. Otherwise, follow the steps below to manually configure your environment. -#### Installing and using `pyenv` and `pyenv-virtualenv` #### +#### Installing and using GNU `getopt`, `pyenv`, and `pyenv-virtualenv` #### -On the Mac, we recommend installing [brew](https://brew.sh/). Then -installation is as simple as `brew install pyenv pyenv-virtualenv` and +On macOS, we recommend installing [brew](https://brew.sh/). Then +installation is as simple as `brew install gnu-getopt pyenv pyenv-virtualenv` and adding this to your profile: ```bash +# GNU getopt must be explicitly added to the path since it is +# keg-only (https://docs.brew.sh/FAQ#what-does-keg-only-mean) +export PATH="$(brew --prefix)/opt/gnu-getopt/bin:$PATH" + +# Setup pyenv export PYENV_ROOT="$HOME/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init --path)" @@ -71,13 +80,15 @@ eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)" ``` -For Linux, Windows Subsystem for Linux (WSL), or on the Mac (if you +For Linux, Windows Subsystem for Linux (WSL), or macOS (if you don't want to use `brew`) you can use [pyenv/pyenv-installer](https://github.com/pyenv/pyenv-installer) to install the necessary tools. Before running this ensure that you have installed the prerequisites for your platform according to the [`pyenv` wiki page](https://github.com/pyenv/pyenv/wiki/common-build-problems). +GNU `getopt` is included in most Linux distributions as part of the +[`util-linux`](https://github.com/util-linux/util-linux) package. On WSL you should treat your platform as whatever Linux distribution you've chosen to install. diff --git a/README.md b/README.md index c789c15..bdc57b1 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,28 @@ None. None. +## Installation ## + +This role can be installed via the command: + +```console +ansible-galaxy install --role-file path/to/requirements.yml +``` + +where `requirements.yml` looks like: + +```yaml +--- +- name: nvme + src: https://github.com/cisagov/ansible-role-nvme +``` + +and may contain other roles as well. + +For more information about installing Ansible roles via a YAML file, +please see [the `ansible-galaxy` +documentation](https://docs.ansible.com/ansible/latest/galaxy/user_guide.html#installing-multiple-roles-from-a-file). + ## Example Playbook ## Here's how to use it in a playbook: diff --git a/meta/main.yml b/meta/main.yml index 7ba648b..ef6e6ea 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -28,10 +28,11 @@ galaxy_info: - buster - bullseye - bookworm + - trixie - name: Fedora versions: - - "37" - "38" + - "39" - name: Kali versions: - "2023" diff --git a/meta/requirements.yml b/meta/requirements.yml index d8f8eef..bdeda61 100644 --- a/meta/requirements.yml +++ b/meta/requirements.yml @@ -1,12 +1,7 @@ --- -# Note that dependencies listed here are made available to the role -# but _are not_ automatically installed. Role variables cannot be -# specified here. -# -# It _is_ possible to list both collections and roles in this file, -# but unfortunately ansible-galaxy attempts to naively merge the -# dependencies listed in meta/main.yml with these. That means that -# both sets of dependencies must be lists. :( +# Note that role dependencies listed here are made available to the +# role but _are not_ automatically installed. Role variables cannot +# be specified here. # # See also cisagov/skeleton-ansible-role#153. [] diff --git a/molecule/default/molecule-no-systemd.yml b/molecule/default/molecule-no-systemd.yml deleted file mode 100644 index d7555d4..0000000 --- a/molecule/default/molecule-no-systemd.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# This molecule configuration file is suitable for testing Ansible -# roles that _do not_ require SystemD. If your Ansible role _does_ -# require SystemD then you should use molecule-with-systemd.yml -# instead. -# -# Note that the molecule configuration file that is symlinked to -# molecule.yml is the one that will be used. -dependency: - name: galaxy -driver: - name: docker -platforms: - - image: amazonlinux:2023 - name: amazonlinux2023 - platform: amd64 - - image: debian:buster-slim - name: debian10 - platform: amd64 - - image: debian:bullseye-slim - name: debian11 - platform: amd64 - - image: debian:bookworm-slim - name: debian12 - platform: amd64 - - image: kalilinux/kali-rolling - name: kali - platform: amd64 - - image: fedora:37 - name: fedora37 - platform: amd64 - - image: fedora:38 - name: fedora38 - platform: amd64 - - image: ubuntu:focal - name: ubuntu20 - platform: amd64 - - image: ubuntu:jammy - name: ubuntu22 - platform: amd64 -scenario: - name: default -verifier: - name: testinfra diff --git a/molecule/default/molecule-with-systemd.yml b/molecule/default/molecule-with-systemd.yml deleted file mode 100644 index 8039782..0000000 --- a/molecule/default/molecule-with-systemd.yml +++ /dev/null @@ -1,97 +0,0 @@ ---- -# This molecule configuration file is suitable for testing Ansible -# roles that _do_ require SystemD. If your Ansible role _does not_ -# require SystemD then you should use molecule-no-systemd.yml instead. -# -# Note that the molecule configuration file that is symlinked to -# molecule.yml is the one that will be used. -dependency: - name: galaxy -driver: - name: docker -platforms: - - cgroupns_mode: host - command: /lib/systemd/systemd - image: geerlingguy/docker-amazonlinux2023-ansible:latest - name: amazonlinux2023-systemd - platform: amd64 - pre_build_image: true - privileged: true - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:rw - - cgroupns_mode: host - command: /lib/systemd/systemd - image: geerlingguy/docker-debian10-ansible:latest - name: debian10-systemd - platform: amd64 - pre_build_image: true - privileged: true - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:rw - - cgroupns_mode: host - command: /lib/systemd/systemd - image: geerlingguy/docker-debian11-ansible:latest - name: debian11-systemd - platform: amd64 - pre_build_image: true - privileged: true - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:rw - - cgroupns_mode: host - command: /lib/systemd/systemd - image: cisagov/docker-debian12-ansible:latest - name: debian12-systemd - platform: amd64 - pre_build_image: true - privileged: true - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:rw - - cgroupns_mode: host - command: /lib/systemd/systemd - image: cisagov/docker-kali-ansible:latest - name: kali-systemd - platform: amd64 - pre_build_image: true - privileged: true - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:rw - - cgroupns_mode: host - command: /lib/systemd/systemd - image: geerlingguy/docker-fedora37-ansible:latest - name: fedora37-systemd - platform: amd64 - pre_build_image: true - privileged: true - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:rw - - cgroupns_mode: host - command: /lib/systemd/systemd - image: geerlingguy/docker-fedora38-ansible:latest - name: fedora38-systemd - platform: amd64 - pre_build_image: true - privileged: true - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:rw - - cgroupns_mode: host - command: /lib/systemd/systemd - image: geerlingguy/docker-ubuntu2004-ansible:latest - name: ubuntu-20-systemd - platform: amd64 - pre_build_image: true - privileged: true - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:rw - - cgroupns_mode: host - command: /lib/systemd/systemd - image: geerlingguy/docker-ubuntu2204-ansible:latest - name: ubuntu-22-systemd - platform: amd64 - pre_build_image: true - privileged: true - volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:rw -scenario: - name: default -verifier: - name: testinfra diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml deleted file mode 120000 index 35a50fd..0000000 --- a/molecule/default/molecule.yml +++ /dev/null @@ -1 +0,0 @@ -molecule-no-systemd.yml \ No newline at end of file diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml new file mode 100644 index 0000000..b4b3c96 --- /dev/null +++ b/molecule/default/molecule.yml @@ -0,0 +1,100 @@ +--- +dependency: + name: galaxy +driver: + name: docker +platforms: + - cgroupns_mode: host + command: /lib/systemd/systemd + image: docker.io/geerlingguy/docker-amazonlinux2023-ansible:latest + name: amazonlinux2023-systemd + platform: amd64 + pre_build_image: true + privileged: true + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + - cgroupns_mode: host + command: /lib/systemd/systemd + image: docker.io/geerlingguy/docker-debian10-ansible:latest + name: debian10-systemd + platform: amd64 + pre_build_image: true + privileged: true + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + - cgroupns_mode: host + command: /lib/systemd/systemd + image: docker.io/geerlingguy/docker-debian11-ansible:latest + name: debian11-systemd + platform: amd64 + pre_build_image: true + privileged: true + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + - cgroupns_mode: host + command: /lib/systemd/systemd + image: docker.io/geerlingguy/docker-debian12-ansible:latest + name: debian12-systemd + platform: amd64 + pre_build_image: true + privileged: true + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + - cgroupns_mode: host + command: /lib/systemd/systemd + image: docker.io/cisagov/docker-debian13-ansible:latest + name: debian13-systemd + platform: amd64 + pre_build_image: true + privileged: true + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + - cgroupns_mode: host + command: /lib/systemd/systemd + image: docker.io/cisagov/docker-kali-ansible:latest + name: kali-systemd + platform: amd64 + pre_build_image: true + privileged: true + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + - cgroupns_mode: host + command: /lib/systemd/systemd + image: docker.io/geerlingguy/docker-fedora38-ansible:latest + name: fedora38-systemd + platform: amd64 + pre_build_image: true + privileged: true + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + - cgroupns_mode: host + command: /lib/systemd/systemd + image: docker.io/geerlingguy/docker-fedora39-ansible:latest + name: fedora39-systemd + platform: amd64 + pre_build_image: true + privileged: true + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + - cgroupns_mode: host + command: /lib/systemd/systemd + image: docker.io/geerlingguy/docker-ubuntu2004-ansible:latest + name: ubuntu-20-systemd + platform: amd64 + pre_build_image: true + privileged: true + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + - cgroupns_mode: host + command: /lib/systemd/systemd + image: docker.io/geerlingguy/docker-ubuntu2204-ansible:latest + name: ubuntu-22-systemd + platform: amd64 + pre_build_image: true + privileged: true + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw +scenario: + name: default +verifier: + name: testinfra diff --git a/molecule/default/upgrade.yml b/molecule/default/upgrade.yml index 14cf86b..356f84e 100644 --- a/molecule/default/upgrade.yml +++ b/molecule/default/upgrade.yml @@ -1,6 +1,6 @@ --- -- hosts: all - name: Upgrade base image +- name: Upgrade base image + hosts: all become: true become_method: ansible.builtin.sudo tasks: diff --git a/requirements-test.txt b/requirements-test.txt index f2dba15..09f58a0 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -6,8 +6,23 @@ # 2.10 or newer. # # We need at least version 6 to correctly identify Amazon Linux 2023 -# as using the dnf package manager. -ansible>=6,<7 +# as using the dnf package manager, and version 8 is currently the +# oldest supported version. +# +# We have tested against version 9. We want to avoid automatically +# jumping to another major version without testing, since there are +# often breaking changes across major versions. This is the reason +# for the upper bound. +ansible>=8,<10 +# TODO: Remove this pin when possible. See +# cisagov/skeleton-ansible-role#178 for more details. +# +# ansible-core 2.16.3 and later suffer from the bug discussed in +# ansible/ansible#82702, which breaks any symlinked files in vars, +# tasks, etc. for any Ansible role installed via ansible-galaxy. +# +# See also cisagov/skeleton-packer#312. +ansible-core<2.16.3 # With the release of molecule v5 there were some breaking changes so # we need to pin at v5 or newer. However, v5.0.0 had an internal # dependency issue so we must use the bugfix release as the actual diff --git a/setup-env b/setup-env index 77926bf..3a22d43 100755 --- a/setup-env +++ b/setup-env @@ -9,60 +9,76 @@ USAGE=$( Configure a development environment for this repository. It does the following: + - Allows the user to specify the Python version to use for the virtual environment. + - Allows the user to specify a name for the virtual environment. - Verifies pyenv and pyenv-virtualenv are installed. - - Creates a Python virtual environment. + - Creates the Python virtual environment. - Configures the activation of the virtual enviroment for the repo directory. - Installs the requirements needed for development. - Installs git pre-commit hooks. - - Configures git upstream remote "lineage" repositories. + - Configures git remotes for upstream "lineage" repositories. Usage: - setup-env [options] [virt_env_name] + setup-env [--venv-name venv_name] [--python-version python_version] setup-env (-h | --help) Options: - -f --force Delete virtual enviroment if it already exists. - -h --help Show this message. - -i --install-hooks Install hook environments for all environments in the - pre-commit config file. + -f | --force Delete virtual enviroment if it already exists. + -h | --help Show this message. + -i | --install-hooks Install hook environments for all environments in the + pre-commit config file. + -l | --list-versions List available Python versions and select one interactively. + -v | --venv-name Specify the name of the virtual environment. + -p | --python-version Specify the Python version for the virtual environment. END_OF_LINE ) +# Display pyenv's installed Python versions +python_versions() { + pyenv versions --bare --skip-aliases --skip-envs +} + # Flag to force deletion and creation of virtual environment FORCE=0 -# Positional parameters -PARAMS="" +# Initialize the other flags +INSTALL_HOOKS=0 +LIST_VERSIONS=0 +PYTHON_VERSION="" +VENV_NAME="" -# Parse command line arguments -while (("$#")); do - case "$1" in - -f | --force) - FORCE=1 - shift - ;; - -h | --help) - echo "${USAGE}" - exit 0 - ;; - -i | --install-hooks) - INSTALL_HOOKS=1 - shift - ;; - -*) # unsupported flags - echo "Error: Unsupported flag $1" >&2 - exit 1 - ;; - *) # preserve positional arguments - PARAMS="$PARAMS $1" - shift - ;; - esac -done +# Define long options +LONGOPTS="force,help,install-hooks,list-versions,python-version:,venv-name:" + +# Define short options for getopt +SHORTOPTS="fhilp:v:" + +# Check for GNU getopt by matching a specific pattern ("getopt from util-linux") +# in its version output. This approach presumes the output format remains stable. +# Be aware that format changes could invalidate this check. +if [[ $(getopt --version 2> /dev/null) != *"getopt from util-linux"* ]]; then + cat << 'END_OF_LINE' + + Please note, this script requires GNU getopt due to its enhanced + functionality and compatibility with certain script features that + are not supported by the POSIX getopt found in some systems, particularly + those with a non-GNU version of getopt. This distinction is crucial + as a system might have a non-GNU version of getopt installed by default, + which could lead to unexpected behavior. -# set positional arguments in their proper place -eval set -- "$PARAMS" + On macOS, we recommend installing brew (https://brew.sh/). Then installation + is as simple as `brew install gnu-getopt` and adding this to your + profile: + + export PATH="$(brew --prefix)/opt/gnu-getopt/bin:$PATH" + + GNU getopt must be explicitly added to the PATH since it + is keg-only (https://docs.brew.sh/FAQ#what-does-keg-only-mean). + +END_OF_LINE + exit 1 +fi # Check to see if pyenv is installed if [ -z "$(command -v pyenv)" ] || { [ -z "$(command -v pyenv-virtualenv)" ] && [ ! -f "$(pyenv root)/plugins/pyenv-virtualenv/bin/pyenv-virtualenv" ]; }; then @@ -70,7 +86,7 @@ if [ -z "$(command -v pyenv)" ] || { [ -z "$(command -v pyenv-virtualenv)" ] && if [[ "$OSTYPE" == "darwin"* ]]; then cat << 'END_OF_LINE' - On the Mac, we recommend installing brew, https://brew.sh/. Then installation + On macOS, we recommend installing brew, https://brew.sh/. Then installation is as simple as `brew install pyenv pyenv-virtualenv` and adding this to your profile: @@ -81,7 +97,7 @@ END_OF_LINE fi cat << 'END_OF_LINE' - For Linux, Windows Subsystem for Linux (WSL), or on the Mac (if you don't want + For Linux, Windows Subsystem for Linux (WSL), or macOS (if you don't want to use "brew") you can use https://github.com/pyenv/pyenv-installer to install the necessary tools. Before running this ensure that you have installed the prerequisites for your platform according to the pyenv wiki page, @@ -100,16 +116,88 @@ END_OF_LINE exit 1 fi -set +o nounset +# Use GNU getopt to parse options +if ! PARSED=$(getopt --options $SHORTOPTS --longoptions $LONGOPTS --name "$0" -- "$@"); then + echo "Error parsing options" + exit 1 +fi +eval set -- "$PARSED" + +while true; do + case "$1" in + -f | --force) + FORCE=1 + shift + ;; + -h | --help) + echo "$USAGE" + exit 0 + ;; + -i | --install-hooks) + INSTALL_HOOKS=1 + shift + ;; + -l | --list-versions) + LIST_VERSIONS=1 + shift + ;; + -p | --python-version) + PYTHON_VERSION="$2" + shift 2 + # Check the Python versions being passed in. + if [ -n "${PYTHON_VERSION+x}" ]; then + if python_versions | grep -E "^${PYTHON_VERSION}$" > /dev/null; then + echo Using Python version "$PYTHON_VERSION" + else + echo Error: Python version "$PYTHON_VERSION" is not installed. + echo Installed Python versions are: + python_versions + exit 1 + fi + fi + ;; + -v | --venv-name) + VENV_NAME="$2" + shift 2 + ;; + --) + shift + break + ;; + *) + # Unreachable due to GNU getopt handling all options + echo "Programming error" + exit 64 + ;; + esac +done + # Determine the virtual environment name -if [ "$1" ]; then +if [ -n "$VENV_NAME" ]; then # Use the user-provided environment name - env_name=$1 + env_name="$VENV_NAME" else # Set the environment name to the last part of the working directory. env_name=${PWD##*/} fi -set -o nounset + +# List Python versions and select one interactively. +if [ $LIST_VERSIONS -ne 0 ]; then + echo Available Python versions: + python_versions + # Read the user's desired Python version. + # -r: treat backslashes as literal, -p: display prompt before input. + read -r -p "Enter the desired Python version: " PYTHON_VERSION + # Check the Python versions being passed in. + if [ -n "${PYTHON_VERSION+x}" ]; then + if python_versions | grep -E "^${PYTHON_VERSION}$" > /dev/null; then + echo Using Python version "$PYTHON_VERSION" + else + echo Error: Python version "$PYTHON_VERSION" is not installed. + exit 1 + fi + fi +fi # Remove any lingering local configuration. if [ $FORCE -ne 0 ]; then @@ -118,7 +206,7 @@ if [ $FORCE -ne 0 ]; then elif [[ -f .python-version ]]; then cat << 'END_OF_LINE' An existing .python-version file was found. Either remove this file yourself - or re-run with --force option to have it deleted along with the associated + or re-run with the --force option to have it deleted along with the associated virtual environment. rm .python-version @@ -128,10 +216,18 @@ END_OF_LINE fi # Create a new virtual environment for this project -if ! pyenv virtualenv "${env_name}"; then +# +# If $PYTHON_VERSION is undefined then the current pyenv Python version will be used. +# +# We can't quote ${PYTHON_VERSION:=} below since if the variable is +# undefined then we want nothing to appear; this is the reason for the +# "shellcheck disable" line below. +# +# shellcheck disable=SC2086 +if ! pyenv virtualenv ${PYTHON_VERSION:=} "${env_name}"; then cat << END_OF_LINE An existing virtual environment named $env_name was found. Either delete this - environment yourself or re-run with --force option to have it deleted. + environment yourself or re-run with the --force option to have it deleted. pyenv virtualenv-delete ${env_name} diff --git a/tasks/main.yml b/tasks/main.yml index bbd9e9a..24fcf58 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,22 +1,11 @@ --- -# tasks file for nvme - - name: Install nvme-cli ansible.builtin.package: name: nvme-cli -- name: Set NVMe timeout value to use (Debian Stretch) - ansible.builtin.set_fact: - timeout_value: 255 - when: - - ansible_distribution == 'Debian' - - ansible_distribution_release == 'stretch' - -- name: Set NVMe timeout value to use (not Debian Stretch) +- name: Set NVMe timeout value to use ansible.builtin.set_fact: timeout_value: 4294967295 - when: - - ansible_distribution != 'Debian' or ansible_distribution_release != 'stretch' # Setting this kernel parameter to a high value fixes the bug where # NVMe volumes occassionally fail and are mounted read-only.