diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 0000000..ff1696e --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,2 @@ +--- +offline: true diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..4372d22 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,27 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' +--- +### Describe the bug +A clear and concise description of what the bug is. + +### To reproduce +Steps to reproduce the behavior: +1. Deploy NGINX Controller Agent role using playbook.yml +2. View output/logs/configuration on '...' +3. See error + +### Expected behavior +A clear and concise description of what you expected to happen. + +### Your environment: +- Version of the NGINX Controller Agent role or specific commit +- Version of Ansible +- Version of Jinja2 (if you are using any templating capability) +- Target deployment platform + +### Additional context +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..3ecf9b2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,18 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' +--- +### Is your feature request related to a problem? Please describe +A clear and concise description of what the problem is. Ex. I'm always frustrated when ... + +### Describe the solution you'd like +A clear and concise description of what you want to happen. + +### Describe alternatives you've considered +A clear and concise description of any alternative solutions or features you've considered. + +### Additional context +Add any other context or screenshots about the feature request here. diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..b11b8e4 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +## Supported Versions + +This role mainly consists of Ansible tasks. Ansible applies security fixes to the most recent three releases. Please find more information in [the Ansible docs](https://docs.ansible.com/ansible/devel/reference_appendices/release_and_maintenance.html#release-status). + +## Reporting a Vulnerability + +If you find a security vulnerability that affects Ansible, we encourage you to report it according to the [Ansible guidelines](https://docs.ansible.com/ansible/devel/community/reporting_bugs_and_features.html#reporting-a-bug). diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8a337e0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +--- +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + - package-ecosystem: "pip" + directory: "/.github/workflows/requirements" + schedule: + interval: "daily" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..9a82314 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,10 @@ +### Proposed changes +Describe the use case and detail of the change. If this PR addresses an issue on GitHub, make sure to include a link to that issue using one of the [supported keywords](https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue) here in this description (not in the title of the PR). + +### Checklist +Before creating a PR, run through this checklist and mark each as complete. + +- [ ] I have read the [CONTRIBUTING](https://github.com/nginxinc/ansible-role-nginx-controller-agent/blob/main/CONTRIBUTING.md) document +- [ ] I have added Molecule tests that prove my fix is effective or that my feature works +- [ ] I have checked that any relevant Molecule tests pass after adding my changes +- [ ] I have updated any relevant documentation (`defaults/main/*.yml`, `README.md` and `CHANGELOG.md`) diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..f096f76 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,99 @@ +--- +name-template: "$RESOLVED_VERSION" +tag-template: "$RESOLVED_VERSION" +categories: + - title: "💣 Breaking Changes" + labels: + - "breaking change" + - title: "🔔 Deprecation Warnings" + labels: + - "deprecation" + - title: "🚀 Features" + labels: + - "feature" + - title: "🎉 Enhancements" + labels: + - "enhancement" + - title: "🐛 Bug Fixes" + labels: + - "bug" + - title: "📝 Documentation" + labels: + - "documentation" + - title: "⬆️ Dependencies" + labels: + - "dependencies" +exclude-labels: + - "skip-changelog" +version-resolver: + minor: + labels: + - "breaking change" + - "deprecation" + patch: + labels: + - "bug" + - "dependencies" + - "documentation" + - "feature" + - "enhancement" + default: patch +autolabeler: + - label: "breaking change" + body: + - "/breaking/i" + - label: "deprecation" + branch: + - "/deprecate\/.+/" + title: + - "/deprecate/i" + - label: "feature" + branch: + - "/feat\/.+/" + - "/feature\/.+/" + - "/implement\/.+/" + title: + - "/feat/i" + - "/feature/i" + - "/implement/i" + - label: "enhancement" + branch: + - "/add\/.+/" + - "/enhancement\/.+/" + title: + - "/add/i" + - "/enhancement/i" + - label: "bug" + branch: + - "/fix\/.+/" + title: + - "/fix/i" + - label: "documentation" + branch: + - "/docs\/.+/" + files: + - "**/!(changelog).md" + title: + - "/docs/i" + - "/documentation/i" + - label: "dependencies" + files: + - ".github/workflows/requirements/*" +template: | + 👾 *Help make the NGINX Controller Agent Ansible role better by participating in our [survey](https://forms.office.com/Pages/ResponsePage.aspx?id=L_093Ttq0UCb4L-DJ9gcUKLQ7uTJaE1PitM_37KR881UM0NCWkY5UlE5MUYyWU1aTUcxV0NRUllJSC4u)!* 👾 + + ## What's new in NGINX's Controller Agent Ansible role $RESOLVED_VERSION! + + $CHANGES + + ## Install & Upgrade + + * To install the Ansible NGINX Controller Agent role on a fresh environment, run `ansible-galaxy install nginxinc.nginx_controller_agent`. + * To upgrade the Ansible NGINX Controller Agent role to the latest release, run `ansible-galaxy install -f nginxinc.nginx_controller_agent`. + * To install or upgrade to this specific Ansible NGINX Controller Agent role release ($RESOLVED_VERSION), run `ansible-galaxy install -f nginxinc.nginx_controller_agent,v$RESOLVED_VERSION`. + + ## Resources + + * Functional configuration examples (check `converge.yml` under each `molecule` scenario) -- [github.com/nginxinc/ansible-role-nginx-controller-agent/tree/$RESOLVED_VERSION/molecule](https://github.com/nginxinc/ansible-role-nginx-controller-agent/tree/$RESOLVED_VERSION/molecule). + * Ansible Galaxy repository -- [galaxy.ansible.com/nginxinc/nginx_controller_agent](https://galaxy.ansible.com/nginxinc/nginx_controller_agent). + * NGINX: Better with Ansible demo -- [github.com/alessfg/nginx-ansible-demo](https://github.com/alessfg/nginx-ansible-demo). diff --git a/.github/workflows/galaxy.yml b/.github/workflows/galaxy.yml new file mode 100644 index 0000000..44cab65 --- /dev/null +++ b/.github/workflows/galaxy.yml @@ -0,0 +1,24 @@ +--- +name: Ansible Galaxy import +"on": + release: + types: + - published +jobs: + galaxy: + name: Galaxy + runs-on: ubuntu-20.04 + steps: + - name: Check out the codebase + uses: actions/checkout@v2.3.4 + + - name: Set up Python 3 + uses: actions/setup-python@v2.2.2 + with: + python-version: 3.x + + - name: Install Ansible + run: pip3 install -r .github/workflows/requirements/requirements_galaxy.txt + + - name: Import release to Ansible Galaxy + run: ansible-galaxy role import --api-key ${{ secrets.GALAXY_API_KEY }} $(echo ${{ github.repository }} | cut -d/ -f1) $(echo ${{ github.repository }} | cut -d/ -f2) diff --git a/.github/workflows/molecule.yml b/.github/workflows/molecule.yml new file mode 100644 index 0000000..d7fb469 --- /dev/null +++ b/.github/workflows/molecule.yml @@ -0,0 +1,47 @@ +--- +name: Molecule CI/CD +"on": + pull_request: + branches: + - main + push: + branches: + - main + ignore-tags: + - "*" + schedule: + - cron: "0 0 1 * *" + workflow_dispatch: +jobs: + molecule: + name: Molecule + runs-on: ubuntu-20.04 + strategy: + matrix: + scenario: + - default + steps: + - name: Check out the codebase + if: "!(matrix.scenario == 'default' && github.event.pull_request.head.repo.full_name != github.repository)" + uses: actions/checkout@v2.3.4 + + - name: Set up Python 3 + if: "!(matrix.scenario == 'default' && github.event.pull_request.head.repo.full_name != github.repository)" + uses: actions/setup-python@v2.2.2 + with: + python-version: 3.x + + - name: Install Molecule dependencies + if: "!(matrix.scenario == 'default' && github.event.pull_request.head.repo.full_name != github.repository)" + run: pip3 install -r .github/workflows/requirements/requirements_molecule.txt + + - name: Install Ansible base dependencies + if: "!(contains(matrix.scenario, 'default') && github.event.pull_request.head.repo.full_name != github.repository)" + run: ansible-galaxy install -r .github/workflows/requirements/requirements_ansible.yml + + - name: Run Molecule tests + if: "!(matrix.scenario == 'default' && github.event.pull_request.head.repo.full_name != github.repository)" + run: molecule test -s ${{ matrix.scenario }} + env: + PY_COLORS: "1" + ANSIBLE_FORCE_COLOR: "1" diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000..df48be6 --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,19 @@ +--- +name: Release Drafter +"on": + pull_request: + types: + - opened + - reopened + - synchronize + push: + branches: + - main +jobs: + update_release_draft: + name: Update release draft + runs-on: ubuntu-20.04 + steps: + - uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/requirements/requirements_ansible.yml b/.github/workflows/requirements/requirements_ansible.yml new file mode 100644 index 0000000..6089368 --- /dev/null +++ b/.github/workflows/requirements/requirements_ansible.yml @@ -0,0 +1,4 @@ +--- +collections: + - name: community.docker + version: 1.7.0 diff --git a/.github/workflows/requirements/requirements_galaxy.txt b/.github/workflows/requirements/requirements_galaxy.txt new file mode 100644 index 0000000..b654dee --- /dev/null +++ b/.github/workflows/requirements/requirements_galaxy.txt @@ -0,0 +1 @@ +ansible-core==2.11.4 diff --git a/.github/workflows/requirements/requirements_molecule.txt b/.github/workflows/requirements/requirements_molecule.txt new file mode 100644 index 0000000..2e228af --- /dev/null +++ b/.github/workflows/requirements/requirements_molecule.txt @@ -0,0 +1,6 @@ +ansible-core==2.11.4 +Jinja2==3.0.1 +ansible-lint==5.1.2 +yamllint==1.26.3 +molecule[docker]==3.4.0 +docker==5.0.0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1fd827f --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +# Any private crt and keys # +############################ +*.crt +*.key +*~ +\#* +!molecule.crt +!molecule.key + +# OS Specific # +############### +Thumbs.db +.DS_Store +.vscode + +# Ansible specific # +#################### +.cache +*.retry + +# Python specific # +################### +__pycache__ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 702190a..0000000 --- a/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ ---- -sudo: required -language: python -services: - - docker -env: - - scenario: default -before_install: - - sudo apt-get -qq update -install: - - pip install ansible==2.9.5 - - pip install molecule[docker]==2.22 -script: - - travis_wait 50 molecule lint -s $scenario -notifications: - webhooks: https://galaxy.ansible.com/api/v1/notifications/ diff --git a/.yamllint b/.yamllint index cfab5e4..ff6d5ce 100644 --- a/.yamllint +++ b/.yamllint @@ -1,3 +1,4 @@ +--- extends: default rules: @@ -9,4 +10,3 @@ rules: level: error comments-indentation: disable line-length: disable - truthy: disable diff --git a/README.md b/README.md index 4a2ba4e..25978f8 100644 --- a/README.md +++ b/README.md @@ -108,4 +108,4 @@ Author Information [Daniel Edgar](https://github.com/aknot242) -© [NGINX, Inc.](https://www.nginx.com/) 2020 +© [NGINX, Inc.](https://www.nginx.com/) 2021 diff --git a/meta/main.yml b/meta/main.yml index 0ae616a..45a73bc 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -4,6 +4,7 @@ galaxy_info: description: A role to install, configure, and upgrade the NGINX Controller agent alongside an NGINX Plus instance in a machine. company: F5 Networks, Inc. role_name: nginx_controller_agent + namespace: nginxinc license: Apache License, Version 2.0 @@ -28,6 +29,7 @@ galaxy_info: versions: - xenial - bionic + - focal galaxy_tags: - nginx diff --git a/molecule/MockServerDockerfile b/molecule/MockServerDockerfile new file mode 100644 index 0000000..5d66d73 --- /dev/null +++ b/molecule/MockServerDockerfile @@ -0,0 +1,22 @@ +# +# MockServer Dockerfile +# +# https://github.com/mock-server/mockserver +# http://www.mock-server.com +# + +# build image +FROM alpine:3.12 + +# download jar +RUN apk add --update openssl ca-certificates bash wget curl openrc python3 sudo openjdk11-jre +# REPOSITORY is releases or snapshots +ARG REPOSITORY=releases +# VERSION is LATEST or RELEASE or x.x.x +ARG VERSION=RELEASE +# see: https://oss.sonatype.org/nexus-restlet1x-plugin/default/docs/path__artifact_maven_redirect.html +ARG REPOSITORY_URL=https://oss.sonatype.org/service/local/artifact/maven/redirect?r=${REPOSITORY}&g=org.mock-server&a=mockserver-netty&c=jar-with-dependencies&e=jar&v=${VERSION} +RUN wget --max-redirect=10 -O mockserver-netty-jar-with-dependencies.jar "$REPOSITORY_URL" + +# expose ports. +EXPOSE 1080 diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml new file mode 100644 index 0000000..179fe50 --- /dev/null +++ b/molecule/default/converge.yml @@ -0,0 +1,11 @@ +--- +- name: Converge + hosts: instances + tasks: + - name: Call Agent Role + include_role: + name: ansible-role-nginx-controller-agent + vars: + nginx_controller_fqdn: mock-server.molecule-test:1080 + nginx_controller_validate_certs: false + nginx_controller_api_key: "ABC123" diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml index 84ce594..5320c58 100644 --- a/molecule/default/molecule.yml +++ b/molecule/default/molecule.yml @@ -1,30 +1,31 @@ --- -dependency: - name: galaxy - options: - ignore-certs: true - ignore-errors: true - role-file: requirements.yml driver: name: docker -lint: - name: yamllint +lint: | + set -e + yamllint . + ansible-lint --force-color platforms: - - name: debian-stretch - image: debian:stretch-slim - dockerfile: Dockerfile.j2 - - name: debian-buster - image: debian:buster-slim - dockerfile: Dockerfile.j2 - - name: ubuntu-xenial - image: ubuntu:xenial - dockerfile: Dockerfile.j2 + - name: mock-server + groups: + - mock_server + image: alpine:3.12 + dockerfile: ../MockServerDockerfile + networks: + - name: molecule-test + ports: + - 1080:1080 - name: ubuntu-bionic + groups: + - instances image: ubuntu:bionic - dockerfile: Dockerfile.j2 + dockerfile: ../Dockerfile.j2 + networks: + - name: molecule-test provisioner: name: ansible playbooks: - converge: playbook.yml - lint: - name: ansible-lint + prepare: prepare.yml + converge: converge.yml + verify: verify.yml + log: false diff --git a/molecule/default/playbook.yml b/molecule/default/playbook.yml index 4fd59df..9b5b0eb 100644 --- a/molecule/default/playbook.yml +++ b/molecule/default/playbook.yml @@ -1,15 +1,12 @@ --- - name: Converge - hosts: all + hosts: instances vars: - # controller: - # user_email: "user@example.com" - # user_password: "mySecurePassword" - # fqdn: "controller.mydomain.com" - # validate_certs: false - # api_key: "" + nginx_controller_fqdn: "controller.mydomain.com" + nginx_controller_api_key: "ABC123" tasks: - - include_role: + - name: Call agent install role + include_role: name: ansible-role-nginx-controller-agent diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml new file mode 100644 index 0000000..3ef7f56 --- /dev/null +++ b/molecule/default/prepare.yml @@ -0,0 +1,50 @@ +--- +- name: Prepare Test Node + hosts: instances + gather_facts: false + tasks: + - name: Create the conf.d directory + ansible.builtin.file: + path: /etc/nginx/conf.d/ + state: directory + mode: "0644" + +- name: Prepare Mock Server + hosts: mock_server + become: true + tasks: + - name: Start mock server + raw: "nohup java -Dfile.encoding=UTF-8 -cp /mockserver-netty-jar-with-dependencies.jar:/libs/* -Dmockserver.propertyFile=/mockserver.properties org.mockserver.cli.Main -serverPort 1080 /dev/null 2>&1 & sleep 1" + changed_when: false + +- name: Set Expectations + hosts: mock_server + connection: local + gather_facts: false + tasks: + - name: Reset mock server expectations + uri: + url: "https://{{ inventory_hostname }}:1080/mockserver/reset" + method: PUT + status_code: 200 + headers: + Content-Type: application/json + validate_certs: false + + - name: Create agent script expectation + uri: + url: "https://{{ inventory_hostname }}:1080/mockserver/expectation" + method: PUT + body: + httpRequest: + method: "GET" + path: "/install/controller-agent" + httpResponse: + statusCode: 200 + body: "mkdir /var/log/nginx-controller && touch /var/log/nginx-controller/agent.log" + + status_code: 201 + body_format: json + headers: + Content-Type: application/json + validate_certs: false diff --git a/molecule/default/requirements.yml b/molecule/default/requirements.yml deleted file mode 100644 index 94ce8f4..0000000 --- a/molecule/default/requirements.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -- src: https://github.com/nginxinc/ansible-role-nginx-controller-generate-token diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml new file mode 100644 index 0000000..422cfc8 --- /dev/null +++ b/molecule/default/verify.yml @@ -0,0 +1,41 @@ +--- +- name: Verify Mock + hosts: mock_server + connection: local + tasks: + - name: Check that the agent script request was sent to the mock controller exactly twice per docker instance (includes the idempotence test) + uri: + url: "https://{{ inventory_hostname }}:1080/mockserver/verify" + method: PUT + body: + httpRequest: + path: "/install/controller-agent" + times: + atLeast: 2 + atMost: 2 + status_code: 202 + body_format: json + headers: + Content-Type: application/json + validate_certs: false + +- name: Verify File + hosts: instances + tasks: + - name: Store the statistics of /etc/nginx/conf.d/nginx-plus-api.conf in the 'conf_file' variable + stat: + path: /etc/nginx/conf.d/nginx-plus-api.conf + register: conf_file + + - name: Ensure /etc/nginx/conf.d/nginx-plus-api.conf exists + assert: + that: conf_file.stat.exists == true + + - name: Store the statistics of /var/log/nginx-controller/agent.log in the 'agent_log_file' variable + stat: + path: /var/log/nginx-controller/agent.log + register: agent_log_file + + - name: Ensure /var/log/nginx-controller/agent.log exists + assert: + that: agent_log_file.stat.exists == true diff --git a/tasks/main.yml b/tasks/main.yml index 0c335c1..01d6d77 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -6,18 +6,20 @@ - nginx_controller_fqdn - nginx_controller_api_key -- name: COPY files/nginx-plus-api.conf /etc/nginx/conf.d/ necessary for process monitoring. +- name: Copy files/nginx-plus-api.conf to /etc/nginx/conf.d/ necessary for process monitoring copy: src: "files/nginx-plus-api.conf" dest: "/etc/nginx/conf.d/nginx-plus-api.conf" - force: yes + mode: preserve + force: true - name: Download the installer script from NGINX Controller get_url: - url: "https://{{ nginx_controller_fqdn }}:8443/1.4/install/controller/" + url: "https://{{ nginx_controller_fqdn }}/install/controller-agent" dest: "{{ ansible_env.HOME }}/install.sh" validate_certs: "{{ nginx_controller_validate_certs | default(false) }}" - force: yes + force: true + changed_when: false register: nginx_controller_return - name: Run the NGINX Controller agent installer @@ -31,19 +33,15 @@ args: chdir: "{{ ansible_env.HOME }}" creates: /var/log/nginx-controller/agent.log + changed_when: false register: nginx_controller_agent_install - name: Output agent install results debug: var: nginx_controller_agent_install.stdout_lines -# - name: Restart NGINX -# service: -# name: nginx -# state: restarted - -- name: remove the install script +- name: Remove the install script file: path: "{{ ansible_env.HOME }}/install.sh" state: absent - \ No newline at end of file + changed_when: false