From 38b7c80217c4e72b1d8988eb1e60bb6e77334114 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 18 Apr 2024 07:52:22 +0200 Subject: Adding upstream version 9.4.0+dfsg. Signed-off-by: Daniel Baumann --- ansible_collections/grafana/grafana/.ansible-lint | 18 + .../grafana/grafana/.config/molecule/config.yml | 80 + ansible_collections/grafana/grafana/.editorconfig | 42 + .../grafana/grafana/.github/dependabot.yml | 11 + .../grafana/grafana/.github/workflows/ci-test.yml | 83 - .../.github/workflows/full-integration-test.yml | 18 +- .../grafana/grafana/.github/workflows/lint.yaml | 63 + .../grafana/.github/workflows/modules-test.yml | 98 ++ .../grafana/grafana/.github/workflows/release.yml | 38 +- .../grafana/.github/workflows/roles-test.yml | 90 + ansible_collections/grafana/grafana/.gitignore | 236 +++ .../grafana/grafana/.markdownlint.yaml | 261 +++ ansible_collections/grafana/grafana/.shellcheckrc | 7 + ansible_collections/grafana/grafana/.textlintrc | 187 +++ ansible_collections/grafana/grafana/.yamllint | 15 + ansible_collections/grafana/grafana/CHANGELOG.rst | 278 +++- ansible_collections/grafana/grafana/CODEOWNERS | 3 + ansible_collections/grafana/grafana/FILES.json | 858 +++++++++- ansible_collections/grafana/grafana/MANIFEST.json | 6 +- ansible_collections/grafana/grafana/Makefile | 86 + ansible_collections/grafana/grafana/Pipfile | 14 + ansible_collections/grafana/grafana/Pipfile.lock | 825 ++++++++++ ansible_collections/grafana/grafana/README.md | 82 +- ansible_collections/grafana/grafana/ansible.cfg | 2 + .../grafana/grafana/changelogs/.plugin-cache.yaml | 12 +- .../grafana/grafana/changelogs/changelog.yaml | 163 +- .../grafana/grafana/changelogs/config.yaml | 33 +- .../grafana/examples/agent-basic-no-options.yaml | 10 + .../examples/agent-send-to-grafana-cloud.yaml | 95 ++ .../grafana/grafana/examples/ansible.cfg | 32 + .../grafana/examples/monitor-multiple-instances.md | 184 +++ .../grafana/grafana/meta/runtime.yml | 2 +- ansible_collections/grafana/grafana/package.json | 26 + .../grafana/plugins/modules/alert_contact_point.py | 46 +- .../plugins/modules/alert_notification_policy.py | 33 +- .../grafana/plugins/modules/cloud_api_key.py | 2 +- .../grafana/plugins/modules/cloud_plugin.py | 2 +- .../grafana/grafana/plugins/modules/dashboard.py | 24 +- .../grafana/grafana/plugins/modules/datasource.py | 44 +- .../grafana/grafana/plugins/modules/folder.py | 47 +- .../grafana/grafana/requirements.txt | 3 + .../grafana/grafana/requirements.yml | 6 + .../grafana/grafana/roles/grafana/README.md | 142 ++ .../grafana/roles/grafana/defaults/main.yml | 278 ++++ .../grafana/roles/grafana/handlers/main.yml | 28 + .../grafana/grafana/roles/grafana/meta/main.yml | 31 + .../grafana/molecule/alternative/converge.yml | 105 ++ .../grafana/molecule/alternative/molecule.yml | 1 + .../molecule/alternative/tests/test_alternative.py | 52 + .../roles/grafana/molecule/default/converge.yml | 10 + .../roles/grafana/molecule/default/molecule.yml | 1 + .../grafana/molecule/default/tests/test_default.py | 50 + .../grafana/roles/grafana/tasks/api_keys.yml | 43 + .../grafana/roles/grafana/tasks/configure.yml | 106 ++ .../grafana/roles/grafana/tasks/dashboards.yml | 140 ++ .../grafana/roles/grafana/tasks/datasources.yml | 40 + .../grafana/roles/grafana/tasks/install.yml | 89 + .../grafana/grafana/roles/grafana/tasks/main.yml | 120 ++ .../grafana/roles/grafana/tasks/notifications.yml | 28 + .../grafana/roles/grafana/tasks/plugins.yml | 20 + .../grafana/roles/grafana/tasks/preflight.yml | 84 + .../grafana/roles/grafana/templates/grafana.ini.j2 | 214 +++ .../grafana/roles/grafana/templates/ldap.toml.j2 | 39 + .../grafana/roles/grafana/templates/tmpfiles.j2 | 2 + .../grafana/roles/grafana/test-requirements.txt | 6 + .../grafana/roles/grafana/vars/distro/debian.yml | 8 + .../grafana/roles/grafana/vars/distro/redhat.yml | 5 + .../grafana/roles/grafana/vars/distro/suse.yml | 2 + .../grafana/grafana/roles/grafana_agent/README.md | 92 +- .../grafana/roles/grafana_agent/defaults/main.yaml | 193 +++ .../grafana/roles/grafana_agent/defaults/main.yml | 20 - .../grafana/roles/grafana_agent/handlers/main.yaml | 12 + .../grafana/roles/grafana_agent/meta/main.yaml | 25 + .../grafana/roles/grafana_agent/meta/main.yml | 25 - .../roles/grafana_agent/tasks/configure.yaml | 51 + .../roles/grafana_agent/tasks/ga-started.yaml | 29 + .../grafana/roles/grafana_agent/tasks/install.yaml | 19 + .../grafana_agent/tasks/install/directories.yaml | 26 + .../tasks/install/download-install.yaml | 48 + .../grafana_agent/tasks/install/local-install.yaml | 10 + .../grafana_agent/tasks/install/user-group.yaml | 38 + .../grafana/roles/grafana_agent/tasks/main.yaml | 48 + .../grafana/roles/grafana_agent/tasks/main.yml | 59 - .../roles/grafana_agent/tasks/preflight.yaml | 12 + .../grafana_agent/tasks/preflight/download.yaml | 36 + .../grafana_agent/tasks/preflight/install.yaml | 72 + .../grafana_agent/tasks/preflight/systemd.yaml | 28 + .../roles/grafana_agent/tasks/preflight/vars.yaml | 72 + .../grafana_agent/templates/EnvironmentFile.j2 | 9 + .../roles/grafana_agent/templates/config.yaml.j2 | 37 + .../templates/grafana-agent.service.j2 | 62 + .../grafana/roles/grafana_agent/vars/main.yaml | 29 + .../targets/alert_contact_point/tasks/main.yml | 43 +- .../alert_notification_policy/tasks/main.yml | 3 +- .../targets/cloud_api_key/tasks/main.yml | 18 +- .../targets/cloud_plugin/tasks/main.yml | 27 +- .../integration/targets/cloud_stack/tasks/main.yml | 30 - .../targets/create_cloud_stack/tasks/main.yml | 18 + .../integration/targets/dashboard/tasks/main.yml | 59 +- .../integration/targets/datasource/tasks/main.yml | 53 +- .../targets/delete_cloud_stack/tasks/main.yml | 19 + .../integration/targets/folder/tasks/main.yml | 27 +- .../targets/molecule-grafana-alternative/runme.sh | 12 + .../targets/molecule-grafana-default/runme.sh | 12 + .../grafana/grafana/tools/includes/logging.sh | 123 ++ .../grafana/grafana/tools/includes/utils.sh | 66 + .../grafana/grafana/tools/lint-ansible.sh | 39 + .../grafana/grafana/tools/lint-editorconfig.sh | 38 + .../grafana/grafana/tools/lint-markdown.sh | 49 + .../grafana/grafana/tools/lint-shell.sh | 46 + .../grafana/grafana/tools/lint-text.sh | 40 + .../grafana/grafana/tools/lint-yaml.sh | 37 + ansible_collections/grafana/grafana/tools/setup.sh | 39 + ansible_collections/grafana/grafana/yarn.lock | 1721 ++++++++++++++++++++ 114 files changed, 8831 insertions(+), 549 deletions(-) create mode 100644 ansible_collections/grafana/grafana/.ansible-lint create mode 100644 ansible_collections/grafana/grafana/.config/molecule/config.yml create mode 100644 ansible_collections/grafana/grafana/.editorconfig create mode 100644 ansible_collections/grafana/grafana/.github/dependabot.yml delete mode 100644 ansible_collections/grafana/grafana/.github/workflows/ci-test.yml create mode 100644 ansible_collections/grafana/grafana/.github/workflows/lint.yaml create mode 100644 ansible_collections/grafana/grafana/.github/workflows/modules-test.yml create mode 100644 ansible_collections/grafana/grafana/.github/workflows/roles-test.yml create mode 100644 ansible_collections/grafana/grafana/.gitignore create mode 100644 ansible_collections/grafana/grafana/.markdownlint.yaml create mode 100644 ansible_collections/grafana/grafana/.shellcheckrc create mode 100644 ansible_collections/grafana/grafana/.textlintrc create mode 100644 ansible_collections/grafana/grafana/.yamllint create mode 100644 ansible_collections/grafana/grafana/CODEOWNERS create mode 100644 ansible_collections/grafana/grafana/Makefile create mode 100644 ansible_collections/grafana/grafana/Pipfile create mode 100644 ansible_collections/grafana/grafana/Pipfile.lock create mode 100644 ansible_collections/grafana/grafana/ansible.cfg create mode 100644 ansible_collections/grafana/grafana/examples/agent-basic-no-options.yaml create mode 100644 ansible_collections/grafana/grafana/examples/agent-send-to-grafana-cloud.yaml create mode 100644 ansible_collections/grafana/grafana/examples/ansible.cfg create mode 100644 ansible_collections/grafana/grafana/examples/monitor-multiple-instances.md create mode 100644 ansible_collections/grafana/grafana/package.json create mode 100644 ansible_collections/grafana/grafana/requirements.txt create mode 100644 ansible_collections/grafana/grafana/requirements.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/README.md create mode 100644 ansible_collections/grafana/grafana/roles/grafana/defaults/main.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/handlers/main.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/meta/main.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/molecule/alternative/converge.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/molecule/alternative/molecule.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/molecule/alternative/tests/test_alternative.py create mode 100644 ansible_collections/grafana/grafana/roles/grafana/molecule/default/converge.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/molecule/default/molecule.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/molecule/default/tests/test_default.py create mode 100644 ansible_collections/grafana/grafana/roles/grafana/tasks/api_keys.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/tasks/configure.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/tasks/dashboards.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/tasks/datasources.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/tasks/install.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/tasks/main.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/tasks/notifications.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/tasks/plugins.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/tasks/preflight.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/templates/grafana.ini.j2 create mode 100644 ansible_collections/grafana/grafana/roles/grafana/templates/ldap.toml.j2 create mode 100644 ansible_collections/grafana/grafana/roles/grafana/templates/tmpfiles.j2 create mode 100644 ansible_collections/grafana/grafana/roles/grafana/test-requirements.txt create mode 100644 ansible_collections/grafana/grafana/roles/grafana/vars/distro/debian.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/vars/distro/redhat.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana/vars/distro/suse.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/defaults/main.yaml delete mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/defaults/main.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/handlers/main.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/meta/main.yaml delete mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/meta/main.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/configure.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/ga-started.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/directories.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/download-install.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/local-install.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/user-group.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/main.yaml delete mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/main.yml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/download.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/install.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/systemd.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/vars.yaml create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/templates/EnvironmentFile.j2 create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/templates/config.yaml.j2 create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/templates/grafana-agent.service.j2 create mode 100644 ansible_collections/grafana/grafana/roles/grafana_agent/vars/main.yaml delete mode 100644 ansible_collections/grafana/grafana/tests/integration/targets/cloud_stack/tasks/main.yml create mode 100644 ansible_collections/grafana/grafana/tests/integration/targets/create_cloud_stack/tasks/main.yml create mode 100644 ansible_collections/grafana/grafana/tests/integration/targets/delete_cloud_stack/tasks/main.yml create mode 100755 ansible_collections/grafana/grafana/tests/integration/targets/molecule-grafana-alternative/runme.sh create mode 100755 ansible_collections/grafana/grafana/tests/integration/targets/molecule-grafana-default/runme.sh create mode 100755 ansible_collections/grafana/grafana/tools/includes/logging.sh create mode 100755 ansible_collections/grafana/grafana/tools/includes/utils.sh create mode 100755 ansible_collections/grafana/grafana/tools/lint-ansible.sh create mode 100755 ansible_collections/grafana/grafana/tools/lint-editorconfig.sh create mode 100755 ansible_collections/grafana/grafana/tools/lint-markdown.sh create mode 100755 ansible_collections/grafana/grafana/tools/lint-shell.sh create mode 100755 ansible_collections/grafana/grafana/tools/lint-text.sh create mode 100755 ansible_collections/grafana/grafana/tools/lint-yaml.sh create mode 100755 ansible_collections/grafana/grafana/tools/setup.sh create mode 100644 ansible_collections/grafana/grafana/yarn.lock (limited to 'ansible_collections/grafana') diff --git a/ansible_collections/grafana/grafana/.ansible-lint b/ansible_collections/grafana/grafana/.ansible-lint new file mode 100644 index 000000000..6dab8332e --- /dev/null +++ b/ansible_collections/grafana/grafana/.ansible-lint @@ -0,0 +1,18 @@ +--- +profile: production + +exclude_paths: + - .cache/ + - .github/ + - examples/ + +parseable: true +verbosity: 1 + +use_default_rules: true + +skip_list: + - '204' # Allow string length greater than 160 chars + - 'no-changed-when' # False positives for running command shells + - 'yaml' # Disable YAML linting since it's done by yamllint + - 'empty-string-compare' # Allow compare to empty string diff --git a/ansible_collections/grafana/grafana/.config/molecule/config.yml b/ansible_collections/grafana/grafana/.config/molecule/config.yml new file mode 100644 index 000000000..6e627cae5 --- /dev/null +++ b/ansible_collections/grafana/grafana/.config/molecule/config.yml @@ -0,0 +1,80 @@ +--- +dependency: + name: galaxy +driver: + name: docker +platforms: + - name: almalinux-8 + image: dokken/almalinux-8 + pre_build_image: true + privileged: true + cgroup_parent: docker.slice + command: /lib/systemd/systemd + - name: almalinux-9 + image: dokken/almalinux-9 + pre_build_image: true + privileged: true + cgroup_parent: docker.slice + command: /lib/systemd/systemd + - name: centos-7 + image: dokken/centos-7 + pre_build_image: true + privileged: true + cgroup_parent: docker.slice + command: /usr/lib/systemd/systemd + - name: centos-stream-8 + image: dokken/centos-stream-8 + pre_build_image: true + privileged: true + cgroup_parent: docker.slice + command: /lib/systemd/systemd + - name: centos-stream-9 + image: dokken/centos-stream-9 + pre_build_image: true + privileged: true + cgroup_parent: docker.slice + command: /lib/systemd/systemd + - name: debian-10 + image: dokken/debian-10 + pre_build_image: true + privileged: true + cgroup_parent: docker.slice + command: /lib/systemd/systemd + - name: debian-11 + image: dokken/debian-11 + pre_build_image: true + privileged: true + cgroup_parent: docker.slice + command: /lib/systemd/systemd + - name: fedora-36 + image: dokken/fedora-36 + pre_build_image: true + privileged: true + cgroup_parent: docker.slice + command: /lib/systemd/systemd + - name: fedora-37 + image: dokken/fedora-37 + pre_build_image: true + privileged: true + cgroup_parent: docker.slice + command: /lib/systemd/systemd + - name: ubuntu-18.04 + image: dokken/ubuntu-18.04 + pre_build_image: true + privileged: true + cgroup_parent: docker.slice + command: /lib/systemd/systemd + - name: ubuntu-20.04 + image: dokken/ubuntu-20.04 + pre_build_image: true + privileged: true + cgroup_parent: docker.slice + command: /lib/systemd/systemd + - name: ubuntu-22.04 + image: dokken/ubuntu-22.04 + pre_build_image: true + privileged: true + cgroup_parent: docker.slice + command: /lib/systemd/systemd +verifier: + name: testinfra diff --git a/ansible_collections/grafana/grafana/.editorconfig b/ansible_collections/grafana/grafana/.editorconfig new file mode 100644 index 000000000..9a7d285db --- /dev/null +++ b/ansible_collections/grafana/grafana/.editorconfig @@ -0,0 +1,42 @@ +# This file is the top-most EditorConfig file +root = true + +# All Files +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +# JSON Files +[*.{json,json5,webmanifest}] +indent_size = 2 + +# YAML Files +[*.{yml,yaml}] +indent_size = 2 + +# Markdown Files +[*.{md,mdx}] +indent_size = 2 +trim_trailing_whitespace = false + +# Web Files +[*.{htm,html,js,jsm,ts,tsx,cjs,cts,ctsx,mjs,mts,mtsx,css,sass,scss,less,pcss,svg,vue}] +indent_size = 2 + +# Bash Files +[*.sh] +indent_size = 2 +end_of_line = lf + +# Makefiles +[{Makefile,**.mk}] +indent_style = tab + +# Python Files +[*.py] +indent_style = space +indent_size = 4 diff --git a/ansible_collections/grafana/grafana/.github/dependabot.yml b/ansible_collections/grafana/grafana/.github/dependabot.yml new file mode 100644 index 000000000..9d866e392 --- /dev/null +++ b/ansible_collections/grafana/grafana/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "pip" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/ansible_collections/grafana/grafana/.github/workflows/ci-test.yml b/ansible_collections/grafana/grafana/.github/workflows/ci-test.yml deleted file mode 100644 index 33f7bbb8e..000000000 --- a/ansible_collections/grafana/grafana/.github/workflows/ci-test.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: CI Tests -on: - push: - branches: - - "main" - pull_request: - schedule: - - cron: '0 6 * * *' -env: - NAMESPACE: grafana - COLLECTION_NAME: grafana - -jobs: - - sanity: - name: Sanity (Ⓐ${{ matrix.ansible }}) - strategy: - matrix: - ansible: - - stable-2.12 - - stable-2.13 - - stable-2.14 - - devel - runs-on: ubuntu-20.04 - steps: - - - name: Check out code - uses: actions/checkout@v3 - with: - path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - - - name: Set up Python - uses: actions/setup-python@v3 - with: - python-version: '3.10' - - - name: Install ansible-base (${{ matrix.ansible }}) - run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - - - name: Run sanity tests - run: ansible-test sanity -v --docker --color --coverage - working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - - integration: - runs-on: ubuntu-20.04 - name: Integration (Ⓐ${{ matrix.ansible }}-py${{ matrix.python }}) - strategy: - fail-fast: true - max-parallel: 1 - matrix: - ansible: - - stable-2.13 - python: - - '3.10' - - steps: - - name: Check out code - uses: actions/checkout@v2 - with: - path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - - - name: create integration_config - working-directory: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}/tests/integration - run: | - cat < integration_config.yml - stack_name: ${{ secrets.ANSIBLE_TEST_STACK_NAME }} - org_name: ${{ secrets.ANSIBLE_TEST_ORG_NAME }} - grafana_cloud_api_key: ${{ secrets.ANSIBLE_TEST_CLOUD_API_KEY }} - grafana_api_key: ${{ secrets.ANSIBLE_TEST_GRAFANA_API_KEY }} - test_stack_name: ${{ secrets.ANSIBLE_TEST_CI_STACK }} - EOF - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python }} - - - name: Install ansible-base (${{ matrix.ansible }}) - run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - - - name: Run integration test - run: ansible-test integration -v --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --coverage --docker - working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} diff --git a/ansible_collections/grafana/grafana/.github/workflows/full-integration-test.yml b/ansible_collections/grafana/grafana/.github/workflows/full-integration-test.yml index 2654a3688..a7fd9c488 100644 --- a/ansible_collections/grafana/grafana/.github/workflows/full-integration-test.yml +++ b/ansible_collections/grafana/grafana/.github/workflows/full-integration-test.yml @@ -1,4 +1,7 @@ +--- name: Full Integration Test + +# yamllint disable-line rule:truthy on: schedule: - cron: '0 0 * * 0' @@ -32,13 +35,13 @@ jobs: exclude: - ansible: stable-2.11 python: '3.10' - + steps: - name: Check out code uses: actions/checkout@v2 with: path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - + - name: create integration_config working-directory: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}/tests/integration run: | @@ -47,8 +50,9 @@ jobs: org_name: ${{ secrets.ANSIBLE_TEST_ORG_NAME }} grafana_cloud_api_key: ${{ secrets.ANSIBLE_TEST_CLOUD_API_KEY }} grafana_api_key: ${{ secrets.ANSIBLE_TEST_GRAFANA_API_KEY }} + test_stack_name: ${{ secrets.ANSIBLE_TEST_CI_STACK }} EOF - + - name: Set up Python uses: actions/setup-python@v2 with: @@ -57,9 +61,9 @@ jobs: - name: Install ansible-base (${{ matrix.ansible }}) run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - - name: Run integration test - run: ansible-test integration -v --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --docker --coverage + - name: Test Modules + run: ansible-test integration -v alert_contact_point alert_notification_policy cloud_api_key cloud_plugin cloud_stack dashboard datasource folder --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --coverage --docker working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - + - name: Cooling Period - run: sleep 1m + run: sleep 3m diff --git a/ansible_collections/grafana/grafana/.github/workflows/lint.yaml b/ansible_collections/grafana/grafana/.github/workflows/lint.yaml new file mode 100644 index 000000000..a53315d28 --- /dev/null +++ b/ansible_collections/grafana/grafana/.github/workflows/lint.yaml @@ -0,0 +1,63 @@ +--- +name: Lint + +# yamllint disable-line rule:truthy +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + lint: + name: Perform Linting + runs-on: ubuntu-latest + steps: + - name: Install shellcheck + run: | + wget -c https://github.com/koalaman/shellcheck/releases/download/v0.9.0/shellcheck-v0.9.0.linux.x86_64.tar.xz -O shellcheck.tar.xz && \ + tar -xvf shellcheck.tar.xz && \ + sudo mv ./shellcheck-v0.9.0/shellcheck /usr/bin/shellcheck && \ + rm -rf shellcheck-v0.9.0 + + - uses: actions/checkout@v3 + + - uses: actions/setup-node@v3 + with: + node-version: 18 + cache: npm + + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: Install pipenv + run: | + python -m pip install --upgrade pipenv wheel + + - name: Install dependencies + run: make install + + - name: Shell Linting + run: make ci-lint-shell + if: success() || failure() + + # - name: Markdown Linting + # run: make ci-lint-markdown + # if: success() || failure() + + # - name: Text Linting + # run: make ci-lint-text + # if: success() || failure() + + - name: Yaml Linting + run: make ci-lint-yaml + if: success() || failure() + + - name: Editorconfig Linting + run: make ci-lint-editorconfig + if: success() || failure() + + - name: Ansible Linting + run: make ci-lint-ansible + if: success() || failure() diff --git a/ansible_collections/grafana/grafana/.github/workflows/modules-test.yml b/ansible_collections/grafana/grafana/.github/workflows/modules-test.yml new file mode 100644 index 000000000..20f789783 --- /dev/null +++ b/ansible_collections/grafana/grafana/.github/workflows/modules-test.yml @@ -0,0 +1,98 @@ +--- +name: Modules Test + +# yamllint disable-line rule:truthy +on: + push: + branches: + - "main" + pull_request: + schedule: + - cron: '0 6 * * *' +env: + NAMESPACE: grafana + COLLECTION_NAME: grafana + +jobs: + + sanity: + name: Sanity (Ⓐ${{ matrix.ansible }}) + strategy: + matrix: + ansible: + - stable-2.12 + - stable-2.13 + - stable-2.14 + - devel + runs-on: ubuntu-20.04 + steps: + + - name: Check out code + uses: actions/checkout@v3 + with: + path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.10' + + - name: Install ansible-base (${{ matrix.ansible }}) + run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check + + - name: Run sanity tests + run: ansible-test sanity -v --docker --color --coverage + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + integration: + runs-on: ubuntu-20.04 + name: Integration (Ⓐ${{ matrix.ansible }}-py${{ matrix.python }}) + strategy: + fail-fast: true + max-parallel: 1 + matrix: + ansible: + - stable-2.13 + python: + - '3.10' + + steps: + - name: Check out code + uses: actions/checkout@v2 + with: + path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + - name: create integration_config + working-directory: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}/tests/integration + run: | + cat < integration_config.yml + org_name: ${{ secrets.ANSIBLE_TEST_ORG_NAME }} + grafana_cloud_api_key: ${{ secrets.ANSIBLE_TEST_CLOUD_API_KEY }} + grafana_api_key: ${{ secrets.ANSIBLE_TEST_GRAFANA_API_KEY }} + grafana_url: ${{ secrets.ANSIBLE_GRAFANA_URL }} + test_stack_name: ${{ secrets.ANSIBLE_TEST_CI_STACK }} + EOF + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python }} + + - name: Install ansible-base (${{ matrix.ansible }}) + run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check + + - name: Install Requests + run: pip install requests + + - name: Create Test Stack + run: ansible-test integration -v create_cloud_stack --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --coverage --docker + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + - name: Test Modules + run: ansible-test integration -v alert_contact_point alert_notification_policy cloud_api_key cloud_plugin dashboard datasource folder --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --coverage --docker + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + - name: Delete Test Stack + if: success() || failure() + run: ansible-test integration -v delete_cloud_stack --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --coverage --docker + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} diff --git a/ansible_collections/grafana/grafana/.github/workflows/release.yml b/ansible_collections/grafana/grafana/.github/workflows/release.yml index 03d012cfe..88528c92a 100644 --- a/ansible_collections/grafana/grafana/.github/workflows/release.yml +++ b/ansible_collections/grafana/grafana/.github/workflows/release.yml @@ -1,4 +1,7 @@ +--- name: GitHub Release + +# yamllint disable-line rule:truthy on: workflow_dispatch: inputs: @@ -34,11 +37,11 @@ jobs: - name: Install ansible-base (${{ matrix.ansible }}) run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - + - name: Run sanity tests run: ansible-test sanity -v --docker --color --coverage working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - + integration: runs-on: ubuntu-20.04 name: Integration (Ⓐ${{ matrix.ansible }}-py${{ matrix.python }}) @@ -50,23 +53,24 @@ jobs: - stable-2.13 python: - '3.10' - + steps: - name: Check out code uses: actions/checkout@v2 with: path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - + - name: create integration_config working-directory: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}/tests/integration run: | cat < integration_config.yml - stack_name: ${{ secrets.ANSIBLE_TEST_STACK_NAME }} org_name: ${{ secrets.ANSIBLE_TEST_ORG_NAME }} grafana_cloud_api_key: ${{ secrets.ANSIBLE_TEST_CLOUD_API_KEY }} grafana_api_key: ${{ secrets.ANSIBLE_TEST_GRAFANA_API_KEY }} + grafana_url: ${{ secrets.ANSIBLE_GRAFANA_URL }} + test_stack_name: ${{ secrets.ANSIBLE_TEST_CI_STACK }} EOF - + - name: Set up Python uses: actions/setup-python@v2 with: @@ -75,14 +79,26 @@ jobs: - name: Install ansible-base (${{ matrix.ansible }}) run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - - name: Run integration test - run: ansible-test integration -v --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --docker --coverage + - name: Install Requests + run: pip install requests + + - name: Create Test Stack + run: ansible-test integration -v create_cloud_stack --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --coverage --docker working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - + + - name: Test Modules + run: ansible-test integration -v alert_contact_point alert_notification_policy cloud_api_key cloud_plugin dashboard datasource folder --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --coverage --docker + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + - name: Delete Test Stack + if: success() || failure() + run: ansible-test integration -v delete_cloud_stack --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --coverage --docker + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + release: name: Create GitHub Release runs-on: ubuntu-latest - needs: [sanity] + needs: [sanity, integration] steps: - name: Checkout uses: actions/checkout@v3 @@ -100,5 +116,5 @@ jobs: - name: Release uses: softprops/action-gh-release@v1 - with: + with: tag_name: ${{ github.event.inputs.version }} diff --git a/ansible_collections/grafana/grafana/.github/workflows/roles-test.yml b/ansible_collections/grafana/grafana/.github/workflows/roles-test.yml new file mode 100644 index 000000000..959550546 --- /dev/null +++ b/ansible_collections/grafana/grafana/.github/workflows/roles-test.yml @@ -0,0 +1,90 @@ +--- +name: Roles Test + +# yamllint disable-line rule:truthy +on: + push: + branches: + - "main" + pull_request: + schedule: + - cron: '0 6 * * *' +env: + NAMESPACE: grafana + COLLECTION_NAME: grafana + +jobs: + + sanity: + name: Sanity (Ⓐ${{ matrix.ansible }}) + strategy: + matrix: + ansible: + - stable-2.12 + - stable-2.13 + - stable-2.14 + - devel + runs-on: ubuntu-20.04 + steps: + + - name: Check out code + uses: actions/checkout@v3 + with: + path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.10' + + - name: Install ansible-base (${{ matrix.ansible }}) + run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check + + - name: Run sanity tests + run: ansible-test sanity -v --docker --color --coverage + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + integration: + runs-on: ubuntu-20.04 + name: Integration (Ⓐ${{ matrix.ansible }}-py${{ matrix.python }}) + strategy: + fail-fast: true + max-parallel: 1 + matrix: + ansible: + - stable-2.13 + python: + - '3.10' + + steps: + - name: Check out code + uses: actions/checkout@v2 + with: + path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + + - name: create integration_config + working-directory: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}/tests/integration + run: | + cat < integration_config.yml + stack_name: ${{ secrets.ANSIBLE_TEST_STACK_NAME }} + org_name: ${{ secrets.ANSIBLE_TEST_ORG_NAME }} + grafana_cloud_api_key: ${{ secrets.ANSIBLE_TEST_CLOUD_API_KEY }} + grafana_api_key: ${{ secrets.ANSIBLE_TEST_GRAFANA_API_KEY }} + grafana_url: ${{ secrets.ANSIBLE_GRAFANA_URL }} + test_stack_name: ${{ secrets.ANSIBLE_TEST_CI_STACK }} + EOF + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python }} + + - name: Install ansible-base (${{ matrix.ansible }}) + run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check + + - name: Install Requests + run: pip install requests + + - name: Test Roles + run: ansible-test integration -v molecule-grafana-alternative molecule-grafana-default --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --coverage --docker + working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} diff --git a/ansible_collections/grafana/grafana/.gitignore b/ansible_collections/grafana/grafana/.gitignore new file mode 100644 index 000000000..fb34ac8df --- /dev/null +++ b/ansible_collections/grafana/grafana/.gitignore @@ -0,0 +1,236 @@ +# Project +# --------------------------------------------------- +*.pyc +.vscode +.idea +hosts +*.log + +# MacOS +# --------------------------------------------------- +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +# Windows +# --------------------------------------------------- +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + + +# MS Office +# --------------------------------------------------- +*.tmp + +# Word temporary +~$*.doc* + +# Word Auto Backup File +Backup of *.doc* + +# Excel temporary +~$*.xls* + +# Excel Backup File +*.xlk + +# PowerPoint temporary +~$*.ppt* + +# Visio autosave temporary files +*.~vsd* + + +# VS Code +# --------------------------------------------------- +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ +*.app +.snapshots/* + + +# NodeJS +# --------------------------------------------------- +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* diff --git a/ansible_collections/grafana/grafana/.markdownlint.yaml b/ansible_collections/grafana/grafana/.markdownlint.yaml new file mode 100644 index 000000000..f12a082d8 --- /dev/null +++ b/ansible_collections/grafana/grafana/.markdownlint.yaml @@ -0,0 +1,261 @@ +--- +# Example markdownlint YAML configuration with all properties set to their default value + +# Default state for all rules +default: true + +# Path to configuration file to extend +extends: null + +# MD001/heading-increment/header-increment - Heading levels should only increment by one level at a time +MD001: true + +# MD002/first-heading-h1/first-header-h1 - First heading should be a top-level heading +MD002: + # Heading level + level: 1 + +# MD003/heading-style/header-style - Heading style +MD003: + # Heading style + style: "consistent" + +# MD004/ul-style - Unordered list style +MD004: + # List style + style: "consistent" + +# MD005/list-indent - Inconsistent indentation for list items at the same level +MD005: true + +# MD006/ul-start-left - Consider starting bulleted lists at the beginning of the line +MD006: true + +# MD007/ul-indent - Unordered list indentation +MD007: + # Spaces for indent + indent: 2 + # Whether to indent the first level of the list + start_indented: false + # Spaces for first level indent (when start_indented is set) + start_indent: 2 + +# MD009/no-trailing-spaces - Trailing spaces +MD009: + # Spaces for line break + br_spaces: 2 + # Allow spaces for empty lines in list items + list_item_empty_lines: false + # Include unnecessary breaks + strict: false + +# MD010/no-hard-tabs - Hard tabs +MD010: + # Include code blocks + code_blocks: true + # Fenced code languages to ignore + ignore_code_languages: [] + # Number of spaces for each hard tab + spaces_per_tab: 2 + +# MD011/no-reversed-links - Reversed link syntax +MD011: true + +# MD012/no-multiple-blanks - Multiple consecutive blank lines +MD012: + # Consecutive blank lines + maximum: 1 + +# MD013/line-length - Line length +MD013: + # Number of characters + line_length: 150 + # Number of characters for headings + heading_line_length: 80 + # Number of characters for code blocks + code_block_line_length: 100 + # Include code blocks + code_blocks: true + # Include tables + tables: false + # Include headings + headings: true + # Include headings + headers: true + # Strict length checking + strict: false + # Stern length checking + stern: false + +# MD014/commands-show-output - Dollar signs used before commands without showing output +MD014: false + +# MD018/no-missing-space-atx - No space after hash on atx style heading +MD018: true + +# MD019/no-multiple-space-atx - Multiple spaces after hash on atx style heading +MD019: true + +# MD020/no-missing-space-closed-atx - No space inside hashes on closed atx style heading +MD020: true + +# MD021/no-multiple-space-closed-atx - Multiple spaces inside hashes on closed atx style heading +MD021: true + +# MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines +MD022: + # Blank lines above heading + lines_above: 1 + # Blank lines below heading + lines_below: 1 + +# MD023/heading-start-left/header-start-left - Headings must start at the beginning of the line +MD023: true + +# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content +MD024: false + +# MD025/single-title/single-h1 - Multiple top-level headings in the same document +MD025: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD026/no-trailing-punctuation - Trailing punctuation in heading +MD026: + # Punctuation characters not allowed at end of headings + punctuation: ".,;:!。,;:!" + +# MD027/no-multiple-space-blockquote - Multiple spaces after blockquote symbol +MD027: true + +# MD028/no-blanks-blockquote - Blank line inside blockquote +MD028: true + +# MD029/ol-prefix - Ordered list item prefix +MD029: + # List style + style: "one_or_ordered" + +# MD030/list-marker-space - Spaces after list markers +MD030: + # Spaces for single-line unordered list items + ul_single: 3 + # Spaces for single-line ordered list items + ol_single: 2 + # Spaces for multi-line unordered list items + ul_multi: 3 + # Spaces for multi-line ordered list items + ol_multi: 2 + +# MD031/blanks-around-fences - Fenced code blocks should be surrounded by blank lines +MD031: + # Include list items + list_items: true + +# MD032/blanks-around-lists - Lists should be surrounded by blank lines +MD032: true + +# MD033/no-inline-html - Inline HTML +MD033: + # Allowed elements + allowed_elements: + - div + - br + - hr + +# MD034/no-bare-urls - Bare URL used +MD034: true + +# MD035/hr-style - Horizontal rule style +MD035: + # Horizontal rule style + style: "consistent" + +# MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading +MD036: false + +# MD037/no-space-in-emphasis - Spaces inside emphasis markers +MD037: true + +# MD038/no-space-in-code - Spaces inside code span elements +MD038: true + +# MD039/no-space-in-links - Spaces inside link text +MD039: true + +# MD040/fenced-code-language - Fenced code blocks should have a language specified +MD040: + # List of languages + allowed_languages: [] + # Require language only + language_only: false + +# MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading +MD041: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD042/no-empty-links - No empty links +MD042: true + +# MD043/required-headings/required-headers - Required heading structure +MD043: + # List of headings + headings: + - "*" + # List of headings + headers: [] + # Match case of headings + match_case: false + +# MD044/proper-names - Proper names should have the correct capitalization +MD044: + # List of proper names + names: [] + # Include code blocks + code_blocks: true + # Include HTML elements + html_elements: true + +# MD045/no-alt-text - Images should have alternate text (alt text) +MD045: true + +# MD046/code-block-style - Code block style +MD046: + # Block style + style: "consistent" + +# MD047/single-trailing-newline - Files should end with a single newline character +MD047: true + +# MD048/code-fence-style - Code fence style +MD048: + # Code fence style + style: "consistent" + +# MD049/emphasis-style - Emphasis style should be consistent +MD049: + # Emphasis style should be consistent + style: "consistent" + +# MD050/strong-style - Strong style should be consistent +MD050: + # Strong style should be consistent + style: "consistent" + +# MD051/link-fragments - Link fragments should be valid +MD051: false + +# MD052/reference-links-images - Reference links and images should use a label that is defined +MD052: true + +# MD053/link-image-reference-definitions - Link and image reference definitions should be needed +MD053: + # Ignored definitions + ignored_definitions: [ + "//" + ] diff --git a/ansible_collections/grafana/grafana/.shellcheckrc b/ansible_collections/grafana/grafana/.shellcheckrc new file mode 100644 index 000000000..9eac5ba59 --- /dev/null +++ b/ansible_collections/grafana/grafana/.shellcheckrc @@ -0,0 +1,7 @@ +# Allow opening any 'source'd file, even if not specified as input +external-sources=true + +# some files are sourced which can make some areas appear unreachable +disable=SC2317 +disable=SC2250 +disable=SC2312 diff --git a/ansible_collections/grafana/grafana/.textlintrc b/ansible_collections/grafana/grafana/.textlintrc new file mode 100644 index 000000000..1ea8e9c70 --- /dev/null +++ b/ansible_collections/grafana/grafana/.textlintrc @@ -0,0 +1,187 @@ +{ + "rules": { + "common-misspellings": true, + "no-todo": true, + "terminology": { + "defaultTerms": false, + "terms": [ + "Grafana", + ["GrafanaLabs", "Grafana Labs"], + ["GrafanaCloud", "Grafana Cloud"], + "Mimir", + "Loki", + "Phlare", + "Tempo", + "Faro", + "Raintank", + "Prometheus", + "PromQL", + ["(E|e)xamplars", "$1xemplars"], + ["(D|d)atasource", "$1ata source"], + "CData", + "Google", + "Amazon", + "RedHat", + "Azure", + "Airbnb", + "Android", + "AppleScript", + "AppVeyor", + "AVA", + "BrowserStack", + "Browsersync", + "Codecov", + "CodePen", + "CodeSandbox", + "DefinitelyTyped", + "EditorConfig", + "ESLint", + "GitHub", + "GraphQL", + "iOS", + "JavaScript", + "JetBrains", + "jQuery", + "LinkedIn", + "Lodash", + "MacBook", + "Markdown", + "OpenType", + "PayPal", + "PhpStorm", + "RubyMine", + "Sass", + "SemVer", + "TypeScript", + "UglifyJS", + "Wasm", + "WebAssembly", + "WebStorm", + "WordPress", + "YouTube", + ["Common[ .]js", "CommonJS"], + ["JSDocs?", "JSDoc"], + ["Nodejs", "Node.js"], + ["React[ .]js", "React"], + ["SauceLabs", "Sauce Labs"], + ["StackOverflow", "Stack Overflow"], + ["styled ?components", "styled-components"], + ["HTTP[ /]2(?:\\.0)?", "HTTP/2"], + ["OS X", "macOS"], + ["Mac ?OS", "macOS"], + ["a npm", "an npm"], + "ECMAScript", + ["ES2015", "ES6"], + ["ES7", "ES2016"], + "3D", + ["3-D", "3D"], + "Ajax", + "API", + ["API[']?s", "APIs"], + "CSS", + "GIF", + " HTML ", + "HTTPS", + "IoT", + "I/O", + ["I-O", "I/O"], + "JPEG", + "MIME", + "OK", + "PaaS", + " PDF ", + "PNG", + "SaaS", + "URL", + ["URL[']?s", "URLs"], + ["an URL", "a URL"], + ["wi[- ]?fi", "Wi-Fi"], + "McKenzie", + "McConnell", + [" id", " ID"], + ["id[']?s", "IDs"], + ["backwards compatible", "backward compatible"], + ["build system(s?)", "build tool$1"], + ["CLI tool(s?)", "command-line tool$1"], + ["he or she", "they"], + ["he/she", "they"], + ["\\(s\\)he", "they"], + ["repo\\b", "repository"], + ["smartphone(s?)", "mobile phone$1"], + ["web[- ]?site(s?)", "site$1"], + ["auto[- ]complete", "autocomplete"], + ["auto[- ]format", "autoformat"], + ["auto[- ]fix", "autofix"], + ["auto[- ]fixing", "autofixing"], + ["back[- ]end(\\w*)", "backend$1"], + ["bug[- ]fix(es?)", "bugfix$1"], + ["change[- ]log(s?)", "changelog$1"], + ["check[- ]box(es?)", "checkbox$1"], + ["code[- ]base(es?)", "codebase$1"], + ["co[- ]locate(d?)", "colocate$1"], + ["end[- ]point(s?)", "endpoint$1"], + ["e[- ]mail(s?)", "email$1"], + ["file[- ]name(s?)", "filename$1"], + ["front[- ]end(\\w*)", "frontend$1"], + ["hack[- ]a[- ]thon(s?)", "hackathon$1"], + ["host[- ]name(s?)", "hostname$1"], + ["hot[- ]key(s?)", "hotkey$1"], + ["life[- ]cycle", "lifecycle"], + ["life[- ]stream(s?)", "lifestream$1"], + ["lock[- ]file(s?)", "lockfile$1"], + ["mark-up", "markup"], + ["meta[- ]data", "metadata"], + ["micro[- ]service(s?)", "microservice$1"], + ["name[- ]space(s?)", "namespace$1"], + ["pre[- ]condition(s?)", "precondition$1"], + ["pre[- ]defined", "predefined"], + ["pre[- ]release(s?)", "prerelease$1"], + ["re[- ]write", "rewrite"], + ["run[- ]time", "runtime"], + ["screen[- ]shot(s?)", "screenshot$1"], + ["screen[- ]?snap(s?)", "screenshot$1"], + ["sub[- ]class((?:es|ing)?)", "subclass$1"], + ["sub[- ]tree(s?)", "subtree$1"], + ["time[- ]stamp(s?)", "timestamp$1"], + ["touch[- ]screen(s?)", "touchscreen$1"], + ["user[- ]name(s?)", "username$1"], + ["walk[- ]through", "walkthrough"], + ["white[- ]space", "whitespace"], + ["wild[- ]card(s?)", "wildcard$1"], + ["css-?in-?js", "CSS in JS"], + ["code-?review(s?)", "code review$1"], + ["code-?splitting", "code splitting"], + ["end-?user(s?)", "end user$1"], + ["file-?type(s?)", "file type$1"], + ["micro-?frontend(s?)", "micro frontend$1"], + ["open-?source(ed?)", "open source$1"], + ["regexp?(s?)", "regular expression$1"], + ["style-?guide(s?)", "style guide$1"], + ["tree-?shaking", "tree shaking"], + ["source-?map(s?)", "source map$1"], + ["style-?sheet(s?)", "style sheet$1"], + ["user-?base", "user base"], + ["web-?page(s?)", "web page$1"], + ["built ?in", "built-in"], + ["client ?side", "client-side"], + ["command ?line", "command-line"], + ["end ?to ?end", "end-to-end"], + ["error ?prone", "error-prone"], + ["higher ?order", "higher-order"], + ["key[/ ]?value", "key-value"], + ["server ?side", "server-side"], + ["two ?steps?", "two-step"], + ["2 ?steps?", "two-step"], + ["(\\w+[^.?!]\\)? )base64", "$1base64"], + ["(\\w+[^.?!]\\)? )internet", "$1internet"], + ["(\\w+[^.?!]\\)? )stylelint", "$1stylelint"], + ["(\\w+[^.?!]\\)? )webpack", "$1webpack"], + ["(\\w+[^.?!]\\)? )npm", "$1npm"], + ["environemnt(s?)", "environment$1"], + ["pacakge(s?)", "package$1"], + ["tilda", "tilde"], + ["falsey", "falsy"] + ] + } + } +} diff --git a/ansible_collections/grafana/grafana/.yamllint b/ansible_collections/grafana/grafana/.yamllint new file mode 100644 index 000000000..53231c45a --- /dev/null +++ b/ansible_collections/grafana/grafana/.yamllint @@ -0,0 +1,15 @@ +--- +yaml-files: + - "*.yaml" + - "*.yml" + - ".yamllint" + +ignore: + - node_modules + +extends: default + +rules: + line-length: + max: 150 + level: warning diff --git a/ansible_collections/grafana/grafana/CHANGELOG.rst b/ansible_collections/grafana/grafana/CHANGELOG.rst index e2e5dc7bf..eabc0c278 100644 --- a/ansible_collections/grafana/grafana/CHANGELOG.rst +++ b/ansible_collections/grafana/grafana/CHANGELOG.rst @@ -5,6 +5,280 @@ Grafana.Grafana Release Notes .. contents:: Topics +v2.2.5 +====== + +Release Summary +--------------- + +Grafana and Agent Role bug fixes and security updates + +Minor Changes +------------- + +- Add 'run_once' to download&unzip tasks by @v-zhuravlev in https://github.com/grafana/grafana-ansible-collection/pull/136 +- Adding `oauth_allow_insecure_email_lookup` to fix oauth user sync error by @hypery2k in https://github.com/grafana/grafana-ansible-collection/pull/132 +- Bump ansible-core from 2.15.4 to 2.15.8 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/137 +- Bump ansible-lint from 6.13.1 to 6.14.3 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/139 +- Bump ansible-lint from 6.14.3 to 6.22.2 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/142 +- Bump ansible-lint from 6.22.2 to 24.2.0 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/150 +- Bump jinja2 from 3.1.2 to 3.1.3 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/129 +- Bump pylint from 2.16.2 to 3.0.3 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/141 +- Bump yamllint from 1.29.0 to 1.33.0 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/140 +- Bump yamllint from 1.29.0 to 1.33.0 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/143 +- Bump yamllint from 1.33.0 to 1.34.0 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/151 +- Change handler to systemd by @v-zhuravlev in https://github.com/grafana/grafana-ansible-collection/pull/135 +- Fix links in grafana_agent/defaults/main.yaml by @PabloCastellano in https://github.com/grafana/grafana-ansible-collection/pull/134 +- Topic/grafana agent idempotency by @ohdearaugustin in https://github.com/grafana/grafana-ansible-collection/pull/147 + +v2.2.4 +====== + +Release Summary +--------------- + +Grafana and Agent Role bug fixes and security updates + +Minor Changes +------------- + +- Bump cryptography from 41.0.4 to 41.0.6 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/126 +- Drop curl check by @v-zhuravlev in https://github.com/grafana/grafana-ansible-collection/pull/120 +- Fix check mode for grafana role by @Boschung-Mecatronic-AG-Infrastructure in https://github.com/grafana/grafana-ansible-collection/pull/125 +- Fix check mode in Grafana Agent by @AmandaCameron in https://github.com/grafana/grafana-ansible-collection/pull/124 +- Update tags in README by @ishanjainn in https://github.com/grafana/grafana-ansible-collection/pull/121 + +v2.2.3 +====== + +Release Summary +--------------- + +Remove dependency on local-fs.target from Grafana Agent role + +Minor Changes +------------- + +- Remove dependency on local-fs.target from Grafana Agent role + +v2.2.2 +====== + +Release Summary +--------------- + +Grafana Role bug fixes and security updates + +Minor Changes +------------- + +- Bump cryptography from 41.0.3 to 41.0.4 +- Create missing notification directory in Grafana Role +- Remove check_mode from create local directory task in Grafana Role + +v2.2.1 +====== + +Release Summary +--------------- + +Allow alert resource provisioning in Grafana Role + +Minor Changes +------------- + +- Allow alert resource provisioning in Grafana Role + +v2.2.0 +====== + +Release Summary +--------------- + +Grafana Agent Role Updates + +Minor Changes +------------- + +- Use 'ansible_system' env variable to detect os typ in Grafana Agent Role +- hange grafana Agent Wal and Positions Directory in Grafana Agent Role + +v2.1.9 +====== + +Release Summary +--------------- + +Security Updates and Grafana Agent Version failure fixes + +Minor Changes +------------- + +- Add check for Curl and failure step if Agent Version is not retrieved +- Bump cryptography from 39.0.2 to 41.0.3 +- Bump semver from 5.7.1 to 5.7.2 +- Bump word-wrap from 1.2.3 to 1.2.5 +- Create local dashboard directory in check mode +- Update CI Testing +- Update Cloud Stack Module failures + +v2.1.8 +====== + +Release Summary +--------------- + +Fix grafana dashboard import in Grafana Role + +Minor Changes +------------- + +- Fix grafana dashboard import in Grafana Role + +v2.1.7 +====== + +Release Summary +--------------- + +YAML Fixes + +Minor Changes +------------- + +- YAML Fixes + +v2.1.6 +====== + +Release Summary +--------------- + +Grafana and Grafana Agent role updates + +Minor Changes +------------- + +- Add overrides.conf with CAP_NET_BIND_SERVICE for grafana-server unit +- Fix Grafana Dashboard Import for Grafana Role +- Make grafana_agent Idempotent +- Provisioning errors in YAML +- Use new standard to configure Grafana APT source for Grafana Role + +v2.1.5 +====== + +Release Summary +--------------- + +Update Grafana Agent Download varibale and ZIP file + +Minor Changes +------------- + +- Add Grafana Agent Version and CPU Arch to Downloaded ZIP in Grafana Agent Role +- Move _grafana_agent_base_download_url from /vars to /defaults in Grafana Agent Role + +v2.1.4 +====== + +Release Summary +--------------- + +Update Datasource Tests and minor fixes + +Minor Changes +------------- + +- Datasource test updates and minor fixes + +v2.1.3 +====== + +Release Summary +--------------- + +Update modules to fix failing Sanity Tests + +Minor Changes +------------- + +- indentation and Lint fixes to modules + +v2.1.2 +====== + +Release Summary +--------------- + +Idempotency Updates and minor api_url fixes + +Minor Changes +------------- + +- Fix Deleting datasources +- Fix alert_notification_policy failing on fresh instance +- Making Deleting folders idempotent +- Remove trailing slash automatically from grafana_url + +v2.1.1 +====== + +Release Summary +--------------- + +Update Download tasks in Grafana Agent Role + +Minor Changes +------------- + +- Update Download tasks in Grafana Agent Role + +v2.1.0 +====== + +Release Summary +--------------- + +Add Grafana Server role and plugins support on-prem Grafana + +Major Changes +------------- + +- Addition of Grafana Server role by @gardar +- Configurable agent user groups by @NormanJS +- Grafana Plugins support on-prem Grafana installation by @ishanjainn +- Updated Service for flow mode by @bentonam + +Minor Changes +------------- + +- Ability to configure date format in grafana server role by @RomainMou +- Avoid using shell for fetching latest version in Grafana Agent Role by @gardar +- Fix for invalid yaml with datasources list enclosed in quotes by @elkozmon +- Remove agent installation custom check by @VLZZZ +- Remove explicit user creation check by @v-zhuravlev + +v2.0.0 +====== + +Release Summary +--------------- + +Updated Grafana Agent Role + +Major Changes +------------- + +- Added Lint support +- Configs for server, metrics, logs, traces, and integrations +- Installation of the latest version +- Local installations when internet connection is not allowed +- Only download binary to controller once instead of hosts +- Skip install if the agent is already installed and the version is the same as the requested version +- Support for Grafana Agent Flow +- Validation of variables + v1.1.1 ====== @@ -74,8 +348,8 @@ Minor Changes ------------- - Add a fail method to modules source code if `requests` library is not present -- Fixed markup for arg option in Documenation -- Updated Documenation with `notes` to specify if the check_mode feature is supported by modules +- Fixed markup for arg option in Documentation +- Updated Documentation with `notes` to specify if the check_mode feature is supported by modules - removed `supports_check_mode=True` from source code of modules v1.0.2 diff --git a/ansible_collections/grafana/grafana/CODEOWNERS b/ansible_collections/grafana/grafana/CODEOWNERS new file mode 100644 index 000000000..654eb1a6d --- /dev/null +++ b/ansible_collections/grafana/grafana/CODEOWNERS @@ -0,0 +1,3 @@ +./ @ishanjainn +/roles/grafana @gardar @ishanjainn +/roles/grafana_agent @ishanjainn @v-zhuravlev diff --git a/ansible_collections/grafana/grafana/FILES.json b/ansible_collections/grafana/grafana/FILES.json index 149552305..caf8f3754 100644 --- a/ansible_collections/grafana/grafana/FILES.json +++ b/ansible_collections/grafana/grafana/FILES.json @@ -7,6 +7,111 @@ "chksum_sha256": null, "format": 1 }, + { + "name": ".config", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": ".config/molecule", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": ".config/molecule/config.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ee4a1988dea005400d660348502eda25f24fa1c76cf64f59df537b56e72fb58f", + "format": 1 + }, + { + "name": "tools", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tools/setup.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "56b5525e62563c65e6b5b71f27c797d60c1561e3b66578f999c65642f4ec9049", + "format": 1 + }, + { + "name": "tools/lint-yaml.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "51c10eabc5c1360649fc5cab528151135f13d2bbc97cbe907d0e939d6e979e03", + "format": 1 + }, + { + "name": "tools/includes", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tools/includes/utils.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "16a2ebce5931f01510c8e0d7597b632d017a0f10154a83f42d538926913e6eb5", + "format": 1 + }, + { + "name": "tools/includes/logging.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e90aa1f7b29d85263926e228f4321fa31304448f6ce2ff8d48a0e461d076474b", + "format": 1 + }, + { + "name": "tools/lint-shell.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2d969bd175bfdf137539a5f4d97cfc2644dd5c81c677e2c40a40082af9333e36", + "format": 1 + }, + { + "name": "tools/lint-text.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0c01a1e5d52ba8a65e4417d641d1958cfe129112562cb74e11131f8846e6db95", + "format": 1 + }, + { + "name": "tools/lint-ansible.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "87867490595fd8cb5fcd09337f90c8b9135dce7864c0af10c72960081ca0981d", + "format": 1 + }, + { + "name": "tools/lint-markdown.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6f58c8dfd68ddf75eea250ea0f44ad9e9b567deeedacc70ea357f2cd4d92037c", + "format": 1 + }, + { + "name": "tools/lint-editorconfig.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4c438197ed79286cc7ea91cebcbeaaa53ccd5a0b3f04dc66e38c998ebccad271", + "format": 1 + }, + { + "name": ".textlintrc", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "89110cd16e278a39577eae8098d6dd2f4d6ea094b164163e012e31d021ea301e", + "format": 1 + }, { "name": "LICENSE", "ftype": "file", @@ -14,6 +119,20 @@ "chksum_sha256": "8b1ba204bb69a0ade2bfcf65ef294a920f6bb361b317dba43c7ef29d96332b9b", "format": 1 }, + { + "name": "requirements.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "04fac92121706aa4e4940bb95d9fc7f508b729dadcd46afe13f54ec59a32e6c8", + "format": 1 + }, + { + "name": ".shellcheckrc", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "60a0a1e54cc805233096790628fd1ff4b629bf389eeef72d8194c331e7ae1912", + "format": 1 + }, { "name": "plugins", "ftype": "dir", @@ -32,21 +151,21 @@ "name": "plugins/modules/cloud_api_key.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ad92af34ba14124db79243297d55d40f7f98655ec838ea1aa2f1b2fc4af11dcd", + "chksum_sha256": "ad31e2ec04741910e6447d24e8b30b5e29e206651345cb6041cbe40c37033cc7", "format": 1 }, { "name": "plugins/modules/folder.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c7072d564f6a9afd16dd668e07010c87b58791e94b511fe6f94ea55befa9338a", + "chksum_sha256": "44a8ab0965650f4e6faeab4f123c37f40dde8352f5d833144928da374f060962", "format": 1 }, { "name": "plugins/modules/alert_contact_point.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a000ddc28c98669934b5d30f9f08be04c07b14f34bec82a3845de90c19b4d8bd", + "chksum_sha256": "daddbe225bee6a3d20d1877ab9de62d7486a5bd42fcc8d4a76f5a5980c25e33d", "format": 1 }, { @@ -60,28 +179,49 @@ "name": "plugins/modules/datasource.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7d6bc50da5bbf6c6d140ff1729c18663a42cc9e6224d831615d727f493f83598", + "chksum_sha256": "ff0da1a8d35ff138650b263287d584932620acf7439b4c0411dfce79051c70b2", "format": 1 }, { "name": "plugins/modules/dashboard.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "98acf3a7df9d574b2fd8d8e649472786ea4c2885924cbcb0e6862d8c4dc45e0e", + "chksum_sha256": "08f0fb71defb51b4b96d56b413c7c16343f251679e4ed82d983c12b2215bdeb9", "format": 1 }, { "name": "plugins/modules/cloud_plugin.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "880d925213311ae4b699df702e848b5a5ae57c27ebd3280d68908848f60558d0", + "chksum_sha256": "34d3f84453ad0517b14a96720e2f644f5b3aaf7f8b094b83cc1bdf96e6715c50", "format": 1 }, { "name": "plugins/modules/alert_notification_policy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "85b9f18d00b1e7cacb77e46c67cfe8a876e81184e396397dbf636d9170ebfcae", + "chksum_sha256": "87b4dcb32818a17642e6a8b268f0a294b78b6853cfac0b4446be995ed26ce44a", + "format": 1 + }, + { + "name": "Makefile", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8be8db2081029f79bc49bca1f6d8f71a5be2ce62b8aa2e5d7c6782c60db284a4", + "format": 1 + }, + { + "name": "CODEOWNERS", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "bb2590977547e3e484039e55ec54510f37ecfaaa116e84d0389745c40411b53c", + "format": 1 + }, + { + "name": ".yamllint", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8a17bf0fc69dcfd57f1c2f0ab83dd0f276d7bb29edfbf6b7433f201f6abbeece", "format": 1 }, { @@ -112,6 +252,27 @@ "chksum_sha256": null, "format": 1 }, + { + "name": "tests/integration/targets/create_cloud_stack", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/create_cloud_stack/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/create_cloud_stack/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1f7c98fab7394b31039b9df11a55837b58730bf54d45f9d6e65998340189e64a", + "format": 1 + }, { "name": "tests/integration/targets/datasource", "ftype": "dir", @@ -130,70 +291,70 @@ "name": "tests/integration/targets/datasource/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b342deafb0fb490680a798dfc42fa4bf4ba3b8188c9a4aac7ad397f42ad09ead", + "chksum_sha256": "3e19bb584c92e420fa31a417b79fe59162dcb5f9ee10c89ae8854e101a5b4cb0", "format": 1 }, { - "name": "tests/integration/targets/alert_contact_point", + "name": "tests/integration/targets/delete_cloud_stack", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/alert_contact_point/tasks", + "name": "tests/integration/targets/delete_cloud_stack/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/alert_contact_point/tasks/main.yml", + "name": "tests/integration/targets/delete_cloud_stack/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5ea8a53327bfcac36da1b74cf3d96c1ab00a9dfaada7f041385ccb50b37dfd23", + "chksum_sha256": "5d44026e2c68a4714eb678ae9a40478db8576cdf1969d689bf5b00d9dc7b147b", "format": 1 }, { - "name": "tests/integration/targets/folder", + "name": "tests/integration/targets/alert_contact_point", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/folder/tasks", + "name": "tests/integration/targets/alert_contact_point/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/folder/tasks/main.yml", + "name": "tests/integration/targets/alert_contact_point/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "78b2f1a855ed12cdd7baff990fc4e54399f41c4af2da0de6e74737e823ad4e3a", + "chksum_sha256": "f682124f5425fbd4ff86697d9834436c874f85e03abac301302f691841b49adc", "format": 1 }, { - "name": "tests/integration/targets/cloud_stack", + "name": "tests/integration/targets/folder", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/cloud_stack/tasks", + "name": "tests/integration/targets/folder/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/cloud_stack/tasks/main.yml", + "name": "tests/integration/targets/folder/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "54e2086aeb431d3016a02e4594f3d126ba8825f735a5114d356c573f25b9b3b5", + "chksum_sha256": "686ea10021f56ebda73ffae5c8c1a4829642d4c9e105f6c9ca8ae327c01a7387", "format": 1 }, { @@ -214,7 +375,21 @@ "name": "tests/integration/targets/dashboard/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "acdac91a4ec8fca7f99abad3bbc5fd920962e20e02e166f35d5513b6e92fa1b6", + "chksum_sha256": "686b506ae8c9e62a7122c0d9e957bf0aa04d7a4c766e5abc78f995fc0fbfab26", + "format": 1 + }, + { + "name": "tests/integration/targets/molecule-grafana-alternative", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/molecule-grafana-alternative/runme.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2879c89b4f2adf554de77e72bb21681933f1c3ffad0ff6097a11e40c97bd78c1", "format": 1 }, { @@ -235,7 +410,7 @@ "name": "tests/integration/targets/cloud_api_key/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "07fc392112316089cd6c5e2048ff5e1d8d6837ae103039e31c6938e4d5f5cff5", + "chksum_sha256": "6ab83417398137412541c07bc2e4461435d1b2393b3a8108f6c7380dbee71944", "format": 1 }, { @@ -256,7 +431,21 @@ "name": "tests/integration/targets/alert_notification_policy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "23f171d359577a28d52d24d174d217df537e9a662e01b503bd5c2198d4f00490", + "chksum_sha256": "4dec8dcbc12ebc228cd8171a515b64dc91fe0e9f258f350201148da594b0010c", + "format": 1 + }, + { + "name": "tests/integration/targets/molecule-grafana-default", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/molecule-grafana-default/runme.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2879c89b4f2adf554de77e72bb21681933f1c3ffad0ff6097a11e40c97bd78c1", "format": 1 }, { @@ -277,7 +466,7 @@ "name": "tests/integration/targets/cloud_plugin/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "19a6f479071b0a89c376b9cf6789370887b09f071adf9b56332c7932e23ee9ae", + "chksum_sha256": "7eb8a48e85835bc5154d9e6cc867e22e8ec0aca3dbc6b43f385bb6f2370a4486", "format": 1 }, { @@ -291,7 +480,7 @@ "name": "meta/runtime.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6daa0edca47a8056cd10e7c19b447549fb8accbc248cea597ce04b998e4190ae", + "chksum_sha256": "47e045205cccf3dab2959ce5a559aaea3e4283d3ed07fb1fb0392d8fb70f4be5", "format": 1 }, { @@ -309,129 +498,682 @@ "format": 1 }, { - "name": "roles/grafana_agent/tasks", + "name": "roles/grafana_agent/vars", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "roles/grafana_agent/tasks/main.yml", + "name": "roles/grafana_agent/vars/main.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7419b9d46b754bf838c5907de5dd1c2abc7d5a31ce0c8cc464eaaded1f9733e9", + "chksum_sha256": "bb6ac30f82acdbbee2aa7e8c3f61532319bdaf3d983b6c48c82c1901a9620725", "format": 1 }, { - "name": "roles/grafana_agent/meta", + "name": "roles/grafana_agent/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana_agent/tasks/install", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "roles/grafana_agent/meta/main.yml", + "name": "roles/grafana_agent/tasks/install/directories.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2bc89c9b41ea94d590cb9f76d7309f89175dd2cbbf698a0b3de4abbf6a2bf62d", + "chksum_sha256": "58cac80f91405cd323266b7435e58e656a16740ad9ac27f31b7167a1e6de84dd", "format": 1 }, { - "name": "roles/grafana_agent/README.md", + "name": "roles/grafana_agent/tasks/install/user-group.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c10802a2d7a4139178f2cedbb329146c480226ad956796ce1f9da515c9d89ae7", + "chksum_sha256": "6c36f9389415ee98e51bb7727045d5f6fae4e24a31ea62a74d48922af84abfd1", "format": 1 }, { - "name": "roles/grafana_agent/defaults", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "roles/grafana_agent/tasks/install/download-install.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8771b974c8e7592292ee66941c5c68e49b196408ea4b5655b80b849802255770", "format": 1 }, { - "name": "roles/grafana_agent/defaults/main.yml", + "name": "roles/grafana_agent/tasks/install/local-install.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b3fdc4f593e5eed0dc603f07b7c9864f6bc054266e5b9ea99f03b48b3ddb8cb2", + "chksum_sha256": "73d7d9cb92f3f837ac941d160296ee510fe4598685c1c67303c9246f459268aa", "format": 1 }, { - "name": "changelogs", + "name": "roles/grafana_agent/tasks/ga-started.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "03c283e74fef8eac9f628c37cb795d87bdbdb4c804acb2f2924813fb31ce6b82", + "format": 1 + }, + { + "name": "roles/grafana_agent/tasks/configure.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ade472dcf4c91db3ea6b3841b1f383045eac823c97f71c271ddccf98ac514b1c", + "format": 1 + }, + { + "name": "roles/grafana_agent/tasks/main.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "bb0018dd15d6c1deb675428d0088213b3a6bbd3bbbc795e7c847a2346b05ab9d", + "format": 1 + }, + { + "name": "roles/grafana_agent/tasks/install.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "aea56415837b4074ea9ec2e442bdc3eb509caf3b0574b54897c03b76b7eb190d", + "format": 1 + }, + { + "name": "roles/grafana_agent/tasks/preflight.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6518c23dabc92eb772132cd2dbb764ef381b93df8535ee59d7d5a4f0a39a24d4", + "format": 1 + }, + { + "name": "roles/grafana_agent/tasks/preflight", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "changelogs/config.yaml", + "name": "roles/grafana_agent/tasks/preflight/download.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "25b6f12f29b0f34c36cd88dafcdeec34796da955ee5a391a8491d25897b8d2ea", + "chksum_sha256": "5e90c5e06f97a8d2fa8398c6ab4f18857ad73553249558dfacc28f382a53502e", "format": 1 }, { - "name": "changelogs/.plugin-cache.yaml", + "name": "roles/grafana_agent/tasks/preflight/vars.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1420e01dfd19a743aa8a1a9ee80d51a235e00a5c5746ca0673d2f12e5a054e82", + "chksum_sha256": "87d1a4c7f9a02423c6cecd4927e79c89e126287d5671d26ae391a70de9a34a1a", "format": 1 }, { - "name": "changelogs/changelog.yaml", + "name": "roles/grafana_agent/tasks/preflight/systemd.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0225d8440fd04c2fa4486e8aaa00a9973e959b2ef933727318dba8018591c371", + "chksum_sha256": "ff9f62885f4516d0d17bc00f9be5cfb94d8fc23e18c1d3953c73e555fcb9e370", "format": 1 }, { - "name": "README.md", + "name": "roles/grafana_agent/tasks/preflight/install.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "19a0ff9a144be1931b9d65d698607cc96e91bacd3f1107edd6407a490e7a3106", + "chksum_sha256": "53c0a1d31af571b48eea830d1d53ca6f91d2e0149b98882af4240ba6a9e1e5bf", "format": 1 }, { - "name": ".github", + "name": "roles/grafana_agent/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": ".github/workflows", + "name": "roles/grafana_agent/meta/main.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "00ec33a60eed132359ae684f2602eaafd80c67bc8dc8103d4558857b37a89df5", + "format": 1 + }, + { + "name": "roles/grafana_agent/README.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f39efa315d0c1af1d87514936636e71ad15156effd4b14a4ed78bf37d2e514b8", + "format": 1 + }, + { + "name": "roles/grafana_agent/defaults", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": ".github/workflows/release.yml", + "name": "roles/grafana_agent/defaults/main.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f7dab8faa996095d8f73530fc55583a49d0db631a3cd8e1d5abc3d4b5f4fa16c", + "chksum_sha256": "ce5ef24967abddc425039e9fb4ff9bc49bdfaba4c9c046738d27a63675c6f3ad", "format": 1 }, { - "name": ".github/workflows/full-integration-test.yml", + "name": "roles/grafana_agent/templates", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana_agent/templates/EnvironmentFile.j2", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b1b7961d4550e68cdc8e6d0b2e5dd26aece4cfa12879be7ea987b1f241a702db", + "chksum_sha256": "9ddfc40e42ee8ffecff13ee5a7c995d4c968e14927d09e0f8ac228090c506bec", "format": 1 }, { - "name": ".github/workflows/ci-test.yml", + "name": "roles/grafana_agent/templates/config.yaml.j2", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1efd3367382e7027fc954b12a7b8f0c97dfbe69c4a4aee8eb53d9f52e89bafe8", + "chksum_sha256": "4ad78718159f384c7f85dec32f39f6901ce620ea03511e2159fae26da5fc1df6", "format": 1 }, { - "name": "CHANGELOG.rst", + "name": "roles/grafana_agent/templates/grafana-agent.service.j2", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "239c89d903d7df2d931969e783e84ee17184edf659d170c5cba727d907d9cfca", + "format": 1 + }, + { + "name": "roles/grafana_agent/handlers", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana_agent/handlers/main.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f04d1539911e34d8d0b41ecb1148195bb6e05f7d8a01bd7d1737b15a201a8d25", + "format": 1 + }, + { + "name": "roles/grafana", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/vars", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/vars/distro", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/vars/distro/redhat.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "54082a7385b630fb01d158412031ccdb3ab724ec0920d2b938fc2abfe5f231b1", + "format": 1 + }, + { + "name": "roles/grafana/vars/distro/suse.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9e0de4f35a28fba9722ec6b2e85448a9d17a446228d2c2ecac419510e1c0489f", + "format": 1 + }, + { + "name": "roles/grafana/vars/distro/debian.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b944353cfe0087673039b76c46305669d5f53f5402df8cd6637bf603dd5ba822", + "format": 1 + }, + { + "name": "roles/grafana/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/tasks/preflight.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5448f51232dfd1aac920ccc6e6c873c44702ee558b6b5ed1a5e0f7ff2331c820", + "format": 1 + }, + { + "name": "roles/grafana/tasks/configure.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "35e6680ced488f4de5995ff84e5a11b678ee3aa3dcea651b2bc0dd9427edc0ed", + "format": 1 + }, + { + "name": "roles/grafana/tasks/dashboards.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9ed4293bc3bb37072a64a333c3bc8ded3f2fd1d72b993581d3a4a6b3334eff74", + "format": 1 + }, + { + "name": "roles/grafana/tasks/notifications.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c9e18e896767159426fd75600ab6fa0e24bb746841ac0f363abc93a1732e0118", + "format": 1 + }, + { + "name": "roles/grafana/tasks/api_keys.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8ba965a54f41626728596d124b55e8ad7e437ac4342766bc7b95233b17a6a355", + "format": 1 + }, + { + "name": "roles/grafana/tasks/plugins.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb3dffd3395c8b6d8d363e98ba09c6f5add1ac667ffaa6239c93492b3732e347", + "format": 1 + }, + { + "name": "roles/grafana/tasks/datasources.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ad5d5a6a8d25c980b1961e6bf3fc54d7545fc8d420642381341c91bf7085a26f", + "format": 1 + }, + { + "name": "roles/grafana/tasks/install.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "de51e53b700558c75377e6dbeed087508e1362ee2793d084eea89125a42c6481", + "format": 1 + }, + { + "name": "roles/grafana/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "580c6f1da407217e65bbabb0ccd355f0bc8ce1ddda3b18206a0a97d380b7e0dc", + "format": 1 + }, + { + "name": "roles/grafana/test-requirements.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "bd70637dd6307a21c6084e83828c1ae13ac7818001bb9cffef2f8c0ea4e18b7b", + "format": 1 + }, + { + "name": "roles/grafana/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b74a99dba66c4a559a3a0c1fe555e3a5fb45ae036d89f5fa772b4b9978d8004d", + "format": 1 + }, + { + "name": "roles/grafana/README.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e60db326c70efc1cddd791edbe2e717922b4b65d10a71c126e02a8dbf4933140", + "format": 1 + }, + { + "name": "roles/grafana/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2f0b3a3a16323f48435a725a1d286c1fbd5008a3d6ad18e15d2c7004feb44b1e", + "format": 1 + }, + { + "name": "roles/grafana/templates", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/templates/grafana.ini.j2", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2dcef2a5205dd9b7d6b1a4c025e17a0827815b7b239cd63deec4ebeb24fc8745", + "format": 1 + }, + { + "name": "roles/grafana/templates/ldap.toml.j2", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8eaf66b16c9bbb51b8365b86e17a6bfc4776f58a4a0cb3804702707281c99abd", + "format": 1 + }, + { + "name": "roles/grafana/templates/tmpfiles.j2", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e2bf1d4dce1cab326b862898d787a16957b203ad3795012f4cbc3d11eb2315b9", + "format": 1 + }, + { + "name": "roles/grafana/molecule", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/molecule/alternative", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/molecule/alternative/molecule.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f52d711103d50a437830c6fbcd04fb4bab49a0f82f6d26d1c791c6e8488dd090", + "format": 1 + }, + { + "name": "roles/grafana/molecule/alternative/tests", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/molecule/alternative/tests/test_alternative.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "38cb4a0397ae36a77d8db4471e725be59d74a15350ccf42cffac3b5e7c399898", + "format": 1 + }, + { + "name": "roles/grafana/molecule/alternative/converge.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f502dc095236346e31330a7975e4fd0799d80fa8eb5e8c549ec56bf05ee49553", + "format": 1 + }, + { + "name": "roles/grafana/molecule/default", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/molecule/default/molecule.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f52d711103d50a437830c6fbcd04fb4bab49a0f82f6d26d1c791c6e8488dd090", + "format": 1 + }, + { + "name": "roles/grafana/molecule/default/tests", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/molecule/default/tests/test_default.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1f2d9786e6b222db39baa9259d1b420b46489595c74dec50804462ef3b1976a0", + "format": 1 + }, + { + "name": "roles/grafana/molecule/default/converge.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7d479b595ef871e3f545ee7b294d352978f572e581fca90694dcac81cf9e7948", + "format": 1 + }, + { + "name": "roles/grafana/handlers", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "roles/grafana/handlers/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fad32614d3bba77836db3fb79632a2f5336c4ca09ef6b0ff60c14793496c8799", + "format": 1 + }, + { + "name": ".editorconfig", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f1c0a5b9b3d1b8330cb6b4f2efc2df0be1bfb76faf1f4d67c9f1b65decc97c22", + "format": 1 + }, + { + "name": "changelogs", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "changelogs/config.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c3589ee373e4787fad20ff37228dfb90696a54ee0023c5f61ff5bf3abcf4b720", + "format": 1 + }, + { + "name": "changelogs/.plugin-cache.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "74da9ff1ab4154c38a7d91b8c3aa985e70c59709efa8832f7325dc0530483da2", + "format": 1 + }, + { + "name": "changelogs/changelog.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "200b1a4250b4551f9ec3e9e4409a4818f8d82be69875f4a8b44cff47741a6cf8", + "format": 1 + }, + { + "name": "README.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "58ab38c25312c0f6e89abd7ea7e99341806c0d7b9629a6b50fba7f31dfa1dd19", + "format": 1 + }, + { + "name": "Pipfile", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b812b6255a910c789bb830ada81e1af0f6a9c0c1d715f753b3224c03c63133a0", + "format": 1 + }, + { + "name": "yarn.lock", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5f22c47c3c50f0456bfbe9dcca84abe6e42f89f57ea6fe867bdf223dc19de933", + "format": 1 + }, + { + "name": ".ansible-lint", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "04baf7f010586545cab0fe765309cc43f22c2a2cb63361480c74e37b878d8684", + "format": 1 + }, + { + "name": ".gitignore", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d48f68dd16490e0613490dafff5d5284650fab7276c7117bbc6c726ee5b9b96f", + "format": 1 + }, + { + "name": "package.json", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b2bb1491300328b7736ace99ef86cd6e7c97ffd9a36dd8303c0b76ef28cc4787", + "format": 1 + }, + { + "name": "examples", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "examples/agent-basic-no-options.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cda05d1f95640fbfc976b77d7fcf3a319e8fb0bf9ba5e514b49bc99e04ac1c11", + "format": 1 + }, + { + "name": "examples/monitor-multiple-instances.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "312db8918e6f1e22bd0a6a2aefad5f5db8c0ab9bb88562c883aa047614b7b701", + "format": 1 + }, + { + "name": "examples/agent-send-to-grafana-cloud.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "50b70488a9b4089b5add092fe3aeb7560ac172ce0fd1a08350564c05ec77bf6a", + "format": 1 + }, + { + "name": "examples/ansible.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b78e2db98e14c343e41120940b0e1c5e553a30f4b61b1978515b1bd8e74aadd0", + "format": 1 + }, + { + "name": "ansible.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2caa654e85c7e66be39d494d173f69f7565059c504b7201f2ee033173ab80df0", + "format": 1 + }, + { + "name": ".github", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": ".github/workflows", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": ".github/workflows/release.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a4624ed81ee0e41e87897e436363a7f43fb54f380b705f159ecdb06bcaa5e2ad", + "format": 1 + }, + { + "name": ".github/workflows/full-integration-test.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "22d2553954fd81ff4e395d58122959f39d93fa9a0654c6aea6c421f49d348df3", + "format": 1 + }, + { + "name": ".github/workflows/roles-test.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6da36e4715b551f98fdbdcb578cc27b06b29f58b47f1e5cd8ac979e5c682089b", + "format": 1 + }, + { + "name": ".github/workflows/lint.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3355027fd55404c8c9b90118f8d3c8818c5f8eff4a2121bf7a8e5b03b7883193", + "format": 1 + }, + { + "name": ".github/workflows/modules-test.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4077b0be0f8279e1cf8a34d1c0a7fae86ed91c5019a99023a36e0164ba867272", + "format": 1 + }, + { + "name": ".github/dependabot.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "04b7f69732d281e9a97d10e72202312b72cb45358cbd1f1514983b6e6923f5bf", + "format": 1 + }, + { + "name": "requirements.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9f11ec06a7a1d62821de4fe26c7f76e15694fb4bfee1ae2ed1d2db93e4803545", + "format": 1 + }, + { + "name": ".markdownlint.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2d0b5ccb1e0c0105040a8c8fbe80b52f812951ff844f6b44ce8a8f8019debf5f", + "format": 1 + }, + { + "name": "CHANGELOG.rst", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "208e9649fa74320b42aea4fe7c32826a1e980b534adee8277d7cdb9767a5b4cb", + "format": 1 + }, + { + "name": "Pipfile.lock", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e5e870c176ffe1a69f5458d33a2cde667228b16d9859face63f0814079aed144", + "chksum_sha256": "1c5742f0d83518089922a5d484029f21ae68612c4bfd55dfbc54be61150ef087", "format": 1 } ], diff --git a/ansible_collections/grafana/grafana/MANIFEST.json b/ansible_collections/grafana/grafana/MANIFEST.json index 0ec5f0eb4..4a9ec0eb1 100644 --- a/ansible_collections/grafana/grafana/MANIFEST.json +++ b/ansible_collections/grafana/grafana/MANIFEST.json @@ -2,7 +2,7 @@ "collection_info": { "namespace": "grafana", "name": "grafana", - "version": "1.1.1", + "version": "2.2.5", "authors": [ "Grafana Labs ", "Ishan Jain " @@ -20,7 +20,7 @@ "license_file": null, "dependencies": {}, "repository": "https://github.com/grafana/grafana-ansible-collection", - "documentation": "https://docs.ansible.com/ansible/devel/collections/grafana/grafana/index.html", + "documentation": "https://docs.ansible.com/ansible/latest/collections/grafana/grafana/index.html", "homepage": null, "issues": "https://github.com/grafana/grafana-ansible-collection/issues" }, @@ -28,7 +28,7 @@ "name": "FILES.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e9bef1714ba34f82d3540689acda476e69f2929dc9c19bd978451e1908ecf11d", + "chksum_sha256": "efd45a0ccd368b6abc4faf1231e1a4cea2b606bd4f3220d4b8b899e3b2084aa7", "format": 1 }, "format": 1 diff --git a/ansible_collections/grafana/grafana/Makefile b/ansible_collections/grafana/grafana/Makefile new file mode 100644 index 000000000..b999dbd0e --- /dev/null +++ b/ansible_collections/grafana/grafana/Makefile @@ -0,0 +1,86 @@ +.DEFAULT_GOAL:= lint +PATH := ./node_modules/.bin:$(PATH) +SHELL := /bin/bash +args = $(filter-out $@, $(MAKECMDGOALS)) +.PHONY: all setup install clean reinstall build compile pdfs lint lint-sh lint-shell lint-md lint-markdown lint-txt lint-text pdf lint-yaml lint-yml lint-editorconfig lint-ec ci-lint ci-lint-shell ci-lint-markdown ci-lint-text ci-lint-yaml ci-lint-editorconfig lint-ansible ci-lint-ansible + +default: all + +all: install + +#################################################################### +# Installation / Setup # +#################################################################### +setup: + @./tools/setup.sh + +install: + yarn install + pipenv install + +# remove the build and log folders +clean: + rm -rf build node_modules + +# reinstall the node_modules and start with a fresh node build +reinstall: clean install + +#################################################################### +# Linting # +#################################################################### +lint: lint-shell lint-markdown lint-text lint-yaml lint-editorconfig lint-ansible + +# Note "|| true" is added to locally make lint can be ran and all linting is preformed, regardless of exit code + +# Shell Linting +lint-sh lint-shell: + @./tools/lint-shell.sh || true + +# Markdown Linting +lint-md lint-markdown: + @./tools/lint-markdown.sh || true + +# Text Linting +lint-txt lint-text: + @./tools/lint-text.sh || true + +# Yaml Linting +lint-yml lint-yaml: + @./tools/lint-yaml.sh || true + +# Editorconfig Linting +lint-ec lint-editorconfig: + @./tools/lint-editorconfig.sh || true + +# Ansible Linting +lint-ansible: + @./tools/lint-ansible.sh || true + +#################################################################### +# CI # +#################################################################### +ci-lint: ci-lint-shell ci-lint-markdown ci-lint-text ci-lint-yaml ci-lint-editorconfig ci-lint-ansible + +# Shell Linting +ci-lint-shell: + @./tools/lint-shell.sh + +# Markdown Linting +ci-lint-markdown: + @./tools/lint-markdown.sh + +# Text Linting +ci-lint-text: + @./tools/lint-text.sh + +# Yaml Linting +ci-lint-yaml: + @./tools/lint-yaml.sh + +# Editorconfig Linting +ci-lint-editorconfig: + @./tools/lint-editorconfig.sh + +# Ansible Linting +ci-lint-ansible: + @./tools/lint-ansible.sh diff --git a/ansible_collections/grafana/grafana/Pipfile b/ansible_collections/grafana/grafana/Pipfile new file mode 100644 index 000000000..162940e72 --- /dev/null +++ b/ansible_collections/grafana/grafana/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +yamllint = "==1.34.0" +ansible-lint = ">=6.13.1,<25.0.0" +pylint = ">=2.16.2,<4.0.0" + +[dev-packages] + +[requires] +python_version = "3.10" diff --git a/ansible_collections/grafana/grafana/Pipfile.lock b/ansible_collections/grafana/grafana/Pipfile.lock new file mode 100644 index 000000000..c15343a37 --- /dev/null +++ b/ansible_collections/grafana/grafana/Pipfile.lock @@ -0,0 +1,825 @@ +{ + "_meta": { + "hash": { + "sha256": "126b8e64a6e5896b218c3d70b198f9a6d159bccb911f554b17295c4a74888223" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.10" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "ansible-compat": { + "hashes": [ + "sha256:74a91807808a39af48ab6595811b9340d1458db26b138362f48bf39292190705", + "sha256:b3e9f9d7c3a1ce6222de444e9dc6fece7eba70ac64f2a0befdc4e2d542018b4a" + ], + "markers": "python_version >= '3.9'", + "version": "==4.1.11" + }, + "ansible-core": { + "hashes": [ + "sha256:50c9f33a5b2ee645470a77f4bf99cf35d1ffdefef60388910020b0c58534bec1", + "sha256:76a8765a8586064ef073a299562e308fa2c180a75b5f7569bbd0f61d4171cdb3" + ], + "markers": "python_version >= '3.10'", + "version": "==2.16.3" + }, + "ansible-lint": { + "hashes": [ + "sha256:6bc5d6273f33711ec6d370dfe5fdbe97a64b4c36c2a7a19a249401326eb03616", + "sha256:755f369c6baf601b09c4931a4e6bd0df3d79c54eb519f093e5db6ab52ad03e0c" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==24.2.0" + }, + "astroid": { + "hashes": [ + "sha256:4a61cf0a59097c7bb52689b0fd63717cd2a8a14dc9f1eee97b82d814881c8c91", + "sha256:d6e62862355f60e716164082d6b4b041d38e2a8cf1c7cd953ded5108bac8ff5c" + ], + "markers": "python_full_version >= '3.8.0'", + "version": "==3.0.2" + }, + "attrs": { + "hashes": [ + "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", + "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1" + ], + "markers": "python_version >= '3.7'", + "version": "==23.2.0" + }, + "black": { + "hashes": [ + "sha256:0269dfdea12442022e88043d2910429bed717b2d04523867a85dacce535916b8", + "sha256:07204d078e25327aad9ed2c64790d681238686bce254c910de640c7cc4fc3aa6", + "sha256:08b34e85170d368c37ca7bf81cf67ac863c9d1963b2c1780c39102187ec8dd62", + "sha256:1a95915c98d6e32ca43809d46d932e2abc5f1f7d582ffbe65a5b4d1588af7445", + "sha256:2588021038bd5ada078de606f2a804cadd0a3cc6a79cb3e9bb3a8bf581325a4c", + "sha256:2fa6a0e965779c8f2afb286f9ef798df770ba2b6cee063c650b96adec22c056a", + "sha256:34afe9da5056aa123b8bfda1664bfe6fb4e9c6f311d8e4a6eb089da9a9173bf9", + "sha256:3897ae5a21ca132efa219c029cce5e6bfc9c3d34ed7e892113d199c0b1b444a2", + "sha256:40657e1b78212d582a0edecafef133cf1dd02e6677f539b669db4746150d38f6", + "sha256:48b5760dcbfe5cf97fd4fba23946681f3a81514c6ab8a45b50da67ac8fbc6c7b", + "sha256:5242ecd9e990aeb995b6d03dc3b2d112d4a78f2083e5a8e86d566340ae80fec4", + "sha256:5cdc2e2195212208fbcae579b931407c1fa9997584f0a415421748aeafff1168", + "sha256:5d7b06ea8816cbd4becfe5f70accae953c53c0e53aa98730ceccb0395520ee5d", + "sha256:7258c27115c1e3b5de9ac6c4f9957e3ee2c02c0b39222a24dc7aa03ba0e986f5", + "sha256:854c06fb86fd854140f37fb24dbf10621f5dab9e3b0c29a690ba595e3d543024", + "sha256:a21725862d0e855ae05da1dd25e3825ed712eaaccef6b03017fe0853a01aa45e", + "sha256:a83fe522d9698d8f9a101b860b1ee154c1d25f8a82ceb807d319f085b2627c5b", + "sha256:b3d64db762eae4a5ce04b6e3dd745dcca0fb9560eb931a5be97472e38652a161", + "sha256:e298d588744efda02379521a19639ebcd314fba7a49be22136204d7ed1782717", + "sha256:e2c8dfa14677f90d976f68e0c923947ae68fa3961d61ee30976c388adc0b02c8", + "sha256:ecba2a15dfb2d97105be74bbfe5128bc5e9fa8477d8c46766505c1dda5883aac", + "sha256:fc1ec9aa6f4d98d022101e015261c056ddebe3da6a8ccfc2c792cbe0349d48b7" + ], + "markers": "python_version >= '3.8'", + "version": "==24.1.1" + }, + "bracex": { + "hashes": [ + "sha256:a27eaf1df42cf561fed58b7a8f3fdf129d1ea16a81e1fadd1d17989bc6384beb", + "sha256:efdc71eff95eaff5e0f8cfebe7d01adf2c8637c8c92edaf63ef348c241a82418" + ], + "markers": "python_version >= '3.8'", + "version": "==2.4" + }, + "cffi": { + "hashes": [ + "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc", + "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a", + "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417", + "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab", + "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520", + "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36", + "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743", + "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8", + "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed", + "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684", + "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56", + "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324", + "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d", + "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235", + "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e", + "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088", + "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000", + "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7", + "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e", + "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673", + "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c", + "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe", + "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2", + "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098", + "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8", + "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a", + "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0", + "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b", + "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896", + "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e", + "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9", + "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2", + "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b", + "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6", + "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404", + "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f", + "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0", + "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4", + "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc", + "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936", + "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba", + "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872", + "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb", + "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614", + "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1", + "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d", + "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969", + "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b", + "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4", + "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627", + "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", + "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" + ], + "markers": "platform_python_implementation != 'PyPy'", + "version": "==1.16.0" + }, + "click": { + "hashes": [ + "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.7" + }, + "cryptography": { + "hashes": [ + "sha256:087887e55e0b9c8724cf05361357875adb5c20dec27e5816b653492980d20380", + "sha256:09a77e5b2e8ca732a19a90c5bca2d124621a1edb5438c5daa2d2738bfeb02589", + "sha256:130c0f77022b2b9c99d8cebcdd834d81705f61c68e91ddd614ce74c657f8b3ea", + "sha256:141e2aa5ba100d3788c0ad7919b288f89d1fe015878b9659b307c9ef867d3a65", + "sha256:28cb2c41f131a5758d6ba6a0504150d644054fd9f3203a1e8e8d7ac3aea7f73a", + "sha256:2f9f14185962e6a04ab32d1abe34eae8a9001569ee4edb64d2304bf0d65c53f3", + "sha256:320948ab49883557a256eab46149df79435a22d2fefd6a66fe6946f1b9d9d008", + "sha256:36d4b7c4be6411f58f60d9ce555a73df8406d484ba12a63549c88bd64f7967f1", + "sha256:3b15c678f27d66d247132cbf13df2f75255627bcc9b6a570f7d2fd08e8c081d2", + "sha256:3dbd37e14ce795b4af61b89b037d4bc157f2cb23e676fa16932185a04dfbf635", + "sha256:4383b47f45b14459cab66048d384614019965ba6c1a1a141f11b5a551cace1b2", + "sha256:44c95c0e96b3cb628e8452ec060413a49002a247b2b9938989e23a2c8291fc90", + "sha256:4b063d3413f853e056161eb0c7724822a9740ad3caa24b8424d776cebf98e7ee", + "sha256:52ed9ebf8ac602385126c9a2fe951db36f2cb0c2538d22971487f89d0de4065a", + "sha256:55d1580e2d7e17f45d19d3b12098e352f3a37fe86d380bf45846ef257054b242", + "sha256:5ef9bc3d046ce83c4bbf4c25e1e0547b9c441c01d30922d812e887dc5f125c12", + "sha256:5fa82a26f92871eca593b53359c12ad7949772462f887c35edaf36f87953c0e2", + "sha256:61321672b3ac7aade25c40449ccedbc6db72c7f5f0fdf34def5e2f8b51ca530d", + "sha256:701171f825dcab90969596ce2af253143b93b08f1a716d4b2a9d2db5084ef7be", + "sha256:841ec8af7a8491ac76ec5a9522226e287187a3107e12b7d686ad354bb78facee", + "sha256:8a06641fb07d4e8f6c7dda4fc3f8871d327803ab6542e33831c7ccfdcb4d0ad6", + "sha256:8e88bb9eafbf6a4014d55fb222e7360eef53e613215085e65a13290577394529", + "sha256:a00aee5d1b6c20620161984f8ab2ab69134466c51f58c052c11b076715e72929", + "sha256:a047682d324ba56e61b7ea7c7299d51e61fd3bca7dad2ccc39b72bd0118d60a1", + "sha256:a7ef8dd0bf2e1d0a27042b231a3baac6883cdd5557036f5e8df7139255feaac6", + "sha256:ad28cff53f60d99a928dfcf1e861e0b2ceb2bc1f08a074fdd601b314e1cc9e0a", + "sha256:b9097a208875fc7bbeb1286d0125d90bdfed961f61f214d3f5be62cd4ed8a446", + "sha256:b97fe7d7991c25e6a31e5d5e795986b18fbbb3107b873d5f3ae6dc9a103278e9", + "sha256:e0ec52ba3c7f1b7d813cd52649a5b3ef1fc0d433219dc8c93827c57eab6cf888", + "sha256:ea2c3ffb662fec8bbbfce5602e2c159ff097a4631d96235fcf0fb00e59e3ece4", + "sha256:fa3dec4ba8fb6e662770b74f62f1a0c7d4e37e25b58b2bf2c1be4c95372b4a33", + "sha256:fbeb725c9dc799a574518109336acccaf1303c30d45c075c665c0793c2f79a7f" + ], + "markers": "python_version >= '3.7'", + "version": "==42.0.2" + }, + "dill": { + "hashes": [ + "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca", + "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7" + ], + "markers": "python_version < '3.11'", + "version": "==0.3.8" + }, + "filelock": { + "hashes": [ + "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e", + "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c" + ], + "markers": "python_version >= '3.8'", + "version": "==3.13.1" + }, + "isort": { + "hashes": [ + "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109", + "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6" + ], + "markers": "python_full_version >= '3.8.0'", + "version": "==5.13.2" + }, + "jinja2": { + "hashes": [ + "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa", + "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.3" + }, + "jsonschema": { + "hashes": [ + "sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f", + "sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5" + ], + "markers": "python_version >= '3.8'", + "version": "==4.21.1" + }, + "jsonschema-specifications": { + "hashes": [ + "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc", + "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c" + ], + "markers": "python_version >= '3.8'", + "version": "==2023.12.1" + }, + "lazy-object-proxy": { + "hashes": [ + "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382", + "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82", + "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9", + "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494", + "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46", + "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30", + "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63", + "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4", + "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae", + "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be", + "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701", + "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd", + "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006", + "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a", + "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586", + "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8", + "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821", + "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07", + "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b", + "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171", + "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b", + "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2", + "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7", + "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4", + "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8", + "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e", + "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f", + "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda", + "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4", + "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e", + "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671", + "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11", + "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455", + "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734", + "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb", + "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59" + ], + "markers": "python_version >= '3.7'", + "version": "==1.9.0" + }, + "markdown-it-py": { + "hashes": [ + "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", + "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb" + ], + "markers": "python_version >= '3.8'", + "version": "==3.0.0" + }, + "markupsafe": { + "hashes": [ + "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf", + "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff", + "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f", + "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3", + "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532", + "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f", + "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617", + "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df", + "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4", + "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906", + "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f", + "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4", + "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8", + "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371", + "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2", + "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465", + "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52", + "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6", + "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169", + "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad", + "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2", + "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0", + "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029", + "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f", + "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a", + "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced", + "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5", + "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c", + "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf", + "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9", + "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb", + "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad", + "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3", + "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1", + "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46", + "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc", + "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a", + "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee", + "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900", + "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5", + "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea", + "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f", + "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5", + "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e", + "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a", + "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f", + "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50", + "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a", + "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b", + "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4", + "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff", + "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2", + "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46", + "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b", + "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf", + "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5", + "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5", + "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab", + "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd", + "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68" + ], + "markers": "python_version >= '3.7'", + "version": "==2.1.5" + }, + "mccabe": { + "hashes": [ + "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", + "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" + ], + "markers": "python_version >= '3.6'", + "version": "==0.7.0" + }, + "mdurl": { + "hashes": [ + "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", + "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" + ], + "markers": "python_version >= '3.7'", + "version": "==0.1.2" + }, + "mypy-extensions": { + "hashes": [ + "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", + "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.0" + }, + "packaging": { + "hashes": [ + "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", + "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" + ], + "markers": "python_version >= '3.7'", + "version": "==23.2" + }, + "pathspec": { + "hashes": [ + "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", + "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712" + ], + "markers": "python_version >= '3.8'", + "version": "==0.12.1" + }, + "platformdirs": { + "hashes": [ + "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068", + "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768" + ], + "markers": "python_version >= '3.8'", + "version": "==4.2.0" + }, + "pycparser": { + "hashes": [ + "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", + "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" + ], + "version": "==2.21" + }, + "pygments": { + "hashes": [ + "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", + "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367" + ], + "markers": "python_version >= '3.7'", + "version": "==2.17.2" + }, + "pylint": { + "hashes": [ + "sha256:58c2398b0301e049609a8429789ec6edf3aabe9b6c5fec916acd18639c16de8b", + "sha256:7a1585285aefc5165db81083c3e06363a27448f6b467b3b0f30dbd0ac1f73810" + ], + "index": "pypi", + "markers": "python_full_version >= '3.8.0'", + "version": "==3.0.3" + }, + "pyyaml": { + "hashes": [ + "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", + "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", + "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", + "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", + "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", + "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", + "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", + "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", + "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", + "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", + "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", + "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", + "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", + "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", + "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", + "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", + "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", + "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", + "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", + "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", + "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", + "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", + "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", + "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", + "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", + "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", + "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", + "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", + "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", + "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", + "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", + "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", + "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", + "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", + "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", + "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", + "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", + "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", + "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", + "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", + "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", + "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", + "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", + "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", + "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", + "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", + "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", + "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", + "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", + "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", + "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" + ], + "markers": "python_version >= '3.6'", + "version": "==6.0.1" + }, + "referencing": { + "hashes": [ + "sha256:39240f2ecc770258f28b642dd47fd74bc8b02484de54e1882b74b35ebd779bd5", + "sha256:c775fedf74bc0f9189c2a3be1c12fd03e8c23f4d371dce795df44e06c5b412f7" + ], + "markers": "python_version >= '3.8'", + "version": "==0.33.0" + }, + "resolvelib": { + "hashes": [ + "sha256:04ce76cbd63fded2078ce224785da6ecd42b9564b1390793f64ddecbe997b309", + "sha256:d2da45d1a8dfee81bdd591647783e340ef3bcb104b54c383f70d422ef5cc7dbf" + ], + "version": "==1.0.1" + }, + "rich": { + "hashes": [ + "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa", + "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235" + ], + "markers": "python_full_version >= '3.7.0'", + "version": "==13.7.0" + }, + "rpds-py": { + "hashes": [ + "sha256:01f58a7306b64e0a4fe042047dd2b7d411ee82e54240284bab63e325762c1147", + "sha256:0210b2668f24c078307260bf88bdac9d6f1093635df5123789bfee4d8d7fc8e7", + "sha256:02866e060219514940342a1f84303a1ef7a1dad0ac311792fbbe19b521b489d2", + "sha256:0387ce69ba06e43df54e43968090f3626e231e4bc9150e4c3246947567695f68", + "sha256:060f412230d5f19fc8c8b75f315931b408d8ebf56aec33ef4168d1b9e54200b1", + "sha256:071bc28c589b86bc6351a339114fb7a029f5cddbaca34103aa573eba7b482382", + "sha256:0bfb09bf41fe7c51413f563373e5f537eaa653d7adc4830399d4e9bdc199959d", + "sha256:10162fe3f5f47c37ebf6d8ff5a2368508fe22007e3077bf25b9c7d803454d921", + "sha256:149c5cd24f729e3567b56e1795f74577aa3126c14c11e457bec1b1c90d212e38", + "sha256:1701fc54460ae2e5efc1dd6350eafd7a760f516df8dbe51d4a1c79d69472fbd4", + "sha256:1957a2ab607f9added64478a6982742eb29f109d89d065fa44e01691a20fc20a", + "sha256:1a746a6d49665058a5896000e8d9d2f1a6acba8a03b389c1e4c06e11e0b7f40d", + "sha256:1bfcad3109c1e5ba3cbe2f421614e70439f72897515a96c462ea657261b96518", + "sha256:1d36b2b59e8cc6e576f8f7b671e32f2ff43153f0ad6d0201250a7c07f25d570e", + "sha256:1db228102ab9d1ff4c64148c96320d0be7044fa28bd865a9ce628ce98da5973d", + "sha256:1dc29db3900cb1bb40353772417800f29c3d078dbc8024fd64655a04ee3c4bdf", + "sha256:1e626b365293a2142a62b9a614e1f8e331b28f3ca57b9f05ebbf4cf2a0f0bdc5", + "sha256:1f3c3461ebb4c4f1bbc70b15d20b565759f97a5aaf13af811fcefc892e9197ba", + "sha256:20de7b7179e2031a04042e85dc463a93a82bc177eeba5ddd13ff746325558aa6", + "sha256:24e4900a6643f87058a27320f81336d527ccfe503984528edde4bb660c8c8d59", + "sha256:2528ff96d09f12e638695f3a2e0c609c7b84c6df7c5ae9bfeb9252b6fa686253", + "sha256:25f071737dae674ca8937a73d0f43f5a52e92c2d178330b4c0bb6ab05586ffa6", + "sha256:270987bc22e7e5a962b1094953ae901395e8c1e1e83ad016c5cfcfff75a15a3f", + "sha256:292f7344a3301802e7c25c53792fae7d1593cb0e50964e7bcdcc5cf533d634e3", + "sha256:2953937f83820376b5979318840f3ee47477d94c17b940fe31d9458d79ae7eea", + "sha256:2a792b2e1d3038daa83fa474d559acfd6dc1e3650ee93b2662ddc17dbff20ad1", + "sha256:2a7b2f2f56a16a6d62e55354dd329d929560442bd92e87397b7a9586a32e3e76", + "sha256:2f4eb548daf4836e3b2c662033bfbfc551db58d30fd8fe660314f86bf8510b93", + "sha256:3664d126d3388a887db44c2e293f87d500c4184ec43d5d14d2d2babdb4c64cad", + "sha256:3677fcca7fb728c86a78660c7fb1b07b69b281964673f486ae72860e13f512ad", + "sha256:380e0df2e9d5d5d339803cfc6d183a5442ad7ab3c63c2a0982e8c824566c5ccc", + "sha256:3ac732390d529d8469b831949c78085b034bff67f584559340008d0f6041a049", + "sha256:4128980a14ed805e1b91a7ed551250282a8ddf8201a4e9f8f5b7e6225f54170d", + "sha256:4341bd7579611cf50e7b20bb8c2e23512a3dc79de987a1f411cb458ab670eb90", + "sha256:436474f17733c7dca0fbf096d36ae65277e8645039df12a0fa52445ca494729d", + "sha256:4dc889a9d8a34758d0fcc9ac86adb97bab3fb7f0c4d29794357eb147536483fd", + "sha256:4e21b76075c01d65d0f0f34302b5a7457d95721d5e0667aea65e5bb3ab415c25", + "sha256:516fb8c77805159e97a689e2f1c80655c7658f5af601c34ffdb916605598cda2", + "sha256:5576ee2f3a309d2bb403ec292d5958ce03953b0e57a11d224c1f134feaf8c40f", + "sha256:5a024fa96d541fd7edaa0e9d904601c6445e95a729a2900c5aec6555fe921ed6", + "sha256:5d0e8a6434a3fbf77d11448c9c25b2f25244226cfbec1a5159947cac5b8c5fa4", + "sha256:5e7d63ec01fe7c76c2dbb7e972fece45acbb8836e72682bde138e7e039906e2c", + "sha256:60e820ee1004327609b28db8307acc27f5f2e9a0b185b2064c5f23e815f248f8", + "sha256:637b802f3f069a64436d432117a7e58fab414b4e27a7e81049817ae94de45d8d", + "sha256:65dcf105c1943cba45d19207ef51b8bc46d232a381e94dd38719d52d3980015b", + "sha256:698ea95a60c8b16b58be9d854c9f993c639f5c214cf9ba782eca53a8789d6b19", + "sha256:70fcc6c2906cfa5c6a552ba7ae2ce64b6c32f437d8f3f8eea49925b278a61453", + "sha256:720215373a280f78a1814becb1312d4e4d1077b1202a56d2b0815e95ccb99ce9", + "sha256:7450dbd659fed6dd41d1a7d47ed767e893ba402af8ae664c157c255ec6067fde", + "sha256:7b7d9ca34542099b4e185b3c2a2b2eda2e318a7dbde0b0d83357a6d4421b5296", + "sha256:7fbd70cb8b54fe745301921b0816c08b6d917593429dfc437fd024b5ba713c58", + "sha256:81038ff87a4e04c22e1d81f947c6ac46f122e0c80460b9006e6517c4d842a6ec", + "sha256:810685321f4a304b2b55577c915bece4c4a06dfe38f6e62d9cc1d6ca8ee86b99", + "sha256:82ada4a8ed9e82e443fcef87e22a3eed3654dd3adf6e3b3a0deb70f03e86142a", + "sha256:841320e1841bb53fada91c9725e766bb25009cfd4144e92298db296fb6c894fb", + "sha256:8587fd64c2a91c33cdc39d0cebdaf30e79491cc029a37fcd458ba863f8815383", + "sha256:8ffe53e1d8ef2520ebcf0c9fec15bb721da59e8ef283b6ff3079613b1e30513d", + "sha256:9051e3d2af8f55b42061603e29e744724cb5f65b128a491446cc029b3e2ea896", + "sha256:91e5a8200e65aaac342a791272c564dffcf1281abd635d304d6c4e6b495f29dc", + "sha256:93432e747fb07fa567ad9cc7aaadd6e29710e515aabf939dfbed8046041346c6", + "sha256:938eab7323a736533f015e6069a7d53ef2dcc841e4e533b782c2bfb9fb12d84b", + "sha256:9584f8f52010295a4a417221861df9bea4c72d9632562b6e59b3c7b87a1522b7", + "sha256:9737bdaa0ad33d34c0efc718741abaafce62fadae72c8b251df9b0c823c63b22", + "sha256:99da0a4686ada4ed0f778120a0ea8d066de1a0a92ab0d13ae68492a437db78bf", + "sha256:99f567dae93e10be2daaa896e07513dd4bf9c2ecf0576e0533ac36ba3b1d5394", + "sha256:9bdf1303df671179eaf2cb41e8515a07fc78d9d00f111eadbe3e14262f59c3d0", + "sha256:9f0e4dc0f17dcea4ab9d13ac5c666b6b5337042b4d8f27e01b70fae41dd65c57", + "sha256:a000133a90eea274a6f28adc3084643263b1e7c1a5a66eb0a0a7a36aa757ed74", + "sha256:a3264e3e858de4fc601741498215835ff324ff2482fd4e4af61b46512dd7fc83", + "sha256:a71169d505af63bb4d20d23a8fbd4c6ce272e7bce6cc31f617152aa784436f29", + "sha256:a967dd6afda7715d911c25a6ba1517975acd8d1092b2f326718725461a3d33f9", + "sha256:aa5bfb13f1e89151ade0eb812f7b0d7a4d643406caaad65ce1cbabe0a66d695f", + "sha256:ae35e8e6801c5ab071b992cb2da958eee76340e6926ec693b5ff7d6381441745", + "sha256:b686f25377f9c006acbac63f61614416a6317133ab7fafe5de5f7dc8a06d42eb", + "sha256:b760a56e080a826c2e5af09002c1a037382ed21d03134eb6294812dda268c811", + "sha256:b86b21b348f7e5485fae740d845c65a880f5d1eda1e063bc59bef92d1f7d0c55", + "sha256:b9412abdf0ba70faa6e2ee6c0cc62a8defb772e78860cef419865917d86c7342", + "sha256:bd345a13ce06e94c753dab52f8e71e5252aec1e4f8022d24d56decd31e1b9b23", + "sha256:be22ae34d68544df293152b7e50895ba70d2a833ad9566932d750d3625918b82", + "sha256:bf046179d011e6114daf12a534d874958b039342b347348a78b7cdf0dd9d6041", + "sha256:c3d2010656999b63e628a3c694f23020322b4178c450dc478558a2b6ef3cb9bb", + "sha256:c64602e8be701c6cfe42064b71c84ce62ce66ddc6422c15463fd8127db3d8066", + "sha256:d65e6b4f1443048eb7e833c2accb4fa7ee67cc7d54f31b4f0555b474758bee55", + "sha256:d8bbd8e56f3ba25a7d0cf980fc42b34028848a53a0e36c9918550e0280b9d0b6", + "sha256:da1ead63368c04a9bded7904757dfcae01eba0e0f9bc41d3d7f57ebf1c04015a", + "sha256:dbbb95e6fc91ea3102505d111b327004d1c4ce98d56a4a02e82cd451f9f57140", + "sha256:dbc56680ecf585a384fbd93cd42bc82668b77cb525343170a2d86dafaed2a84b", + "sha256:df3b6f45ba4515632c5064e35ca7f31d51d13d1479673185ba8f9fefbbed58b9", + "sha256:dfe07308b311a8293a0d5ef4e61411c5c20f682db6b5e73de6c7c8824272c256", + "sha256:e796051f2070f47230c745d0a77a91088fbee2cc0502e9b796b9c6471983718c", + "sha256:efa767c220d94aa4ac3a6dd3aeb986e9f229eaf5bce92d8b1b3018d06bed3772", + "sha256:f0b8bf5b8db49d8fd40f54772a1dcf262e8be0ad2ab0206b5a2ec109c176c0a4", + "sha256:f175e95a197f6a4059b50757a3dca33b32b61691bdbd22c29e8a8d21d3914cae", + "sha256:f2f3b28b40fddcb6c1f1f6c88c6f3769cd933fa493ceb79da45968a21dccc920", + "sha256:f6c43b6f97209e370124baf2bf40bb1e8edc25311a158867eb1c3a5d449ebc7a", + "sha256:f7f4cb1f173385e8a39c29510dd11a78bf44e360fb75610594973f5ea141028b", + "sha256:fad059a4bd14c45776600d223ec194e77db6c20255578bb5bcdd7c18fd169361", + "sha256:ff1dcb8e8bc2261a088821b2595ef031c91d499a0c1b031c152d43fe0a6ecec8", + "sha256:ffee088ea9b593cc6160518ba9bd319b5475e5f3e578e4552d63818773c6f56a" + ], + "markers": "python_version >= '3.8'", + "version": "==0.17.1" + }, + "ruamel.yaml": { + "hashes": [ + "sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636", + "sha256:8b27e6a217e786c6fbe5634d8f3f11bc63e0f80f6a5890f28863d9c45aac311b" + ], + "markers": "python_version >= '3.7'", + "version": "==0.18.6" + }, + "ruamel.yaml.clib": { + "hashes": [ + "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d", + "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001", + "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462", + "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9", + "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe", + "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b", + "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b", + "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615", + "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62", + "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15", + "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b", + "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1", + "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9", + "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675", + "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899", + "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7", + "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7", + "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312", + "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa", + "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91", + "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b", + "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6", + "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3", + "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334", + "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5", + "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3", + "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe", + "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c", + "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed", + "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337", + "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880", + "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f", + "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d", + "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248", + "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d", + "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf", + "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512", + "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069", + "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb", + "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942", + "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d", + "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31", + "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92", + "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5", + "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28", + "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d", + "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1", + "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2", + "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875", + "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412" + ], + "markers": "python_version < '3.13' and platform_python_implementation == 'CPython'", + "version": "==0.2.8" + }, + "setuptools": { + "hashes": [ + "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05", + "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78" + ], + "markers": "python_version >= '3.8'", + "version": "==69.0.3" + }, + "subprocess-tee": { + "hashes": [ + "sha256:b3c124993f8b88d1eb1c2fde0bc2069787eac720ba88771cba17e8c93324825d", + "sha256:eca56973a1c1237093c2055b2731bcaab784683b83f22c76f26e4c5763402e28" + ], + "markers": "python_version >= '3.8'", + "version": "==0.4.1" + }, + "tomli": { + "hashes": [ + "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" + ], + "markers": "python_version < '3.11'", + "version": "==2.0.1" + }, + "tomlkit": { + "hashes": [ + "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4", + "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba" + ], + "markers": "python_version >= '3.7'", + "version": "==0.12.3" + }, + "typing-extensions": { + "hashes": [ + "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783", + "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" + ], + "markers": "python_version < '3.11'", + "version": "==4.9.0" + }, + "wcmatch": { + "hashes": [ + "sha256:14554e409b142edeefab901dc68ad570b30a72a8ab9a79106c5d5e9a6d241bd5", + "sha256:86c17572d0f75cbf3bcb1a18f3bf2f9e72b39a9c08c9b4a74e991e1882a8efb3" + ], + "markers": "python_version >= '3.8'", + "version": "==8.5" + }, + "wrapt": { + "hashes": [ + "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0", + "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420", + "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a", + "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c", + "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079", + "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923", + "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f", + "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1", + "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8", + "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86", + "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0", + "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364", + "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e", + "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c", + "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e", + "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c", + "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727", + "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff", + "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e", + "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29", + "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7", + "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72", + "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475", + "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a", + "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317", + "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2", + "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd", + "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640", + "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98", + "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248", + "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e", + "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d", + "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec", + "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1", + "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e", + "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9", + "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92", + "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb", + "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094", + "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46", + "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29", + "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd", + "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705", + "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8", + "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975", + "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb", + "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e", + "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b", + "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418", + "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019", + "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1", + "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba", + "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6", + "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2", + "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3", + "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7", + "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752", + "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416", + "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f", + "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1", + "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc", + "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145", + "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee", + "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a", + "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7", + "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b", + "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653", + "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0", + "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90", + "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29", + "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6", + "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034", + "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09", + "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559", + "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639" + ], + "markers": "python_version < '3.11'", + "version": "==1.15.0" + }, + "yamllint": { + "hashes": [ + "sha256:33b813f6ff2ffad2e57a288281098392b85f7463ce1f3d5cd45aa848b916a806", + "sha256:7f0a6a41e8aab3904878da4ae34b6248b6bc74634e0d3a90f0fb2d7e723a3d4f" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==1.34.0" + } + }, + "develop": {} +} diff --git a/ansible_collections/grafana/grafana/README.md b/ansible_collections/grafana/grafana/README.md index 93d90c82b..e28604a1f 100644 --- a/ansible_collections/grafana/grafana/README.md +++ b/ansible_collections/grafana/grafana/README.md @@ -1,22 +1,29 @@ -# Ansible Collection for Grafana Cloud +# Ansible Collection for Grafana -[![CI Tests](https://github.com/grafana/grafana-ansible-collection/actions/workflows/ci-test.yml/badge.svg)](https://github.com/grafana/grafana-ansible-collection/actions/workflows/ci-test.yml) +[![Grafana](https://img.shields.io/badge/grafana-%23F46800.svg?&logo=grafana&logoColor=white)](https://grafana.com) +[![Ansible Collection](https://img.shields.io/badge/grafana.grafana-orange)](https://galaxy.ansible.com/ui/repo/published/grafana/grafana/) +[![GitHub tag](https://img.shields.io/github/tag/grafana/grafana-ansible-collection.svg)](https://github.com/grafana/grafana-ansible-collection/tags) +[![GitHub Last Commit](https://img.shields.io/github/last-commit/grafana/grafana-ansible-collection)](https://github.com/grafana/grafana-ansible-collection/tags) +[![GitHub Contributors](https://img.shields.io/github/contributors/grafana/grafana-ansible-collection)](https://github.com/grafana/grafana-ansible-collection/tags) + +[![Modules Test](https://github.com/grafana/grafana-ansible-collection/actions/workflows/modules-test.yml/badge.svg?branch=main)](https://github.com/grafana/grafana-ansible-collection/actions/workflows/modules-test.yml) +[![Roles Test](https://github.com/grafana/grafana-ansible-collection/actions/workflows/roles-test.yml/badge.svg?branch=main)](https://github.com/grafana/grafana-ansible-collection/actions/workflows/roles-test.yml) [![Full Integration Test](https://github.com/grafana/grafana-ansible-collection/actions/workflows/full-integration-test.yml/badge.svg?branch=main)](https://github.com/grafana/grafana-ansible-collection/actions/workflows/full-integration-test.yml) +[![Lint](https://github.com/grafana/grafana-ansible-collection/actions/workflows/lint.yaml/badge.svg)](https://github.com/grafana/grafana-ansible-collection/actions/workflows/lint.yaml) -This collection (grafana.grafana) contains modules and plugins to assist in automating managing of resources in Grafana Cloud with Ansible. +This collection (`grafana.grafana`) contains modules and plugins to assist in automating managing of resources in **Grafana** with Ansible. -- [Ansible collection Documentation](https://grafana.github.io/grafana-ansible-collection/) -- [Grafana website](https://grafana.com) -- [Grafana Cloud website](https://grafana.com/products/cloud/) +- [Ansible collection Documentation](https://docs.ansible.com/ansible/latest/collections/grafana/grafana/) +- [Grafana](https://grafana.com) +- [Grafana Cloud](https://grafana.com/products/cloud/) ## Ansible version compatibility -The collection is tested and supported with: -* ansible >= 2.9 +The collection is tested and supported with: `ansible >= 2.9` ## Installing the collection -Before using the Grafana collection, you need to install it using the below commoand: +Before using the Grafana collection, you need to install it using the below command: ```shell ansible-galaxy collection install grafana.grafana @@ -29,6 +36,7 @@ You can also include it in a `requirements.yml` file and install it via ansible- collections: - name: grafana.grafana ``` + A specific version of the collection can be installed by using the version keyword in the `requirements.yml` file: ```yaml @@ -37,9 +45,11 @@ collections: - name: grafana.grafana version: 1.0.0 ``` + ## Using this collection You can call modules by their Fully Qualified Collection Namespace (FQCN), such as `grafana.grafana.cloud_stack`: + ```yaml - name: Using grafana collection hosts: localhost @@ -55,6 +65,7 @@ You can call modules by their Fully Qualified Collection Namespace (FQCN), such ``` or you can add full namespace and collection name in the `collections` element in your playbook + ```yaml - name: Using grafana collection hosts: localhost @@ -72,11 +83,12 @@ or you can add full namespace and collection name in the `collections` element i ``` ## Contributing -We are accepting Github pull requests and issues. There are many ways in which you can participate in the project, for example: -* Submit bugs and feature requests, and help us verify them -* Submit and review source code changes in Github pull requests -* Add new modules for more Grafana resources +We are accepting GitHub pull requests and issues. There are many ways in which you can participate in the project, for example: + +- Submit bugs and feature requests, and help us verify them +- Submit and review source code changes in GitHub pull requests +- Add new modules for more Grafana resources ## Testing and Development @@ -89,29 +101,51 @@ and work on it there. We use `ansible-test` for sanity. +## Commands + +| Command | Description | +| :--- | :----------- | +| `make setup` | Checks to see if necessary tools are installed | +| `make install` | Installs project dependencies | +| `make lint` | Performs all linting commands | +| `make lint-sh` / `make lint-shell` | Performs shell script linting | +| `make lint-md` / `make lint-markdown` | Performs Markdown linting | +| `make lint-txt` / `make lint-text` | Performs text linting | +| `make lint-yml` / `make lint-yaml` | Performs Yaml linting | +| `make lint-ec` / `make lint-editorconfig` | Performs EditorConfig Checks | +| `make lint-ansible` | Performs Ansible linting | +| `make clean` | Removes the `./node_modules` and `./build` directories | +| `make reinstall` | Shortcut to `make clean` and `make install` | + ## Releasing, Versioning and Deprecation This collection follows [Semantic Versioning](https://semver.org/). More details on versioning can be found [in the Ansible docs](https://docs.ansible.com/ansible/latest/dev_guide/developing_collections.html#collection-versions). We plan to regularly release new minor or bugfix versions once new features or bugfixes have been implemented. -Releasing the current major version on GitHub happens from the `main` branch by the [GitHub Release Workflow](https://github.com/grafana/grafana-ansible-collection/blob/main/.github/workflows/release.yml) -Before the [GitHub Release Workflow](https://github.com/grafana/grafana-ansible-collection/blob/main/.github/workflows/release.yml) is run, Contributors should push the new version on Ansible Galaxy Manually. +Releasing the current major version on GitHub happens from the `main` branch by the +[GitHub Release Workflow](https://github.com/grafana/grafana-ansible-collection/blob/main/.github/workflows/release.yml). +Before the [GitHub Release Workflow](https://github.com/grafana/grafana-ansible-collection/blob/main/.github/workflows/release.yml) +is run, Contributors should push the new version on Ansible Galaxy Manually. -We currently are not planning any deprecations or new major releases. The current landscape includes minor version updates for Module's documentation in 1.1.1. +To generate changelogs for a new release, Refer [Generating Changelogs](https://docs.ansible.com/ansible/latest/dev_guide/developing_collections_changelogs.html#generating-changelogs) + +To generate the tarball to be uploaded on Ansible Galaxy, Refer [Building collection tarball](https://docs.ansible.com/ansible/latest/dev_guide/developing_collections_distributing.html#building-your-collection-tarball) ## Code of Conduct -This collection follows the Ansible project's [Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html). Please read and familiarize yourself with this doc + +This collection follows the Ansible project's [Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html). +Please read and familiarize yourself with this doc ## More information -- [Maintainer guidelines](https://docs.ansible.com/ansible/devel/community/maintainers.html) -- Subscribe to the [news-for-maintainers](https://github.com/ansible-collections/news-for-maintainers) repo and track announcements there. -- [Ansible Collection overview](https://github.com/ansible-collections/overview) -- [Ansible User guide](https://docs.ansible.com/ansible/latest/user_guide/index.html) -- [Ansible Developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html) -- [Ansible Collection Developer Guide](https://docs.ansible.com/ansible/devel/dev_guide/developing_collections.html) -- [Ansible Community code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) +- [Maintainer guidelines](https://docs.ansible.com/ansible/devel/community/maintainers.html) +- Subscribe to the [news-for-maintainers](https://github.com/ansible-collections/news-for-maintainers) repository and track announcements there. +- [Ansible Collection overview](https://github.com/ansible-collections/overview) +- [Ansible User guide](https://docs.ansible.com/ansible/latest/user_guide/index.html) +- [Ansible Developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html) +- [Ansible Collection Developer Guide](https://docs.ansible.com/ansible/devel/dev_guide/developing_collections.html) +- [Ansible Community code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) ## License diff --git a/ansible_collections/grafana/grafana/ansible.cfg b/ansible_collections/grafana/grafana/ansible.cfg new file mode 100644 index 000000000..fecf5b666 --- /dev/null +++ b/ansible_collections/grafana/grafana/ansible.cfg @@ -0,0 +1,2 @@ +[defaults] +collections_paths = ./ diff --git a/ansible_collections/grafana/grafana/changelogs/.plugin-cache.yaml b/ansible_collections/grafana/grafana/changelogs/.plugin-cache.yaml index 2a55a211f..0f8ab33ab 100644 --- a/ansible_collections/grafana/grafana/changelogs/.plugin-cache.yaml +++ b/ansible_collections/grafana/grafana/changelogs/.plugin-cache.yaml @@ -12,12 +12,12 @@ plugins: lookup: {} module: alert_contact_point: - description: Manage Alerting Contact points in Grafana Cloud + description: Manage Alerting Contact points in Grafana name: alert_contact_point namespace: '' version_added: 0.0.1 alert_notification_policy: - description: Sets the notification policy tree in Alerting on Grafana Cloud + description: Manage Alerting Policies points in Grafana name: alert_notification_policy namespace: '' version_added: 0.0.1 @@ -37,17 +37,17 @@ plugins: namespace: '' version_added: 0.0.1 dashboard: - description: Manage Dashboards in Grafana Cloud + description: Manage Dashboards in Grafana name: dashboard namespace: '' version_added: 0.0.1 datasource: - description: Manage Data sources in Grafana Cloud + description: Manage Data sources in Grafana name: datasource namespace: '' version_added: 0.0.1 folder: - description: Manage Folders in Grafana Cloud + description: Manage Folders in Grafana name: folder namespace: '' version_added: 0.0.1 @@ -56,4 +56,4 @@ plugins: strategy: {} test: {} vars: {} -version: 1.1.1 +version: 2.2.5 diff --git a/ansible_collections/grafana/grafana/changelogs/changelog.yaml b/ansible_collections/grafana/grafana/changelogs/changelog.yaml index 080753dba..c915cd788 100644 --- a/ansible_collections/grafana/grafana/changelogs/changelog.yaml +++ b/ansible_collections/grafana/grafana/changelogs/changelog.yaml @@ -46,8 +46,8 @@ releases: changes: minor_changes: - Add a fail method to modules source code if `requests` library is not present - - Fixed markup for arg option in Documenation - - Updated Documenation with `notes` to specify if the check_mode feature is + - Fixed markup for arg option in Documentation + - Updated Documentation with `notes` to specify if the check_mode feature is supported by modules - removed `supports_check_mode=True` from source code of modules release_date: '2022-10-20' @@ -79,5 +79,162 @@ releases: changes: minor_changes: - Updated the return message in grafana.grafana.folder module - release_summary: Updated return description and value for grafana.grafana.folder module + release_summary: Updated return description and value for grafana.grafana.folder + module release_date: '2023-02-08' + 2.0.0: + changes: + major_changes: + - Added Lint support + - Configs for server, metrics, logs, traces, and integrations + - Installation of the latest version + - Local installations when internet connection is not allowed + - Only download binary to controller once instead of hosts + - Skip install if the agent is already installed and the version is the same + as the requested version + - Support for Grafana Agent Flow + - Validation of variables + release_summary: Updated Grafana Agent Role + release_date: '2023-03-27' + 2.1.0: + changes: + major_changes: + - Addition of Grafana Server role by @gardar + - Configurable agent user groups by @NormanJS + - Grafana Plugins support on-prem Grafana installation by @ishanjainn + - Updated Service for flow mode by @bentonam + minor_changes: + - Ability to configure date format in grafana server role by @RomainMou + - Avoid using shell for fetching latest version in Grafana Agent Role by @gardar + - Fix for invalid yaml with datasources list enclosed in quotes by @elkozmon + - Remove agent installation custom check by @VLZZZ + - Remove explicit user creation check by @v-zhuravlev + release_summary: Add Grafana Server role and plugins support on-prem Grafana + release_date: '2023-06-26' + 2.1.1: + changes: + minor_changes: + - Update Download tasks in Grafana Agent Role + release_summary: Update Download tasks in Grafana Agent Role + release_date: '2023-06-26' + 2.1.2: + changes: + minor_changes: + - Fix Deleting datasources + - Fix alert_notification_policy failing on fresh instance + - Making Deleting folders idempotent + - Remove trailing slash automatically from grafana_url + release_summary: Idempotency Updates and minor api_url fixes + release_date: '2023-06-27' + 2.1.3: + changes: + minor_changes: + - indentation and Lint fixes to modules + release_summary: Update modules to fix failing Sanity Tests + release_date: '2023-06-27' + 2.1.4: + changes: + minor_changes: + - Datasource test updates and minor fixes + release_summary: Update Datasource Tests and minor fixes + release_date: '2023-06-27' + 2.1.5: + changes: + minor_changes: + - Add Grafana Agent Version and CPU Arch to Downloaded ZIP in Grafana Agent + Role + - Move _grafana_agent_base_download_url from /vars to /defaults in Grafana Agent + Role + release_summary: Update Grafana Agent Download varibale and ZIP file + release_date: '2023-08-10' + 2.1.6: + changes: + minor_changes: + - Add overrides.conf with CAP_NET_BIND_SERVICE for grafana-server unit + - Fix Grafana Dashboard Import for Grafana Role + - Make grafana_agent Idempotent + - Provisioning errors in YAML + - Use new standard to configure Grafana APT source for Grafana Role + release_summary: Grafana and Grafana Agent role updates + release_date: '2023-09-11' + 2.1.7: + changes: + minor_changes: + - YAML Fixes + release_summary: YAML Fixes + release_date: '2023-09-11' + 2.1.8: + changes: + minor_changes: + - Fix grafana dashboard import in Grafana Role + release_summary: Fix grafana dashboard import in Grafana Role + release_date: '2023-09-12' + 2.1.9: + changes: + minor_changes: + - Add check for Curl and failure step if Agent Version is not retrieved + - Bump cryptography from 39.0.2 to 41.0.3 + - Bump semver from 5.7.1 to 5.7.2 + - Bump word-wrap from 1.2.3 to 1.2.5 + - Create local dashboard directory in check mode + - Update CI Testing + - Update Cloud Stack Module failures + release_summary: Security Updates and Grafana Agent Version failure fixes + release_date: '2023-09-19' + 2.2.0: + changes: + minor_changes: + - Use 'ansible_system' env variable to detect os typ in Grafana Agent Role + - hange grafana Agent Wal and Positions Directory in Grafana Agent Role + release_summary: Grafana Agent Role Updates + release_date: '2023-09-20' + 2.2.1: + changes: + minor_changes: + - Allow alert resource provisioning in Grafana Role + release_summary: Allow alert resource provisioning in Grafana Role + release_date: '2023-09-27' + 2.2.2: + changes: + minor_changes: + - Bump cryptography from 41.0.3 to 41.0.4 + - Create missing notification directory in Grafana Role + - Remove check_mode from create local directory task in Grafana Role + release_summary: Grafana Role bug fixes and security updates + release_date: '2023-09-29' + 2.2.3: + changes: + minor_changes: + - Remove dependency on local-fs.target from Grafana Agent role + release_summary: Remove dependency on local-fs.target from Grafana Agent role + release_date: '2023-10-05' + 2.2.4: + changes: + minor_changes: + - Bump cryptography from 41.0.4 to 41.0.6 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/126 + - Drop curl check by @v-zhuravlev in https://github.com/grafana/grafana-ansible-collection/pull/120 + - Fix check mode for grafana role by @Boschung-Mecatronic-AG-Infrastructure + in https://github.com/grafana/grafana-ansible-collection/pull/125 + - Fix check mode in Grafana Agent by @AmandaCameron in https://github.com/grafana/grafana-ansible-collection/pull/124 + - Update tags in README by @ishanjainn in https://github.com/grafana/grafana-ansible-collection/pull/121 + release_summary: Grafana and Agent Role bug fixes and security updates + release_date: '2023-12-08' + 2.2.5: + changes: + minor_changes: + - Add 'run_once' to download&unzip tasks by @v-zhuravlev in https://github.com/grafana/grafana-ansible-collection/pull/136 + - Adding `oauth_allow_insecure_email_lookup` to fix oauth user sync error by @hypery2k in https://github.com/grafana/grafana-ansible-collection/pull/132 + - Bump ansible-core from 2.15.4 to 2.15.8 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/137 + - Bump ansible-lint from 6.13.1 to 6.14.3 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/139 + - Bump ansible-lint from 6.14.3 to 6.22.2 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/142 + - Bump ansible-lint from 6.22.2 to 24.2.0 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/150 + - Bump jinja2 from 3.1.2 to 3.1.3 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/129 + - Bump pylint from 2.16.2 to 3.0.3 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/141 + - Bump yamllint from 1.29.0 to 1.33.0 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/140 + - Bump yamllint from 1.29.0 to 1.33.0 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/143 + - Bump yamllint from 1.33.0 to 1.34.0 by @dependabot in https://github.com/grafana/grafana-ansible-collection/pull/151 + - Change handler to systemd by @v-zhuravlev in https://github.com/grafana/grafana-ansible-collection/pull/135 + - Fix links in grafana_agent/defaults/main.yaml by @PabloCastellano in https://github.com/grafana/grafana-ansible-collection/pull/134 + - Topic/grafana agent idempotency by @ohdearaugustin in https://github.com/grafana/grafana-ansible-collection/pull/147 + release_summary: Grafana and Agent Role bug fixes and security updates + release_date: '2024-02-13' diff --git a/ansible_collections/grafana/grafana/changelogs/config.yaml b/ansible_collections/grafana/grafana/changelogs/config.yaml index 75f9be3e9..8710b513f 100644 --- a/ansible_collections/grafana/grafana/changelogs/config.yaml +++ b/ansible_collections/grafana/grafana/changelogs/config.yaml @@ -1,3 +1,4 @@ +--- changelog_filename_template: ../CHANGELOG.rst changelog_filename_version_depth: 0 changes_file: changelog.yaml @@ -11,22 +12,22 @@ prelude_section_name: release_summary prelude_section_title: Release Summary sanitize_changelog: true sections: -- - major_changes - - Major Changes -- - minor_changes - - Minor Changes -- - breaking_changes - - Breaking Changes / Porting Guide -- - deprecated_features - - Deprecated Features -- - removed_features - - Removed Features (previously deprecated) -- - security_fixes - - Security Fixes -- - bugfixes - - Bugfixes -- - known_issues - - Known Issues + - - major_changes + - Major Changes + - - minor_changes + - Minor Changes + - - breaking_changes + - Breaking Changes / Porting Guide + - - deprecated_features + - Deprecated Features + - - removed_features + - Removed Features (previously deprecated) + - - security_fixes + - Security Fixes + - - bugfixes + - Bugfixes + - - known_issues + - Known Issues title: Grafana.Grafana trivial_section_name: trivial use_fqcn: true diff --git a/ansible_collections/grafana/grafana/examples/agent-basic-no-options.yaml b/ansible_collections/grafana/grafana/examples/agent-basic-no-options.yaml new file mode 100644 index 000000000..7ccc5fb7d --- /dev/null +++ b/ansible_collections/grafana/grafana/examples/agent-basic-no-options.yaml @@ -0,0 +1,10 @@ +--- +- hosts: all + become: true + # pre_tasks happen before roles are executed / applied + pre_tasks: [] + # roles are ran after pre_tasks + roles: + - grafana_agent + # tasks are ran after roles + tasks: [] diff --git a/ansible_collections/grafana/grafana/examples/agent-send-to-grafana-cloud.yaml b/ansible_collections/grafana/grafana/examples/agent-send-to-grafana-cloud.yaml new file mode 100644 index 000000000..f90dda9f0 --- /dev/null +++ b/ansible_collections/grafana/grafana/examples/agent-send-to-grafana-cloud.yaml @@ -0,0 +1,95 @@ +--- +- hosts: all + become: true + vars: + grafana_agent_metrics_config: + global: + external_labels: + datacenter: primary + cluster: my-cluster + instance: "{{ ansible_host }}" + remote_write: + - url: https://prometheus-.grafana.net/api/prom/push + basic_auth: + username: "1234567" # your username / instanceID + password: "..." # your grafana.com token + configs: + - name: local + scrape_configs: + # scrape a an application on the localhost + - job_name: my-app + metrics_path: /metrics + static_configs: + - targets: + - localhost:8080 + relabel_configs: [] + metric_relabel_configs: [] + + grafana_agent_logs_config: + global: + clients: + - url: https://logs-.grafana.net/loki/api/v1/push + basic_auth: + username: "1234567" # your username / instanceID + password: "..." # your grafana.com token + configs: + - name: local + positions: + filename: /tmp/positions.yaml + target_config: + sync_period: 10s + scrape_configs: + # scrape all of the log files in /var/log on the localhost + - job_name: log-files + static_configs: + - targets: + - localhost + labels: + job: var-logs + instance: "{{ ansible_host }}" + __path__: /var/log/*.log + # scrape all of the journal logs on localhost + - job_name: systemd-journal + journal: + max_age: 12h + labels: + job: systemd-journal + relabel_configs: + - source_labels: + - __journal__systemd_unit + target_label: systemd_unit + - source_labels: + - __journal__hostname + target_label: hostname + - source_labels: + - __journal_syslog_identifier + target_label: syslog_identifier + - source_labels: + - __journal__pid + target_label: pid + - source_labels: + - __journal__uid + target_label: uid + - source_labels: + - __journal__transport + target_label: transport + grafana_agent_integrations_config: + scrape_integrations: true + # get metrics about the agent + agent: + enabled: true + relabel_configs: [] + metric_relabel_configs: [] + # get node exporter metrics + node_exporter: + enabled: true + relabel_configs: [] + metric_relabel_configs: [] + + # pre_tasks happen before roles are executed / applied + pre_tasks: [] + # roles are ran after pre_tasks + roles: + - grafana_agent + # tasks are ran after roles + tasks: [] diff --git a/ansible_collections/grafana/grafana/examples/ansible.cfg b/ansible_collections/grafana/grafana/examples/ansible.cfg new file mode 100644 index 000000000..f0e70e2b4 --- /dev/null +++ b/ansible_collections/grafana/grafana/examples/ansible.cfg @@ -0,0 +1,32 @@ +[defaults] +# (string) Sets the macro for the 'ansible_managed' variable available for :ref:`ansible_collections.ansible.builtin.template_module` and :ref:`ansible_collections.ansible.windows.win_template_module`. This is only relevant for those two modules. +ansible_managed="Ansible managed file. Be wary of possible overwrites." + +# (boolean) Toggle to control the showing of deprecation warnings +deprecation_warnings=False + +# (boolean) Set this to "False" if you want to avoid host key checking by the underlying tools Ansible uses to connect to the host +host_key_checking=False + +# (pathlist) Comma separated list of Ansible inventory sources +inventory=hosts + +# (pathspec) Colon separated paths in which Ansible will search for Modules. +library=../plugins/modules + +# (path) File to which Ansible will log on the controller. When empty logging is disabled. +log_path=./ansible.log + +# (pathspec) Colon separated paths in which Ansible will search for Roles. +roles_path=../roles + +[ssh_connection] + +# ssh arguments to use +# Leaving off ControlPersist will result in poor performance, so use +# paramiko on older platforms rather than removing it +ssh_args = -o ControlMaster=auto -o ControlPersist=60s + +# if True, make ansible use scp if the connection type is ssh +# (default is sftp) +scp_if_ssh = True diff --git a/ansible_collections/grafana/grafana/examples/monitor-multiple-instances.md b/ansible_collections/grafana/grafana/examples/monitor-multiple-instances.md new file mode 100644 index 000000000..d624c7ec4 --- /dev/null +++ b/ansible_collections/grafana/grafana/examples/monitor-multiple-instances.md @@ -0,0 +1,184 @@ +# Monitoring multiple Linux hosts with Grafana Agent Role + +Monitoring with Grafana Agents across multiple Linux hosts can be difficult. +To make it easier, you can use the Grafana Agent role with the Grafana Ansible collection. +This guide shows how to use the `grafana_agent` Ansible role to deploy and manage Grafana Agents across multiple Linux hosts so you can monitor them in Grafana. + +## Before you begin + +Before you begin, you should have: + +- Linux hosts +- SSH access to the Linux hosts +- Account permissions sufficient to install and use Grafana Agent on the Linux hosts + +## Install the Grafana Ansible collection + +The [Grafana Agent role](https://github.com/grafana/grafana-ansible-collection/tree/main/roles/grafana_agent) is available in the Grafana Ansible collection as of the 1.1.0 release. + +To install the Grafana Ansible collection, run this command: + +``` +ansible-galaxy collection install grafana.grafana:2.0.0 +``` + +## Create an Ansible inventory file + +Next, you will set up your hosts and create an inventory file. + +1. Create your hosts and add public SSH keys to them. + + This example uses eight Linux hosts: two Ubuntu hosts, two CentOS hosts, two Fedora hosts, and two Debian hosts. + +1. Create an Ansible inventory file. + + The Ansible inventory, which resides in a file named `inventory`, looks similar to this: + + ``` + 146.190.208.216 # hostname = ubuntu-01 + 146.190.208.190 # hostname = ubuntu-02 + 137.184.155.128 # hostname = centos-01 + 146.190.216.129 # hostname = centos-02 + 198.199.82.174 # hostname = debian-01 + 198.199.77.93 # hostname = debian-02 + 143.198.182.156 # hostname = fedora-01 + 143.244.174.246 # hostname = fedora-02 + ``` + + > **Note**: If you are copying the above file, remove the comments (#). + +1. Create an `ansible.cfg` file within the same directory as `inventory`, with the following values: + ``` + [defaults] + inventory = inventory # Path to the inventory file + private_key_file = ~/.ssh/id_rsa # Path to my private SSH Key + remote_user=root + ``` + +## Use the Grafana Agent Ansible role + +Next you will create an Ansible playbook that calls the `grafana_agent` role from the `grafana.grafana` Ansible collection. + +To use the Grafana Agent Ansible role: + +1. Create a file named `deploy-agent.yml` in the same directory as `ansible.cfg` and `inventory` and add the configuration below. + + ```yaml + - name: Install Grafana Agent + hosts: all + become: true + + vars: + grafana_cloud_api_key: # Example - eyJrIjoiYjI3NjI5MGQxZTcyOTIxYTc0MDgzMGVhNDhlODNhYzA5OTk2Y2U5YiIsIm4iOiJhbnNpYmxldGVzdCIsImlkIjo2NTI5 + metrics_username: # Example - 825019 + logs_username: # Example - 411478 + prometheus_url: # Example - https://prometheus-us-central1.grafana.net/api/prom/push + loki_url: # Example - https://logs-prod-017.grafana.net/loki/api/v1/push + tasks: + - name: Install Grafana Agent + ansible.builtin.include_role: + name: grafana.grafana.grafana_agent + vars: + grafana_agent_metrics_config: + configs: + - name: integrations + remote_write: + - basic_auth: + password: "{{ grafana_cloud_api_key }}" + username: "{{ metrics_username }}" + url: "{{ prometheus_url }}" + + global: + scrape_interval: 60s + wal_directory: /tmp/grafana-agent-wal + + grafana_agent_logs_config: + configs: + - name: default + clients: + - basic_auth: + password: "{{ grafana_cloud_api_key }}" + username: "{{ logs_username }}" + url: "{{ loki_url }}" + positions: + filename: /tmp/positions.yaml + target_config: + sync_period: 10s + scrape_configs: + - job_name: varlogs + static_configs: + - targets: [localhost] + labels: + instance: ${HOSTNAME:-default} + job: varlogs + __path__: /var/log/*log + grafana_agent_integrations_config: + node_exporter: + enabled: true + instance: ${HOSTNAME:-default} + prometheus_remote_write: + - basic_auth: + password: "{{ grafana_cloud_api_key }}" + username: "{{ metrics_username }}" + url: "{{ prometheus_url }}" + ``` + + The playbook calls the `grafana_agent` role from the `grafana.grafana` Ansible collection. + The Agent configuration in this playbook send metrics and logs from the linux hosts to your Prometheus and Loki data sources. + + Refer to the [Grafana Ansible documentation](https://github.com/grafana/grafana-ansible-collection/tree/main/roles/grafana_agent#role-variables) to understand the other variables you can pass to the `grafana_agent` role. + + When deploying the Agent across multiple instances for monitoring them, It is essential that the Agent is able to auto-detect the hostname for ease in monitoring. + Notice that the label `instance` has been set to the value `${HOSTNAME:-default}`, which is substituted by the value of the HOSTNAME environment variable in the Linux host. + To read more about the variable substitution, refer to the Grafana Agent [node_exporter_config](https://grafana.com/docs/agent/latest/configuration/integrations/node-exporter-config/) documentation. + +1. To run the playbook, run this command: + + ``` + ansible-playbook deploy-agent.yml + ``` + + > **Note:** You can place the `deploy-agent.yml`, `ansible.cfg` and `inventory` files in different directories based on your needs. + +## Check that logs and metrics are being ingested into Prometheus and Loki + +Logs and metrics will soon be available in Grafana if your Promtheus and Loki datasources are added. +To test this, use the Explore feature. +Click the Explore icon (compass icon) in the vertical navigation bar. + +### Check logs + +To check logs: + +1. Use the dropdown menu at the top of the page to select your Loki logs data source. + +1. In the log browser, run the query `{instance="centos-01"}` where centos-01 is the hostname of one of the Linux hosts. + + If you see log lines (shown in the example below), logs are being received. + + ![Logs](https://grafana.com/static/assets/img/blog/ansible-to-manage-agent1.png) + + If no log lines appear, logs are not being collected. + +### Check metrics + +To check metrics: + +1. Use the dropdown menu at the top of the page to select your Prometheus data source. + +1. Run the query `{instance="centos-01"}` where centos-01 is the hostname of one of the Linux hosts. + + If you see a metrics graph and table (shown in the example below), metrics are being received. + + ![Metrics](https://grafana.com/static/assets/img/blog/ansible-to-manage-agent2.png) + + If no metrics appear, metrics are not being collected. + +### View dashboards + +Now that you have logs and metrics in Grafana, you can use dashboards to view them. +Here's an example of one of the prebuilt dashboards included with the Linux integration in Grafana Cloud: + +![Dashboard](https://grafana.com/static/assets/img/blog/ansible-to-manage-agent3.png) + +Using the **Instance** dropdown in the dashboard, you can select from the hostnames where you deployed Grafana Agent and start monitoring them. diff --git a/ansible_collections/grafana/grafana/meta/runtime.yml b/ansible_collections/grafana/grafana/meta/runtime.yml index 89a0a2bf3..08867faed 100644 --- a/ansible_collections/grafana/grafana/meta/runtime.yml +++ b/ansible_collections/grafana/grafana/meta/runtime.yml @@ -1,2 +1,2 @@ --- -requires_ansible: '>=2.11' +requires_ansible: ">=2.12.0,<3.0.0" diff --git a/ansible_collections/grafana/grafana/package.json b/ansible_collections/grafana/grafana/package.json new file mode 100644 index 000000000..556b3f236 --- /dev/null +++ b/ansible_collections/grafana/grafana/package.json @@ -0,0 +1,26 @@ +{ + "name": "grafana-ansible-collection", + "version": "2.1.4", + "description": "", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/grafana/grafana-ansible-collection.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/grafana/grafana-ansible-collection/issues" + }, + "homepage": "https://github.com/grafana/grafana-ansible-collection#readme", + "dependencies": { + "editorconfig-checker": "^5.0.1", + "markdownlint-cli2": "^0.6.0", + "textlint": "^12.5.1", + "textlint-rule-common-misspellings": "^1.0.1", + "textlint-rule-no-todo": "^2.0.1", + "textlint-rule-terminology": "^3.0.4" + } +} diff --git a/ansible_collections/grafana/grafana/plugins/modules/alert_contact_point.py b/ansible_collections/grafana/grafana/plugins/modules/alert_contact_point.py index b38cb936d..f6fab42fe 100644 --- a/ansible_collections/grafana/grafana/plugins/modules/alert_contact_point.py +++ b/ansible_collections/grafana/grafana/plugins/modules/alert_contact_point.py @@ -12,7 +12,7 @@ module: alert_contact_point author: - Ishan Jain (@ishanjainn) version_added: "0.0.1" -short_description: Manage Alerting Contact points in Grafana Cloud +short_description: Manage Alerting Contact points in Grafana description: - Create, Update and delete Contact points using Ansible. requirements: [ "requests >= 1.0.0" ] @@ -49,14 +49,14 @@ options: - Grafana API Key used to authenticate with Grafana. type: str required : true - stack_slug: + grafana_url: description: - - Name of the Grafana Cloud stack to which the contact points will be added. + - URL of the Grafana instance. type: str required: true state: description: - - State for the Grafana Cloud stack. + - State for the Grafana Alert Contact Point. choices: [ present, absent ] type: str default: present @@ -68,10 +68,9 @@ EXAMPLES = ''' name: ops-email uid: opsemail type: email - settings: { - addresses: "ops@mydomain.com,devs@mydomain.com" - } - stack_slug: "{{ stack_slug }}" + settings: + addresses: "ops@mydomain.com,devs@mydomain.com" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: present @@ -80,10 +79,9 @@ EXAMPLES = ''' name: ops-email uid: opsemail type: email - settings: { - addresses: "ops@mydomain.com,devs@mydomain.com" - } - stack_slug: "{{ stack_slug }}" + settings: + addresses: "ops@mydomain.com,devs@mydomain.com" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: absent ''' @@ -141,7 +139,11 @@ def present_alert_contact_point(module): 'settings': module.params['settings'], 'DisableResolveMessage': module.params['disableResolveMessage'] } - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/v1/provisioning/contact-points' + + if module.params['grafana_url'][-1] == '/': + module.params['grafana_url'] = module.params['grafana_url'][:-1] + + api_url = module.params['grafana_url'] + '/api/v1/provisioning/contact-points' result = requests.post(api_url, json=body, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) @@ -151,7 +153,7 @@ def present_alert_contact_point(module): sameConfig = False contactPointInfo = {} - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/v1/provisioning/contact-points' + api_url = module.params['grafana_url'] + '/api/v1/provisioning/contact-points' result = requests.get(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) @@ -166,13 +168,12 @@ def present_alert_contact_point(module): if sameConfig: return False, False, contactPointInfo else: - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/v1/provisioning/contact-points/' + \ - module.params['uid'] + api_url = module.params['grafana_url'] + '/api/v1/provisioning/contact-points/' + module.params['uid'] result = requests.put(api_url, json=body, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) if result.status_code == 202: - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/v1/provisioning/contact-points' + api_url = module.params['grafana_url'] + '/api/v1/provisioning/contact-points' result = requests.get(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) @@ -187,7 +188,11 @@ def present_alert_contact_point(module): def absent_alert_contact_point(module): already_exists = False - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/v1/provisioning/contact-points' + + if module.params['grafana_url'][-1] == '/': + module.params['grafana_url'] = module.params['grafana_url'][:-1] + + api_url = module.params['grafana_url'] + '/api/v1/provisioning/contact-points' result = requests.get(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) @@ -195,8 +200,7 @@ def absent_alert_contact_point(module): if contact_points['uid'] == module.params['uid']: already_exists = True if already_exists: - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/v1/provisioning/contact-points/' + \ - module.params['uid'] + api_url = module.params['grafana_url'] + '/api/v1/provisioning/contact-points/' + module.params['uid'] result = requests.delete(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) @@ -215,7 +219,7 @@ def main(): type=dict(type='str', required=True), settings=dict(type='dict', required=True), disableResolveMessage=dict(type='bool', required=False, default=False), - stack_slug=dict(type='str', required=True), + grafana_url=dict(type='str', required=True), grafana_api_key=dict(type='str', required=True, no_log=True), state=dict(type='str', required=False, default='present', choices=['present', 'absent']) ) diff --git a/ansible_collections/grafana/grafana/plugins/modules/alert_notification_policy.py b/ansible_collections/grafana/grafana/plugins/modules/alert_notification_policy.py index f01a798e0..651786654 100644 --- a/ansible_collections/grafana/grafana/plugins/modules/alert_notification_policy.py +++ b/ansible_collections/grafana/grafana/plugins/modules/alert_notification_policy.py @@ -12,7 +12,7 @@ module: alert_notification_policy author: - Ishan Jain (@ishanjainn) version_added: "0.0.1" -short_description: Sets the notification policy tree in Alerting on Grafana Cloud +short_description: Manage Alerting Policies points in Grafana description: - Set the notification policy tree using Ansible. requirements: [ "requests >= 1.0.0" ] @@ -71,9 +71,9 @@ options: - Sets the waiting time to resend an alert after they have successfully been sent. type: str default: 4h - stack_slug: + grafana_url: description: - - Name of the Grafana Cloud stack to which the notification policies will be added. + - URL of the Grafana instance. type: str required: true grafana_api_key: @@ -86,7 +86,7 @@ options: EXAMPLES = ''' - name: Set Notification policy tree grafana.grafana.alert_notification_policy: - stack_slug: "{{ stack_slug }}" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" routes: [ { @@ -113,7 +113,7 @@ EXAMPLES = ''' object_matchers: [["env", "=", "Staging"]] } ] - stack_slug: "{{ stack_slug }}" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" ''' @@ -178,15 +178,26 @@ def alert_notification_policy(module): 'group_wait': module.params['groupWait'], 'object_matchers': module.params['objectMatchers'], 'repeat_interval': module.params['repeatInterval']} - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/v1/provisioning/policies' + if module.params['grafana_url'][-1] == '/': + module.params['grafana_url'] = module.params['grafana_url'][:-1] + + api_url = module.params['grafana_url'] + '/api/v1/provisioning/policies' result = requests.get(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) - if (result.json()['receiver'] == module.params['rootPolicyReceiver'] and result.json()['routes'] == module.params['routes'] - and result.json()['group_wait'] == module.params['groupWait'] and result.json()['group_interval'] == module.params['groupInterval'] - and result.json()['repeat_interval'] == module.params['repeatInterval']): + if 'routes' not in result.json(): + api_url = module.params['grafana_url'] + '/api/v1/provisioning/policies' + result = requests.put(api_url, json=body, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) + + if result.status_code == 202: + return False, True, result.json() + else: + return True, False, {"status": result.status_code, 'response': result.json()['message']} + elif (result.json()['receiver'] == module.params['rootPolicyReceiver'] and result.json()['routes'] == module.params['routes'] + and result.json()['group_wait'] == module.params['groupWait'] and result.json()['group_interval'] == module.params['groupInterval'] + and result.json()['repeat_interval'] == module.params['repeatInterval']): return False, False, result.json() else: - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/v1/provisioning/policies' + api_url = module.params['grafana_url'] + '/api/v1/provisioning/policies' result = requests.put(api_url, json=body, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) @@ -207,7 +218,7 @@ def main(): groupWait=dict(type='str', required=False, default='30s'), repeatInterval=dict(type='str', required=False, default='4h'), objectMatchers=dict(type='list', required=False, default=[], elements='dict'), - stack_slug=dict(type='str', required=True), + grafana_url=dict(type='str', required=True), grafana_api_key=dict(type='str', required=True, no_log=True), ) module = AnsibleModule(argument_spec=module_args) diff --git a/ansible_collections/grafana/grafana/plugins/modules/cloud_api_key.py b/ansible_collections/grafana/grafana/plugins/modules/cloud_api_key.py index b7c358eca..85372c96d 100644 --- a/ansible_collections/grafana/grafana/plugins/modules/cloud_api_key.py +++ b/ansible_collections/grafana/grafana/plugins/modules/cloud_api_key.py @@ -47,7 +47,7 @@ options: default: True state: description: - - State for the Grafana Cloud stack. + - State for the Grafana Cloud API Key. type: str default: present choices: [ present, absent ] diff --git a/ansible_collections/grafana/grafana/plugins/modules/cloud_plugin.py b/ansible_collections/grafana/grafana/plugins/modules/cloud_plugin.py index a6399b644..9383beb05 100644 --- a/ansible_collections/grafana/grafana/plugins/modules/cloud_plugin.py +++ b/ansible_collections/grafana/grafana/plugins/modules/cloud_plugin.py @@ -41,7 +41,7 @@ options: required : true state: description: - - State for the Grafana Cloud stack. + - State for the Grafana Cloud Plugin. type: str default: present choices: [ present, absent ] diff --git a/ansible_collections/grafana/grafana/plugins/modules/dashboard.py b/ansible_collections/grafana/grafana/plugins/modules/dashboard.py index df8bb33ea..a2531981d 100644 --- a/ansible_collections/grafana/grafana/plugins/modules/dashboard.py +++ b/ansible_collections/grafana/grafana/plugins/modules/dashboard.py @@ -12,7 +12,7 @@ module: dashboard author: - Ishan Jain (@ishanjainn) version_added: "0.0.1" -short_description: Manage Dashboards in Grafana Cloud +short_description: Manage Dashboards in Grafana description: - Create, Update and delete Dashboards using Ansible. requirements: [ "requests >= 1.0.0" ] @@ -25,9 +25,9 @@ options: - JSON source code for dashboard. type: dict required: true - stack_slug: + grafana_url: description: - - Name of the Grafana Cloud stack to which the dashboard will be added. + - URL of the Grafana instance. type: str required: true grafana_api_key: @@ -37,7 +37,7 @@ options: required : true state: description: - - State for the Grafana Cloud stack. + - State for the Grafana Dashboard. choices: [ present, absent ] default: present type: str @@ -47,14 +47,14 @@ EXAMPLES = ''' - name: Create/Update a dashboard grafana.grafana.dashboard: dashboard: "{{ lookup('ansible.builtin.file', 'dashboard.json') }}" - stack_slug: "{{ stack_slug }}" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: present - name: Delete dashboard grafana.grafana.dashboard: dashboard: "{{ lookup('ansible.builtin.file', 'dashboard.json') }}" - stack_slug: "{{ stack_slug }}" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: absent ''' @@ -120,7 +120,10 @@ __metaclass__ = type def present_dashboard(module): - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/dashboards/db' + if module.params['grafana_url'][-1] == '/': + module.params['grafana_url'] = module.params['grafana_url'][:-1] + + api_url = module.params['grafana_url'] + '/api/dashboards/db' result = requests.post(api_url, json=module.params['dashboard'], headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) @@ -131,10 +134,13 @@ def present_dashboard(module): def absent_dashboard(module): + if module.params['grafana_url'][-1] == '/': + module.params['grafana_url'] = module.params['grafana_url'][:-1] + if 'uid' not in module.params['dashboard']['dashboard']: return True, False, "UID is not defined in the the Dashboard configuration" - api_url = api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/dashboards/uid/' + module.params['dashboard']['dashboard']['uid'] + api_url = api_url = module.params['grafana_url'] + '/api/dashboards/uid/' + module.params['dashboard']['dashboard']['uid'] result = requests.delete(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) @@ -148,7 +154,7 @@ def main(): module_args = dict( dashboard=dict(type='dict', required=True), - stack_slug=dict(type='str', required=True), + grafana_url=dict(type='str', required=True), grafana_api_key=dict(type='str', required=True, no_log=True), state=dict(type='str', required=False, default='present', choices=['present', 'absent']) ) diff --git a/ansible_collections/grafana/grafana/plugins/modules/datasource.py b/ansible_collections/grafana/grafana/plugins/modules/datasource.py index 3c9d150bc..91ae8f20d 100644 --- a/ansible_collections/grafana/grafana/plugins/modules/datasource.py +++ b/ansible_collections/grafana/grafana/plugins/modules/datasource.py @@ -12,7 +12,7 @@ module: datasource author: - Ishan Jain (@ishanjainn) version_added: "0.0.1" -short_description: Manage Data sources in Grafana Cloud +short_description: Manage Data sources in Grafana description: - Create, Update and delete Data sources using Ansible. requirements: [ "requests >= 1.0.0" ] @@ -25,9 +25,9 @@ options: - JSON source code for the Data source. type: dict required: true - stack_slug: + grafana_url: description: - - Name of the Grafana Cloud stack to which the data source will be added. + - URL of the Grafana instance. type: str required: true grafana_api_key: @@ -37,7 +37,7 @@ options: required : true state: description: - - State for the Grafana Cloud stack. + - State for the Grafana Datasource. choices: [ present, absent ] default: present type: str @@ -46,15 +46,27 @@ options: EXAMPLES = ''' - name: Create/Update Data sources grafana.grafana.datasource: - dataSource: "{{ lookup('ansible.builtin.file', 'datasource.json') }}" - stack_slug: "{{ stack_slug }}" + dataSource: | + { + "name": "Prometheus", + "type": "prometheus", + "access": "proxy", + "url": "http://localhost:9090", + "jsonData": { + "httpMethod": "POST", + "manageAlerts": true, + "prometheusType": "Prometheus", + "cacheLevel": "High" + } + } + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: present - name: Delete Data sources grafana.grafana.datasource: dataSource: "{{ lookup('ansible.builtin.file', 'datasource.json') }}" - stack_slug: "{{ stack_slug }}" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: absent ''' @@ -119,17 +131,20 @@ __metaclass__ = type def present_datasource(module): - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/datasources' + if module.params['grafana_url'][-1] == '/': + module.params['grafana_url'] = module.params['grafana_url'][:-1] + + api_url = module.params['grafana_url'] + '/api/datasources' result = requests.post(api_url, json=module.params['dataSource'], headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) if result.status_code == 200: return False, True, result.json() elif result.status_code == 409: - get_id_url = requests.get('https://' + module.params['stack_slug'] + '.grafana.net/api/datasources/id/' + module.params['dataSource']['name'], + get_id_url = requests.get(module.params['grafana_url'] + '/api/datasources/id/' + module.params['dataSource']['name'], headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/datasources/' + str(get_id_url.json()['id']) + api_url = module.params['grafana_url'] + '/api/datasources/' + str(get_id_url.json()['id']) result = requests.put(api_url, json=module.params['dataSource'], headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) @@ -143,12 +158,15 @@ def present_datasource(module): def absent_datasource(module): - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/datasources/' + module.params['dataSource']['name'] + if module.params['grafana_url'][-1] == '/': + module.params['grafana_url'] = module.params['grafana_url'][:-1] + + api_url = module.params['grafana_url'] + '/api/datasources/name/' + module.params['dataSource']['name'] result = requests.delete(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) if result.status_code == 200: - return False, True, result.json() + return False, True, {"status": result.status_code, 'response': result.json()['message']} else: return True, False, {"status": result.status_code, 'response': result.json()['message']} @@ -157,7 +175,7 @@ def main(): module_args = dict( dataSource=dict(type='dict', required=True), - stack_slug=dict(type='str', required=True), + grafana_url=dict(type='str', required=True), grafana_api_key=dict(type='str', required=True, no_log=True), state=dict(type='str', required=False, default='present', choices=['present', 'absent']) ) diff --git a/ansible_collections/grafana/grafana/plugins/modules/folder.py b/ansible_collections/grafana/grafana/plugins/modules/folder.py index 165f34f2a..74db63d0c 100644 --- a/ansible_collections/grafana/grafana/plugins/modules/folder.py +++ b/ansible_collections/grafana/grafana/plugins/modules/folder.py @@ -12,7 +12,7 @@ module: folder author: - Ishan Jain (@ishanjainn) version_added: "0.0.1" -short_description: Manage Folders in Grafana Cloud +short_description: Manage Folders in Grafana description: - Create, Update and delete Folders via Ansible. requirements: [ "requests >= 1.0.0" ] @@ -40,14 +40,14 @@ options: - Grafana API Key to authenticate with Grafana. type: str required : true - stack_slug: + grafana_url: description: - - Name of the Grafana Cloud stack to which the folder will be added. + - URL of the Grafana instance. type: str required: true state: description: - - State for the Grafana Cloud stack. + - State for the Grafana Folder. choices: [ present, absent ] default: present type: str @@ -59,14 +59,14 @@ EXAMPLES = ''' title: folder_name uid: folder_name overwrite: true - stack_slug: "{{ stack_slug }}" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: present - name: Delete a Folder in Grafana grafana.grafana.folder: uid: folder_name - stack_slug: "{{ stack_slug }}" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: absent ''' @@ -165,11 +165,14 @@ __metaclass__ = type def present_folder(module): + if module.params['grafana_url'][-1] == '/': + module.params['grafana_url'] = module.params['grafana_url'][:-1] + body = { 'uid': module.params['uid'], 'title': module.params['title'], } - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/folders' + api_url = module.params['grafana_url'] + '/api/folders' result = requests.post(api_url, json=body, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) @@ -179,7 +182,7 @@ def present_folder(module): sameConfig = False folderInfo = {} - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/folders' + api_url = module.params['grafana_url'] + '/api/folders' result = requests.get(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) for folder in result.json(): @@ -195,7 +198,7 @@ def present_folder(module): 'title': module.params['title'], 'overwrite': module.params['overwrite'] } - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/folders/' + module.params['uid'] + api_url = module.params['grafana_url'] + '/api/folders/' + module.params['uid'] result = requests.put(api_url, json=body, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) @@ -208,14 +211,28 @@ def present_folder(module): def absent_folder(module): - api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/folders/' + module.params['uid'] + if module.params['grafana_url'][-1] == '/': + module.params['grafana_url'] = module.params['grafana_url'][:-1] - result = requests.delete(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) + sameConfig = False - if result.status_code == 200: - return False, True, {"status": result.status_code, 'response': "Folder has been succesfuly deleted"} + api_url = module.params['grafana_url'] + '/api/folders' + result = requests.get(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) + + for folder in result.json(): + if folder['uid'] == module.params['uid'] and folder['title'] == module.params['title']: + sameConfig = True + if sameConfig is True: + api_url = module.params['grafana_url'] + '/api/folders/' + module.params['uid'] + + result = requests.delete(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']}) + + if result.status_code == 200: + return False, True, {"status": result.status_code, 'response': "Folder has been succesfuly deleted"} + else: + return True, False, {"status": result.status_code, 'response': "Error deleting folder"} else: - return True, False, {"status": result.status_code, 'response': "Error deleting folder"} + return False, True, {"status": 200, 'response': "Folder does not exist"} def main(): @@ -224,7 +241,7 @@ def main(): title=dict(type='str', required=True), uid=dict(type='str', required=True), overwrite=dict(type='bool', required=False, default=True), - stack_slug=dict(type='str', required=True), + grafana_url=dict(type='str', required=True), grafana_api_key=dict(type='str', required=True, no_log=True), state=dict(type='str', required=False, default='present', choices=['present', 'absent']) ) diff --git a/ansible_collections/grafana/grafana/requirements.txt b/ansible_collections/grafana/grafana/requirements.txt new file mode 100644 index 000000000..aff353eae --- /dev/null +++ b/ansible_collections/grafana/grafana/requirements.txt @@ -0,0 +1,3 @@ +yamllint==1.33.0 +ansible-lint>=6.13.1, <7.0.0 +pylint>=2.16.2,<3.0.0 diff --git a/ansible_collections/grafana/grafana/requirements.yml b/ansible_collections/grafana/grafana/requirements.yml new file mode 100644 index 000000000..c1917b408 --- /dev/null +++ b/ansible_collections/grafana/grafana/requirements.yml @@ -0,0 +1,6 @@ +--- +collections: + - name: https://github.com/ansible-collections/community.general.git + type: git + - name: https://github.com/ansible-collections/community.grafana.git + type: git diff --git a/ansible_collections/grafana/grafana/roles/grafana/README.md b/ansible_collections/grafana/grafana/roles/grafana/README.md new file mode 100644 index 000000000..eb00b3f25 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/README.md @@ -0,0 +1,142 @@ +

grafana logo

+ +# Ansible Role: grafana.grafana.grafana + +[![License](https://img.shields.io/badge/license-MIT%20License-brightgreen.svg)](https://opensource.org/licenses/MIT) + +Provision and manage [Grafana](https://github.com/grafana/grafana) - platform for analytics and monitoring + +## Requirements + +- Ansible >= 2.9 (It might work on previous versions, but we cannot guarantee it) +- libselinux-python on deployer host (only when deployer machine has SELinux) +- Grafana >= 5.1 (for older Grafana versions use this role in version 0.10.1 or earlier) +- jmespath on deployer machine. If you are using Ansible from a Python virtualenv, install *jmespath* to the same virtualenv via pip. + +## Role Variables + +All variables which can be overridden are stored in [defaults/main.yml](defaults/main.yml) file as well as in table below. + +| Name | Default Value | Description | +| -------------- | ------------- | -----------------------------------| +| `grafana_use_provisioning` | true | Use Grafana provisioning capability when possible (**grafana_version=latest will assume >= 5.0**). | +| `grafana_provisioning_synced` | false | Ensure no previously provisioned dashboards are kept if not referenced anymore. | +| `grafana_version` | latest | Grafana package version | +| `grafana_manage_repo` | true | Manage package repository (or don't) | +| `grafana_yum_repo` | https://packages.grafana.com/oss/rpm | Yum repository URL | +| `grafana_yum_key` | https://packages.grafana.com/gpg.key | Yum repository gpg key | +| `grafana_rhsm_subscription` | | rhsm subscription name (redhat subscription-manager) | +| `grafana_rhsm_repo` | | rhsm repository name (redhat subscription-manager) | +| `grafana_apt_release_channel` | stable | Apt release chanel (stable or beta) | +| `grafana_apt_arch` | {{ 'arm64' if ansible_architecture == 'aarch64' else 'amd64' }} | Apt architecture | +| `grafana_apt_repo` | deb [arch={{ grafana_apt_arch }} signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com/ {{ grafana_apt_release_channel }} main | Apt repository string | +| `grafana_apt_key` | https://apt.grafana.com/gpg.key | Apt repository gpg key | +| `grafana_instance` | {{ ansible_fqdn \| default(ansible_host) \| default(inventory_hostname) }} | Grafana instance name | +| `grafana_logs_dir` | /var/log/grafana | Path to logs directory | +| `grafana_data_dir` | /var/lib/grafana | Path to database directory | +| `grafana_address` | 0.0.0.0 | Address on which Grafana listens | +| `grafana_port` | 3000 | port on which Grafana listens | +| `grafana_cap_net_bind_service` | false | Enables the use of ports below 1024 without root privileges by leveraging the 'capabilities' of the linux kernel. read: http://man7.org/linux/man-pages/man7/capabilities.7.html | +| `grafana_url` | "http://{{ grafana_address }}:{{ grafana_port }}" | Full URL used to access Grafana from a web browser | +| `grafana_api_url` | "{{ grafana_url }}" | URL used for API calls in provisioning if different from public URL. See [this issue](https://github.com/cloudalchemy/ansible-grafana/issues/70). | +| `grafana_domain` | "{{ ansible_fqdn \| default(ansible_host) \| default('localhost') }}" | setting is only used in as a part of the `root_url` option. Useful when using GitHub or Google OAuth | +| `grafana_server` | { protocol: http, enforce_domain: false, socket: "", cert_key: "", cert_file: "", enable_gzip: false, static_root_path: public, router_logging: false } | [server](http://docs.grafana.org/installation/configuration/#server) configuration section | +| `grafana_security` | { admin_user: admin, admin_password: "" } | [security](http://docs.grafana.org/installation/configuration/#security) configuration section | +| `grafana_database` | { type: sqlite3 } | [database](http://docs.grafana.org/installation/configuration/#database) configuration section | +| `grafana_welcome_email_on_sign_up` | false | Send welcome email after signing up | +| `grafana_users` | { allow_sign_up: false, auto_assign_org_role: Viewer, default_theme: dark } | [users](http://docs.grafana.org/installation/configuration/#users) configuration section | +| `grafana_auth` | {} | [authorization](http://docs.grafana.org/installation/configuration/#auth) configuration section | +| `grafana_ldap` | {} | [ldap](http://docs.grafana.org/installation/ldap/) configuration section. group_mappings are expanded, see defaults for example | +| `grafana_session` | {} | [session](http://docs.grafana.org/installation/configuration/#session) management configuration section | +| `grafana_analytics` | {} | Google [analytics](http://docs.grafana.org/installation/configuration/#analytics) configuration section | +| `grafana_smtp` | {} | [smtp](http://docs.grafana.org/installation/configuration/#smtp) configuration section | +| `grafana_alerting` | {} | [alerting](http://docs.grafana.org/installation/configuration/#alerting) configuration section | +| `grafana_log` | {} | [log](http://docs.grafana.org/installation/configuration/#log) configuration section | +| `grafana_metrics` | {} | [metrics](http://docs.grafana.org/installation/configuration/#metrics) configuration section | +| `grafana_tracing` | {} | [tracing](http://docs.grafana.org/installation/configuration/#tracing) configuration section | +| `grafana_snapshots` | {} | [snapshots](http://docs.grafana.org/installation/configuration/#snapshots) configuration section | +| `grafana_image_storage` | {} | [image storage](http://docs.grafana.org/installation/configuration/#external-image-storage) configuration section | +| `grafana_date_formats` | {} | [date formats](http://docs.grafana.org/installation/configuration/#date_formats) configuration section | +| `grafana_dashboards` | [] | List of dashboards which should be imported | +| `grafana_dashboards_dir` | "dashboards" | Path to a local directory containing dashboards files in `json` format | +| `grafana_datasources` | [] | List of datasources which should be configured | +| `grafana_environment` | {} | Optional Environment param for Grafana installation, useful ie for setting http_proxy | +| `grafana_plugins` | [] | List of Grafana plugins which should be installed | +| `grafana_alert_notifications` | [] | List of alert notification channels to be created, updated, or deleted | + +Data source example: + +```yaml +grafana_datasources: + - name: prometheus + type: prometheus + access: proxy + url: 'http://{{ prometheus_web_listen_address }}' + basicAuth: false +``` + +Dashboard example: + +```yaml +grafana_dashboards: + - dashboard_id: 111 + revision_id: 1 + datasource: prometheus +``` + +Alert notification channel example: + +**NOTE**: setting the variable `grafana_alert_notifications` will only come into +effect when `grafana_use_provisioning` is `true`. That means the new +provisioning system using config files, which is available starting from Grafana +v5.0, needs to be in use. + +```yaml +grafana_alert_notifications: + notifiers: + - name: Channel 1 + type: email + uid: channel1 + is_default: false + send_reminder: false + settings: + addresses: "example@example.com" + autoResolve: true + delete_notifiers: + - name: Channel 2 + uid: channel2 +``` + +## Supported CPU Architectures + +Historically packages were taken from different channels according to CPU architecture. Specifically, armv6/armv7 and aarch64/arm64 packages were via [unofficial packages distributed by fg2it](https://github.com/fg2it/grafana-on-raspberry). Now that Grafana publishes official ARM builds, all packages are taken from the official [Debian/Ubuntu](http://docs.grafana.org/installation/debian/#installing-on-debian-ubuntu) or [RPM](http://docs.grafana.org/installation/rpm/) packages. + +## Example + +### Playbook + +Fill in the admin password field with your choice, the Grafana web page won't ask to change it at the first login. + +```yaml +- hosts: all + roles: + - role: grafana.grafana.grafana + vars: + grafana_security: + admin_user: admin + admin_password: enter_your_secure_password +``` + + +## Local Testing + +The preferred way of locally testing the role is to use Docker and [molecule](https://github.com/ansible-community/molecule). You will have to install Docker on your system. + +For more information about molecule go to their [docs](http://molecule.readthedocs.io/en/latest/). + +## License + +This project is licensed under MIT License. See [LICENSE](/LICENSE) for more details. + +## Credits +This role was migrated from [cloudalchemy.grafana](https://github.com/cloudalchemy/ansible-grafana). diff --git a/ansible_collections/grafana/grafana/roles/grafana/defaults/main.yml b/ansible_collections/grafana/grafana/roles/grafana/defaults/main.yml new file mode 100644 index 000000000..12f3d7cc7 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/defaults/main.yml @@ -0,0 +1,278 @@ +--- +grafana_version: latest +grafana_manage_repo: true + +grafana_yum_repo: "https://packages.grafana.com/oss/rpm" +grafana_yum_key: "https://packages.grafana.com/gpg.key" + +grafana_rhsm_subscription: "" +grafana_rhsm_repo: "" + +grafana_apt_release_channel: stable +grafana_apt_arch: "{{ 'arm64' if ansible_architecture == 'aarch64' else 'amd64' }}" +grafana_apt_repo: "deb [arch={{ grafana_apt_arch }} signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com/ {{ grafana_apt_release_channel }} main" +grafana_apt_key: "https://apt.grafana.com/gpg.key" + +# Should we use the provisioning capability when possible (provisioning require grafana >= 5.0) +grafana_use_provisioning: true + +# Should the provisioning be kept synced. If true, previous provisioned objects will be removed if not referenced anymore. +grafana_provisioning_synced: false + +grafana_instance: "{{ ansible_fqdn | default(ansible_host) | default(inventory_hostname) }}" + +grafana_logs_dir: "/var/log/grafana" +grafana_data_dir: "/var/lib/grafana" + +grafana_address: "0.0.0.0" +grafana_port: 3000 +# To enable the use of ports below 1024 for unprivileged processes linux needs to set CAP_NET_BIND_SERVICE. +# This has some security implications, and should be a conscious choice. +# Get informed by reading: http://man7.org/linux/man-pages/man7/capabilities.7.html +grafana_cap_net_bind_service: false + +# External Grafana address. Variable maps to "root_url" in grafana server section +grafana_url: "http://{{ grafana_address }}:{{ grafana_port }}" +grafana_api_url: "{{ grafana_url }}" +grafana_domain: "{{ ansible_fqdn | default(ansible_host) | default('localhost') }}" + +# Additional options for grafana "server" section +# This section WILL omit options for: http_addr, http_port, domain, and root_url, as those settings are set by variables listed before +grafana_server: + protocol: http + enforce_domain: false + socket: "" + cert_key: "" + cert_file: "" + enable_gzip: false + static_root_path: public + router_logging: false + serve_from_sub_path: false + +# Variables correspond to ones in grafana.ini configuration file +# Security +grafana_security: + admin_user: admin + admin_password: "" +# secret_key: "" +# login_remember_days: 7 +# cookie_username: grafana_user +# cookie_remember_name: grafana_remember +# disable_gravatar: true +# data_source_proxy_whitelist: + +# Database setup +grafana_database: + type: sqlite3 +# host: 127.0.0.1:3306 +# name: grafana +# user: root +# password: "" +# url: "" +# ssl_mode: disable +# path: grafana.db +# max_idle_conn: 2 +# max_open_conn: "" +# log_queries: "" + +# Remote cache +grafana_remote_cache: {} + +# User management and registration +grafana_welcome_email_on_sign_up: false +grafana_users: + allow_sign_up: false + # allow_org_create: true + # auto_assign_org: true + auto_assign_org_role: Viewer + # login_hint: "email or username" + default_theme: dark + # external_manage_link_url: "" + # external_manage_link_name: "" + # external_manage_info: "" + +# grafana authentication mechanisms +grafana_auth: {} +# disable_login_form: false +# oauth_auto_login: false +# disable_signout_menu: false +# signout_redirect_url: "" +# anonymous: +# org_name: "Main Organization" +# org_role: Viewer +# ldap: +# config_file: "/etc/grafana/ldap.toml" +# allow_sign_up: false +# basic: +# enabled: true + +grafana_ldap: {} +# verbose_logging: false +# servers: +# host: 127.0.0.1 +# port: 389 # 636 for SSL +# use_ssl: false +# start_tls: false +# ssl_skip_verify: false +# root_ca_cert: /path/to/certificate.crt +# bind_dn: "cn=admin,dc=grafana,dc=org" +# bind_password: grafana +# search_filter: "(cn=%s)" # "(sAMAccountName=%s)" on AD +# search_base_dns: +# - "dc=grafana,dc=org" +# group_search_filter: "(&(objectClass=posixGroup)(memberUid=%s))" +# group_search_base_dns: +# - "ou=groups,dc=grafana,dc=org" +# attributes: +# name: givenName +# surname: sn +# username: sAMAccountName +# member_of: memberOf +# email: mail +# group_mappings: +# - name: Main Org. +# id: 1 +# groups: +# - group_dn: "cn=admins,ou=groups,dc=grafana,dc=org" +# org_role: Admin +# - group_dn: "cn=editors,ou=groups,dc=grafana,dc=org" +# org_role: Editor +# - group_dn: "*" +# org_role: Viewer +# - name: Alternative Org +# id: 2 +# groups: +# - group_dn: "cn=alternative_admins,ou=groups,dc=grafana,dc=org" +# org_role: Admin + +grafana_session: {} +# provider: file +# provider_config: "sessions" + +grafana_analytics: {} +# reporting_enabled: true +# google_analytics_ua_id: "" + +# Set this for mail notifications +grafana_smtp: {} +# host: +# user: +# password: +# from_address: + +# Enable grafana alerting mechanism +grafana_alerting: + execute_alerts: true +# error_or_timeout: 'alerting' +# nodata_or_nullvalues: 'no_data' +# concurrent_render_limit: 5 + +# Grafana logging configuration +grafana_log: +# mode: 'console file' +# level: info + +# Internal grafana metrics system +grafana_metrics: {} +# interval_seconds: 10 +# graphite: +# address: "localhost:2003" +# prefix: "prod.grafana.%(instance_name)s" + +# Distributed tracing options +grafana_tracing: {} +# address: "localhost:6831" +# always_included_tag: "tag1:value1,tag2:value2" +# sampler_type: const +# sampler_param: 1 + +grafana_snapshots: {} +# external_enabled: true +# external_snapshot_url: "https://snapshots-origin.raintank.io" +# external_snapshot_name: "Publish to snapshot.raintank.io" +# snapshot_remove_expired: true +# snapshot_TTL_days: 90 + +# External image store +grafana_image_storage: {} +# provider: gcs +# key_file: +# bucket: +# path: + +# Date format +grafana_date_formats: {} +# full_date: "DD-MM-YYYY HH:mm:ss" +# interval_second: "HH:mm:ss" +# interval_minute: "HH:mm" +# interval_hour: "DD/MM HH:mm" +# interval_day: "DD/MM" +# interval_month: "MM-YYYY" +# interval_year: "YYYY" +# use_browser_locale: true +# default_timezone: "browser" + +####### +# Plugins from https://grafana.com/plugins +grafana_plugins: [] +# - raintank-worldping-app + +# Dashboards from https://grafana.com/dashboards +grafana_dashboards: [] +# - dashboard_id: '4271' +# revision_id: '3' +# datasource: 'Prometheus' +# - dashboard_id: '1860' +# revision_id: '4' +# datasource: 'Prometheus' +# - dashboard_id: '358' +# revision_id: '1' +# datasource: 'Prometheus' + +grafana_dashboards_dir: "dashboards" + +# Alert notification channels to configure +grafana_alert_notifications: [] +# - name: "Email Alert" +# type: "email" +# uid: channel1 +# is_default: true +# settings: +# addresses: "example@example.com" + +# Alert resources channels to configure +grafana_alert_resources: {} + +# Datasources to configure +grafana_datasources: [] +# - name: "Prometheus" +# type: "prometheus" +# access: "proxy" +# url: "http://prometheus.mydomain" +# basicAuth: true +# basicAuthUser: "admin" +# basicAuthPassword: "password" +# isDefault: true +# jsonData: +# tlsAuth: false +# tlsAuthWithCACert: false +# tlsSkipVerify: true + +# API keys to configure +grafana_api_keys: [] +# - name: "admin" +# role: "Admin" +# - name: "viewer" +# role: "Viewer" +# - name: "editor" +# role: "Editor" + +# The location where the keys should be stored. +grafana_api_keys_dir: "{{ lookup('env', 'HOME') }}/grafana/keys" + +grafana_environment: {} + +# Panels configurations +grafana_panels: {} +# disable_sanitize_html: false +# enable_alpha: false diff --git a/ansible_collections/grafana/grafana/roles/grafana/handlers/main.yml b/ansible_collections/grafana/grafana/roles/grafana/handlers/main.yml new file mode 100644 index 000000000..d457b426b --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/handlers/main.yml @@ -0,0 +1,28 @@ +--- +- name: "Restart grafana" + ansible.builtin.service: + name: grafana-server + state: restarted + become: true + listen: "restart_grafana" + tags: + - grafana_run + +- name: "Set privileges on provisioned dashboards" + ansible.builtin.file: + path: "{{ grafana_data_dir }}/dashboards" + recurse: true + owner: "grafana" + group: "grafana" + mode: "0640" + become: true + listen: "provisioned dashboards changed" + +- name: "Set privileges on provisioned dashboards directory" + ansible.builtin.file: + path: "{{ grafana_data_dir }}/dashboards" + state: "directory" + recurse: false + mode: "0755" + become: true + listen: "provisioned dashboards changed" diff --git a/ansible_collections/grafana/grafana/roles/grafana/meta/main.yml b/ansible_collections/grafana/grafana/roles/grafana/meta/main.yml new file mode 100644 index 000000000..564b8bcc5 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/meta/main.yml @@ -0,0 +1,31 @@ +--- +galaxy_info: + author: "Grafana" + description: "Grafana - platform for analytics and monitoring" + license: "MIT" + min_ansible_version: "2.9" + platforms: + - name: Ubuntu + versions: + - bionic + - xenial + - name: Debian + versions: + - stretch + - buster + - name: EL + versions: + - "7" + - "8" + - name: Fedora + versions: + - "30" + - "31" + galaxy_tags: + - grafana + - dashboard + - alerts + - alerting + - presentation + - monitoring + - metrics diff --git a/ansible_collections/grafana/grafana/roles/grafana/molecule/alternative/converge.yml b/ansible_collections/grafana/grafana/roles/grafana/molecule/alternative/converge.yml new file mode 100644 index 000000000..56e1ba894 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/molecule/alternative/converge.yml @@ -0,0 +1,105 @@ +--- +- name: "Run role" + hosts: all + any_errors_fatal: true + roles: + - grafana.grafana.grafana + vars: + grafana_version: 6.2.5 + grafana_security: + admin_user: admin + admin_password: "password" + grafana_address: "127.0.0.1" + grafana_auth: + login_maximum_inactive_lifetime_days: 42 + disable_login_form: false + oauth_auto_login: false + disable_signout_menu: false + signout_redirect_url: "" + anonymous: + org_name: "Main Organization" + org_role: Viewer + ldap: + config_file: "/etc/grafana/ldap.toml" + allow_sign_up: false + basic: + enabled: true + grafana_ldap: + verbose_logging: false + servers: + host: 127.0.0.1 + port: 389 + use_ssl: false + start_tls: false + ssl_skip_verify: false + root_ca_cert: /path/to/certificate.crt + bind_dn: "cn=admin,dc=grafana,dc=org" + bind_password: grafana + search_filter: "(cn=%s)" + search_base_dns: + - "dc=grafana,dc=org" + group_search_filter: "(&(objectClass=posixGroup)(memberUid=%s))" + group_search_base_dns: + - "ou=groups,dc=grafana,dc=org" + attributes: + name: givenName + surname: sn + username: sAMAccountName + member_of: memberOf + email: mail + group_mappings: + - name: "Main Organization" + id: 1 + groups: + - group_dn: "cn=admins,ou=groups,dc=grafana,dc=org" + org_role: Admin + - group_dn: "cn=editors,ou=groups,dc=grafana,dc=org" + org_role: Editor + - group_dn: "*" + org_role: Viewer + - name: "Alternative Org" + id: 2 + groups: + - group_dn: "cn=alternative_admins,ou=groups,dc=grafana,dc=org" + org_role: Admin + grafana_api_keys: + - name: "admin" + role: "Admin" + - name: "viewer" + role: "Viewer" + - name: "editor" + role: "Editor" + grafana_api_keys_dir: "/tmp/grafana/keys" + grafana_plugins: + - raintank-worldping-app + grafana_alert_notifications: + notifiers: + - name: "Email Alert" + type: "email" + uid: notifier1 + is_default: true + settings: + addresses: "example@example.com" + grafana_dashboards: + - dashboard_id: '1860' + revision_id: '4' + datasource: 'Prometheus' + - dashboard_id: '358' + revision_id: '1' + datasource: 'Prometheus' + grafana_datasources: + - name: "Prometheus" + type: "prometheus" + access: "proxy" + url: "http://prometheus.mydomain" + basicAuth: true + basicAuthUser: "admin" + basicAuthPassword: "password" + isDefault: true + jsonData: + tlsAuth: false + tlsAuthWithCACert: false + tlsSkipVerify: true + grafana_log: + mode: syslog + level: warn diff --git a/ansible_collections/grafana/grafana/roles/grafana/molecule/alternative/molecule.yml b/ansible_collections/grafana/grafana/roles/grafana/molecule/alternative/molecule.yml new file mode 100644 index 000000000..ed97d539c --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/molecule/alternative/molecule.yml @@ -0,0 +1 @@ +--- diff --git a/ansible_collections/grafana/grafana/roles/grafana/molecule/alternative/tests/test_alternative.py b/ansible_collections/grafana/grafana/roles/grafana/molecule/alternative/tests/test_alternative.py new file mode 100644 index 000000000..cf6476b0d --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/molecule/alternative/tests/test_alternative.py @@ -0,0 +1,52 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import testinfra.utils.ansible_runner + +testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( + os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all') + + +def test_directories(host): + dirs = [ + "/etc/grafana", + "/var/log/grafana", + "/var/lib/grafana", + "/var/lib/grafana/dashboards", + "/var/lib/grafana/plugins", + "/var/lib/grafana/plugins/raintank-worldping-app" + ] + files = [ + "/etc/grafana/grafana.ini", + "/etc/grafana/ldap.toml" + ] + for directory in dirs: + d = host.file(directory) + assert d.is_directory + assert d.exists + for file in files: + f = host.file(file) + assert f.exists + assert f.is_file + + +def test_service(host): + s = host.service("grafana-server") + # assert s.is_enabled + assert s.is_running + + +def test_packages(host): + p = host.package("grafana") + assert p.is_installed + assert p.version == "6.2.5" + + +def test_socket(host): + assert host.socket("tcp://127.0.0.1:3000").is_listening + + +def test_custom_auth_option(host): + f = host.file("/etc/grafana/grafana.ini") + assert f.contains("login_maximum_inactive_lifetime_days = 42") diff --git a/ansible_collections/grafana/grafana/roles/grafana/molecule/default/converge.yml b/ansible_collections/grafana/grafana/roles/grafana/molecule/default/converge.yml new file mode 100644 index 000000000..3d76ca1bc --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/molecule/default/converge.yml @@ -0,0 +1,10 @@ +--- +- name: "Run role" + hosts: all + any_errors_fatal: true + roles: + - grafana.grafana.grafana + vars: + grafana_security: + admin_user: "admin" + admin_password: "password" diff --git a/ansible_collections/grafana/grafana/roles/grafana/molecule/default/molecule.yml b/ansible_collections/grafana/grafana/roles/grafana/molecule/default/molecule.yml new file mode 100644 index 000000000..ed97d539c --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/molecule/default/molecule.yml @@ -0,0 +1 @@ +--- diff --git a/ansible_collections/grafana/grafana/roles/grafana/molecule/default/tests/test_default.py b/ansible_collections/grafana/grafana/roles/grafana/molecule/default/tests/test_default.py new file mode 100644 index 000000000..67363a3a9 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/molecule/default/tests/test_default.py @@ -0,0 +1,50 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import testinfra.utils.ansible_runner + +testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( + os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all') + + +def test_directories(host): + dirs = [ + "/etc/grafana", + "/var/log/grafana", + "/var/lib/grafana", + "/var/lib/grafana/dashboards", + "/var/lib/grafana/plugins" + ] + files = [ + "/etc/grafana/grafana.ini" + ] + for directory in dirs: + d = host.file(directory) + assert d.is_directory + assert d.exists + for file in files: + f = host.file(file) + assert f.exists + assert f.is_file + + +def test_service(host): + s = host.service("grafana-server") + # assert s.is_enabled + assert s.is_running + + +def test_packages(host): + p = host.package("grafana") + assert p.is_installed + + +def test_socket(host): + assert host.socket("tcp://0.0.0.0:3000").is_listening + + +def test_yum_repo(host): + if host.system_info.distribution in ['centos', 'redhat', 'fedora']: + f = host.file("/etc/yum.repos.d/grafana.repo") + assert f.exists diff --git a/ansible_collections/grafana/grafana/roles/grafana/tasks/api_keys.yml b/ansible_collections/grafana/grafana/roles/grafana/tasks/api_keys.yml new file mode 100644 index 000000000..d6ca94b6d --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/tasks/api_keys.yml @@ -0,0 +1,43 @@ +--- +- name: "Ensure grafana key directory exists" + ansible.builtin.file: + path: "{{ grafana_api_keys_dir }}/{{ inventory_hostname }}" + state: directory + mode: "0755" + become: false + delegate_to: localhost + +- name: "Check api key list" + ansible.builtin.uri: + url: "{{ grafana_api_url }}/api/auth/keys" + user: "{{ grafana_security.admin_user }}" + password: "{{ grafana_security.admin_password }}" + force_basic_auth: true + return_content: true + register: __existing_api_keys + no_log: "{{ 'false' if lookup('env', 'CI') else 'true' }}" + +- name: "Create grafana api keys" + ansible.builtin.uri: + url: "{{ grafana_api_url }}/api/auth/keys" + user: "{{ grafana_security.admin_user }}" + password: "{{ grafana_security.admin_password }}" + force_basic_auth: true + method: POST + body_format: json + body: "{{ item | to_json }}" + loop: "{{ grafana_api_keys }}" + register: __new_api_keys + no_log: "{{ 'false' if lookup('env', 'CI') else 'true' }}" + when: "((__existing_api_keys['json'] | selectattr('name', 'equalto', item['name'])) | list) | length == 0" + +- name: "Create api keys file to allow the keys to be seen and used by other automation" + ansible.builtin.copy: + dest: "{{ grafana_api_keys_dir }}/{{ inventory_hostname }}/{{ item['item']['name'] }}.key" + content: "{{ item['json']['key'] }}" + backup: false + mode: "0644" + loop: "{{ __new_api_keys['results'] }}" + become: false + delegate_to: localhost + when: "item['json'] is defined" diff --git a/ansible_collections/grafana/grafana/roles/grafana/tasks/configure.yml b/ansible_collections/grafana/grafana/roles/grafana/tasks/configure.yml new file mode 100644 index 000000000..ac45615bc --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/tasks/configure.yml @@ -0,0 +1,106 @@ +--- +- name: "Ensure grafana directories exist" + ansible.builtin.file: + path: "{{ item.path }}" + state: "directory" + owner: "{{ item.owner | default('root') }}" + group: "{{ item.group | default('grafana') }}" + mode: "{{ item.mode | default('0755') }}" + loop: + - path: "/etc/grafana" + - path: "/etc/grafana/datasources" + - path: "/etc/grafana/provisioning" + - path: "/etc/grafana/provisioning/datasources" + - path: "/etc/grafana/provisioning/dashboards" + - path: "/etc/grafana/provisioning/notifiers" + - path: "/etc/grafana/provisioning/notification" + - path: "/etc/grafana/provisioning/plugins" + - path: "{{ grafana_logs_dir }}" + owner: grafana + - path: "{{ grafana_data_dir }}" + owner: grafana + - path: "{{ grafana_data_dir }}/dashboards" + owner: grafana + - path: "{{ grafana_data_dir }}/plugins" + owner: grafana + +- name: "Create grafana main configuration file" + ansible.builtin.template: + src: "grafana.ini.j2" + dest: "/etc/grafana/grafana.ini" + owner: "root" + group: "grafana" + mode: "0640" + no_log: "{{ 'false' if lookup('env', 'CI') else 'true' }}" + notify: restart_grafana + +- name: "Create grafana LDAP configuration file" + ansible.builtin.template: + src: "ldap.toml.j2" + dest: "{{ grafana_auth.ldap.config_file | default('/etc/grafana/ldap.toml') }}" + owner: "root" + group: "grafana" + mode: "0640" + no_log: "{{ 'false' if lookup('env', 'CI') else 'true' }}" + notify: restart_grafana + when: + - "'ldap' in grafana_auth" + - "'enabled' not in grafana_auth.ldap or grafana_auth.ldap.enabled" + +- name: "Enable grafana socket" + when: + - "grafana_server.protocol is defined and grafana_server.protocol == 'socket'" + - "grafana_server.socket | dirname != '/var/run'" + block: + - name: "Create grafana socket directory" + ansible.builtin.file: + path: "{{ grafana_server.socket | dirname }}" + state: "directory" + mode: "0775" + owner: "grafana" + group: "grafana" + + - name: "Ensure grafana socket directory created on startup" + ansible.builtin.template: + src: "tmpfiles.j2" + dest: "/etc/tmpfiles.d/grafana.conf" + owner: "root" + group: "root" + mode: "0644" + +- name: "Enable grafana to ports lower than port 1024" + community.general.capabilities: + path: /usr/sbin/grafana-server + capability: CAP_NET_BIND_SERVICE+ep + state: present + when: + - "grafana_port | int <= 1024" + - "grafana_cap_net_bind_service" + +- name: Create a directory for overrides.conf unit file if it does not exist + ansible.builtin.file: + path: /etc/systemd/system/grafana-server.service.d + state: directory + mode: '0755' + when: + - "grafana_port | int <= 1024" + - "grafana_cap_net_bind_service" + +- name: "Enable grafana to ports lower than port 1024 in systemd unitfile" + ansible.builtin.blockinfile: + path: /etc/systemd/system/grafana-server.service.d/overrides.conf + create: true + block: | + [Service] + AmbientCapabilities=CAP_NET_BIND_SERVICE + CapabilityBoundingSet=CAP_NET_BIND_SERVICE + when: + - "grafana_port | int <= 1024" + - "grafana_cap_net_bind_service" + +- name: "Enable and start Grafana systemd unit" + ansible.builtin.systemd: + name: "grafana-server" + enabled: true + state: started + daemon_reload: true diff --git a/ansible_collections/grafana/grafana/roles/grafana/tasks/dashboards.yml b/ansible_collections/grafana/grafana/roles/grafana/tasks/dashboards.yml new file mode 100644 index 000000000..c3f154f7b --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/tasks/dashboards.yml @@ -0,0 +1,140 @@ +--- +- name: "Create local grafana dashboard directory" + become: false + delegate_to: localhost + run_once: true + ansible.builtin.tempfile: + state: directory + register: __tmp_dashboards + changed_when: false + +- name: "Download grafana.net dashboards" + become: false + delegate_to: localhost + run_once: true + when: "grafana_dashboards | length > 0" + block: + - name: "Download grafana dashboard from grafana.net to local directory" + ansible.builtin.get_url: + url: "https://grafana.com/api/dashboards/{{ item.dashboard_id }}/revisions/{{ item.revision_id }}/download" + dest: "{{ __tmp_dashboards.path }}/{{ item.dashboard_id }}.json" + mode: "0644" + register: __download_dashboards + until: "__download_dashboards is succeeded" + retries: 5 + delay: 2 + changed_when: false + loop: "{{ grafana_dashboards }}" + + # As noted in [1] an exported dashboard replaces the exporter's datasource + # name with a representative name, something like 'DS_GRAPHITE'. The name + # is different for each datasource plugin, but always begins with 'DS_'. + # In the rest of the data, the same name is used, but captured in braces, + # for example: '${DS_GRAPHITE}'. + # + # [1] http://docs.grafana.org/reference/export_import/#import-sharing-with-grafana-2-x-or-3-0 + # + # The data structure looks (massively abbreviated) something like: + # + # "name": "DS_GRAPHITE", + # "datasource": "${DS_GRAPHITE}", + # + # If we import the downloaded dashboard verbatim, it will not automatically + # be connected to the data source like we want it. The Grafana UI expects + # us to do the final connection by hand, which we do not want to do. + # So, in the below task we ensure that we replace instances of this string + # with the data source name we want. + # To make sure that we're not being too greedy with the regex replacement + # of the data source to use for each dashboard that's uploaded, we make the + # regex match very specific by using the following: + # + # 1. Literal boundaries for " on either side of the match. + # 2. Non-capturing optional group matches for the ${} bits which may, or + # or may not, be there.. + # 3. A case-sensitive literal match for DS . + # 4. A one-or-more case-sensitive match for the part that follows the + # underscore, with only A-Z, 0-9 and - or _ allowed. + # + # This regex can be tested and understood better by looking at the + # matches and non-matches in https://regex101.com/r/f4Gkvg/6 + + - name: "Set the correct data source name in the dashboard" + ansible.builtin.replace: + dest: "{{ __tmp_dashboards.path }}/{{ item.dashboard_id }}.json" + regexp: '"(?:\${)?DS_[A-Z0-9_-]+(?:})?"' + replace: '"{{ item.datasource }}"' + changed_when: false + loop: "{{ grafana_dashboards }}" + +- name: "Import grafana dashboards via api" + community.grafana.grafana_dashboard: + grafana_url: "{{ grafana_api_url }}" + grafana_user: "{{ grafana_security.admin_user }}" + grafana_password: "{{ grafana_security.admin_password }}" + path: "{{ item }}" + message: "Updated by ansible role {{ ansible_role_name }}" + state: present + overwrite: true + no_log: "{{ 'false' if lookup('env', 'CI') else 'true' }}" + with_fileglob: + - "{{ __tmp_dashboards.path }}/*" + - "{{ grafana_dashboards_dir }}/*.json" + when: "not grafana_use_provisioning" + +- name: "Import grafana dashboards through provisioning" + when: grafana_use_provisioning + block: + - name: "Create/Update dashboards file (provisioning)" + ansible.builtin.copy: + dest: "/etc/grafana/provisioning/dashboards/ansible.yml" + content: | + apiVersion: 1 + providers: + - name: 'default' + orgId: 1 + folder: '' + type: file + options: + path: "{{ grafana_data_dir }}/dashboards" + backup: false + owner: root + group: grafana + mode: "0640" + become: true + notify: restart_grafana + + - name: "Register previously copied dashboards" + ansible.builtin.find: + paths: "{{ grafana_data_dir }}/dashboards" + hidden: true + patterns: + - "*.json" + register: __dashboards_present + when: grafana_provisioning_synced + + - name: "Import grafana dashboards" + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ grafana_data_dir }}/dashboards/{{ item | basename }}" + mode: "0640" + with_fileglob: + - "{{ __tmp_dashboards.path }}/*" + - "{{ grafana_dashboards_dir }}/*.json" + become: true + register: __dashboards_copied + notify: "provisioned dashboards changed" + when: not ansible_check_mode + + - name: "Register present and copied dashboards list" + ansible.builtin.set_fact: + __dashboards_present_list: "{{ __dashboards_present | json_query('files[*].path') | default([]) }}" + __dashboards_copied_list: "{{ __dashboards_copied | json_query('results[*].dest') | default([]) }}" + when: not ansible_check_mode + + - name: "Remove dashboards not present on deployer machine (synchronize)" + ansible.builtin.file: + path: "{{ item }}" + state: absent + loop: "{{ __dashboards_present_list | difference(__dashboards_copied_list) }}" + become: true + when: grafana_provisioning_synced and not ansible_check_mode diff --git a/ansible_collections/grafana/grafana/roles/grafana/tasks/datasources.yml b/ansible_collections/grafana/grafana/roles/grafana/tasks/datasources.yml new file mode 100644 index 000000000..6fc56ed3c --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/tasks/datasources.yml @@ -0,0 +1,40 @@ +--- +- name: "Ensure datasources exist (via API)" + community.grafana.grafana_datasource: + grafana_url: "{{ grafana_api_url }}" + grafana_user: "{{ grafana_security.admin_user }}" + grafana_password: "{{ grafana_security.admin_password }}" + name: "{{ item.name }}" + url: "{{ item.url }}" + ds_type: "{{ item.type }}" + access: "{{ item.access | default(omit) }}" + is_default: "{{ item.isDefault | default(omit) }}" + basic_auth_user: "{{ item.basicAuthUser | default(omit) }}" + basic_auth_password: "{{ item.basicAuthPassword | default(omit) }}" + database: "{{ item.database | default(omit) }}" + user: "{{ item.user | default(omit) }}" + password: "{{ item.password | default(omit) }}" + aws_auth_type: "{{ item.aws_auth_type | default(omit) }}" + aws_default_region: "{{ item.aws_default_region | default(omit) }}" + aws_access_key: "{{ item.aws_access_key | default(omit) }}" + aws_secret_key: "{{ item.aws_secret_key | default(omit) }}" + aws_credentials_profile: "{{ item.aws_credentials_profile | default(omit) }}" + aws_custom_metrics_namespaces: "{{ item.aws_custom_metrics_namespaces | default(omit) }}" + loop: "{{ grafana_datasources }}" + when: "not grafana_use_provisioning" + +- name: "Create/Update datasources file (provisioning)" + ansible.builtin.copy: + dest: "/etc/grafana/provisioning/datasources/ansible.yml" + content: | + apiVersion: 1 + deleteDatasources: [] + datasources: + {{ grafana_datasources | to_nice_yaml }} + backup: false + owner: root + group: grafana + mode: 0640 + notify: restart_grafana + become: true + when: "grafana_use_provisioning" diff --git a/ansible_collections/grafana/grafana/roles/grafana/tasks/install.yml b/ansible_collections/grafana/grafana/roles/grafana/tasks/install.yml new file mode 100644 index 000000000..a83333219 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/tasks/install.yml @@ -0,0 +1,89 @@ +--- +- name: "Remove conflicting grafana packages" + ansible.builtin.package: + name: grafana-data + state: absent + +- name: "Install dependencies" + ansible.builtin.package: + name: "{{ _grafana_dependencies }}" + state: present + update_cache: true + when: "(_grafana_dependencies | default())" + +- name: "Prepare yum/dnf" + when: + - "ansible_pkg_mgr in ['yum', 'dnf']" + - "(grafana_manage_repo)" + environment: "{{ grafana_environment }}" + block: + - name: "Add Grafana yum/dnf repository" + ansible.builtin.yum_repository: + name: grafana + description: grafana + baseurl: "{{ grafana_yum_repo }}" + enabled: true + gpgkey: "{{ grafana_yum_key | default(omit) }}" + repo_gpgcheck: "{{ true if (grafana_yum_key) else omit }}" + gpgcheck: "{{ true if (grafana_yum_key) else omit }}" + when: "(not grafana_rhsm_repo)" + + - name: "Attach RHSM subscription" + when: "(grafana_rhsm_subscription)" + block: + - name: "Check if Grafana RHSM subscription is enabled" + ansible.builtin.command: + cmd: "subscription-manager list --consumed --matches={{ grafana_rhsm_subscription | quote }} --pool-only" + register: __subscription_manager_consumed + changed_when: false + when: (grafana_rhsm_subscription) + + - name: "Find RHSM repo subscription pool id" + ansible.builtin.command: + cmd: "subscription-manager list --available --matches={{ grafana_rhsm_subscription | quote }} --pool-only" + register: __subscription_manager_available + changed_when: false + when: + - "(grafana_rhsm_subscription)" + - "__subscription_manager_consumed.stdout | length <= 0" + + - name: "Attach RHSM subscription" + ansible.builtin.command: + cmd: "subscription-manager attach --pool={{ __subscription_manager_available.stdout }}" + register: __subscription_manager_attach + changed_when: "__subscription_manager_attach.stdout is search('Successfully attached a subscription')" + failed_when: "__subscription_manager_attach.stdout is search('could not be found')" + when: + - "(grafana_rhsm_subscription)" + - "__subscription_manager_consumed.stdout | default() | length <= 0" + - "__subscription_manager_available.stdout | default() | length > 0" + + - name: "Enable RHSM repository" + community.general.rhsm_repository: + name: "{{ grafana_rhsm_repo }}" + state: enabled + when: (grafana_rhsm_repo) + +- name: "Prepare apt" + when: + - "ansible_pkg_mgr == 'apt'" + - "(grafana_manage_repo)" + environment: "{{ grafana_environment }}" + block: + - name: "Import Grafana apt gpg key" + ansible.builtin.get_url: + url: "{{ grafana_apt_key }}" + dest: /usr/share/keyrings/grafana.key + mode: "0644" + + - name: "Add Grafana apt repository" + ansible.builtin.apt_repository: + repo: "{{ grafana_apt_repo }}" + state: present + update_cache: true + +- name: "Install Grafana" + ansible.builtin.package: + name: "{{ grafana_package }}" + state: "{{ (grafana_version == 'latest') | ternary('latest', 'present') }}" + notify: restart_grafana diff --git a/ansible_collections/grafana/grafana/roles/grafana/tasks/main.yml b/ansible_collections/grafana/grafana/roles/grafana/tasks/main.yml new file mode 100644 index 000000000..719e31a1f --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/tasks/main.yml @@ -0,0 +1,120 @@ +--- +- name: "Gather variables for each operating system" + ansible.builtin.include_vars: "{{ distrovars }}" + vars: + distrovars: "{{ lookup('first_found', params, errors='ignore') }}" + params: + skip: true + files: + - "{{ ansible_distribution | lower }}-{{ ansible_distribution_version | lower }}.yml" + - "{{ ansible_distribution | lower }}-{{ ansible_distribution_major_version | lower }}.yml" + - "{{ ansible_os_family | lower }}-{{ ansible_distribution_major_version | lower }}.yml" + - "{{ ansible_distribution | lower }}.yml" + - "{{ ansible_os_family | lower }}.yml" + paths: + - "vars/distro" + tags: + - grafana_install + - grafana_configure + - grafana_datasources + - grafana_notifications + - grafana_dashboards + +- name: Preflight + ansible.builtin.include_tasks: + file: preflight.yml + apply: + tags: + - grafana_install + - grafana_configure + - grafana_datasources + - grafana_notifications + - grafana_dashboards + +- name: Install + ansible.builtin.include_tasks: + file: install.yml + apply: + become: true + tags: + - grafana_install + +- name: Configure + ansible.builtin.include_tasks: + file: configure.yml + apply: + become: true + tags: + - grafana_configure + +- name: Plugins + ansible.builtin.include_tasks: + file: plugins.yml + apply: + tags: + - grafana_configure + when: "grafana_plugins != []" + +- name: "Restart grafana before configuring datasources and dashboards" + ansible.builtin.meta: flush_handlers + tags: + - grafana_install + - grafana_configure + - grafana_datasources + - grafana_notifications + - grafana_dashboards + - grafana_run + +- name: "Wait for grafana to start" + ansible.builtin.wait_for: + host: "{{ grafana_address if grafana_server.protocol is undefined or grafana_server.protocol in ['http', 'https'] else omit }}" + port: "{{ grafana_port if grafana_server.protocol is undefined or grafana_server.protocol in ['http', 'https'] else omit }}" + path: "{{ grafana_server.socket | default() if grafana_server.protocol is defined and grafana_server.protocol == 'socket' else omit }}" + tags: + - grafana_install + - grafana_configure + - grafana_datasources + - grafana_notifications + - grafana_dashboards + - grafana_run + +- name: "Api keys" + ansible.builtin.include_tasks: + file: api_keys.yml + apply: + tags: + - grafana_configure + - grafana_run + when: "grafana_api_keys | length > 0" + +- name: Datasources + ansible.builtin.include_tasks: + file: datasources.yml + apply: + tags: + - grafana_configure + - grafana_datasources + - grafana_run + when: "grafana_datasources != []" + +- name: Notifications + ansible.builtin.include_tasks: + file: notifications.yml + apply: + tags: + - grafana_configure + - grafana_notifications + - grafana_run + when: "grafana_alert_notifications | length > 0 or grafana_alert_resources | length > 0" + +- name: Dashboards + ansible.builtin.include_tasks: + file: dashboards.yml + apply: + tags: + - grafana_configure + - grafana_dashboards + - grafana_run + when: "grafana_dashboards | length > 0 or __found_dashboards | length > 0" + vars: + __found_dashboards: "{{ lookup('fileglob', grafana_dashboards_dir + '/*.json', wantlist=True) }}" diff --git a/ansible_collections/grafana/grafana/roles/grafana/tasks/notifications.yml b/ansible_collections/grafana/grafana/roles/grafana/tasks/notifications.yml new file mode 100644 index 000000000..f08487b44 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/tasks/notifications.yml @@ -0,0 +1,28 @@ +--- +# legacy config +- name: "Create/Delete/Update alert notifications channels (provisioning)" + ansible.builtin.copy: + content: | + apiVersion: 1 + {{ grafana_alert_notifications | to_nice_yaml }} + dest: /etc/grafana/provisioning/notification/ansible.yml + owner: root + group: grafana + mode: 0640 + become: true + notify: restart_grafana + when: grafana_use_provisioning and grafana_alert_notifications | length > 0 + +# new alert resources +- name: "Create/Delete/Update alert resources (provisioning)" + ansible.builtin.copy: + content: | + apiVersion: 1 + {{ grafana_alert_resources | to_nice_yaml }} + dest: /etc/grafana/provisioning/alerting/ansible.yml + owner: root + group: grafana + mode: 0640 + become: true + notify: restart_grafana + when: grafana_use_provisioning and grafana_alert_resources | length > 0 diff --git a/ansible_collections/grafana/grafana/roles/grafana/tasks/plugins.yml b/ansible_collections/grafana/grafana/roles/grafana/tasks/plugins.yml new file mode 100644 index 000000000..133624a0f --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/tasks/plugins.yml @@ -0,0 +1,20 @@ +--- +- name: "Check which plugins are installed" + ansible.builtin.find: + file_type: directory + recurse: false + paths: "{{ grafana_data_dir }}/plugins" + register: __installed_plugins + +- name: "Install plugins" + become: true + ansible.builtin.command: + cmd: "grafana-cli --pluginsDir {{ grafana_data_dir }}/plugins plugins install {{ item }}" + creates: "{{ grafana_data_dir }}/plugins/{{ item }}" + loop: "{{ grafana_plugins | difference(__installed_plugins.files) }}" + register: __plugin_install + until: "__plugin_install is succeeded" + retries: 5 + delay: 2 + notify: + - restart_grafana diff --git a/ansible_collections/grafana/grafana/roles/grafana/tasks/preflight.yml b/ansible_collections/grafana/grafana/roles/grafana/tasks/preflight.yml new file mode 100644 index 000000000..d209abc5d --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/tasks/preflight.yml @@ -0,0 +1,84 @@ +--- +- name: "Check variable types" + ansible.builtin.assert: + that: + - "grafana_server is mapping" + - "grafana_database is mapping" + - "grafana_security is mapping" + +- name: "Fail when datasources aren't configured when dashboards are set to be installed" + ansible.builtin.fail: + msg: "You need to specify datasources for dashboards!!!" + when: "grafana_dashboards != [] and grafana_datasources == []" + +- name: "Fail when grafana admin user isn't set" + ansible.builtin.fail: + msg: "Please specify grafana admin user (grafana_security.admin_user)" + when: + - "grafana_security.admin_user == '' or + grafana_security.admin_user is not defined" + +- name: "Fail when grafana admin password isn't set" + ansible.builtin.fail: + msg: "Please specify grafana admin password (grafana_security.admin_password)" + when: + - "grafana_security.admin_password == '' or + grafana_security.admin_password is not defined" + +- name: "Fail on incorrect variable types in datasource definitions" + ansible.builtin.fail: + msg: "Boolean variables in grafana_datasources shouldn't be passed as strings. Please remove unneeded apostrophes." + when: "( item.isDefault is defined and item.isDefault is string ) or + ( item.basicAuth is defined and item.basicAuth is string )" + loop: "{{ grafana_datasources }}" + +- name: "Fail on bad database configuration" + ansible.builtin.fail: + msg: "Wrong database configuration. Please look at http://docs.grafana.org/installation/configuration/#database" + when: "( grafana_database.type == 'sqlite3' and grafana_database.url is defined ) or + ( grafana_database.type != 'sqlite3' and grafana_database.path is defined ) or + ( grafana_database.type == 'sqlite3' and grafana_database.host is defined ) or + ( grafana_database.type == 'sqlite3' and grafana_database.user is defined ) or + ( grafana_database.type == 'sqlite3' and grafana_database.password is defined ) or + ( grafana_database.type == 'sqlite3' and grafana_database.server_cert_name is defined )" + +- name: "Fail when grafana domain isn't properly configured" + ansible.builtin.fail: + msg: "Check server configuration. Please look at http://docs.grafana.org/installation/configuration/#server" + when: + - "grafana_server.root_url is defined" + - "grafana_server.root_url is search(grafana_server.domain)" + +- name: "Fail when grafana_api_keys uses invalid role names" + ansible.builtin.fail: + msg: "Check grafana_api_keys. The role can only be one of the following values: Viewer, Editor or Admin." + when: "item.role not in ['Viewer', 'Editor', 'Admin']" + loop: "{{ grafana_api_keys }}" + +- name: "Fail when grafana_ldap isn't set when grafana_auth.ldap is" + ansible.builtin.fail: + msg: "You need to configure grafana_ldap.servers and grafana_ldap.group_mappings when grafana_auth.ldap is set" + when: + - "'ldap' in grafana_auth" + - "grafana_ldap is not defined or ('servers' not in grafana_ldap or 'group_mappings' not in grafana_ldap)" + +- name: "Force grafana_use_provisioning to false if grafana_version is < 5.0 ( grafana_version is set to '{{ grafana_version }}' )" + ansible.builtin.set_fact: + grafana_use_provisioning: false + when: + - "grafana_version != 'latest'" + - "grafana_version is version_compare('5.0', '<')" + +- name: "Fail if grafana_port is lower than 1024 and grafana_cap_net_bind_service is not true" + ansible.builtin.fail: + msg: "Trying to use a port lower than 1024 without setting grafana_cap_net_bind_service." + when: + - "grafana_port | int <= 1024" + - "not grafana_cap_net_bind_service" + +- name: "Fail if grafana_server.socket not defined when in socket mode" + ansible.builtin.fail: + msg: "You need to configure grafana_server.socket when grafana_server.protocol is set to 'socket'" + when: + - "grafana_server.protocol is defined and grafana_server.protocol == 'socket'" + - "grafana_server.socket is undefined or grafana_server.socket == ''" diff --git a/ansible_collections/grafana/grafana/roles/grafana/templates/grafana.ini.j2 b/ansible_collections/grafana/grafana/roles/grafana/templates/grafana.ini.j2 new file mode 100644 index 000000000..df6eab14f --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/templates/grafana.ini.j2 @@ -0,0 +1,214 @@ +{{ ansible_managed | comment }} +# More informations: +# http://docs.grafana.org/installation/configuration +# https://github.com/grafana/grafana/blob/master/conf/sample.ini + +app_mode = production +instance_name = {{ grafana_instance }} + +# Directories +[paths] +data = {{ grafana_data_dir }} +logs = {{ grafana_logs_dir }} +plugins = {{ grafana_data_dir }}/plugins +; datasources = conf/datasources + +# HTTP options +[server] +{% if grafana_server.protocol is undefined or grafana_server.protocol in ['http', 'https'] %} +http_addr = {{ grafana_address }} +http_port = {{ grafana_port }} +{% endif %} +domain = {{ grafana_domain }} +root_url = {{ grafana_url }} +{% for k,v in grafana_server.items() %} +{% if not k in ['http_addr', 'http_port', 'domain', 'root_url'] %} +{{ k }} = {{ v }} +{% endif %} +{% endfor %} + +# Database +[database] +{% for k,v in grafana_database.items() %} +{% if k == 'password' %} +{{ k }} = """{{ v }}""" +{% else %} +{{ k }} = {{ v }} +{% endif %} +{% endfor %} + +# Plugins +{% if grafana_plugins_ops is defined %} +[plugins] +{% for k,v in grafana_plugins_ops.items() %} +{{ k }} = {{ v }} +{% endfor %} +{% endif %} + +# Remote cache +[remote_cache] +{% for k,v in grafana_remote_cache.items() %} +{{ k }} = {{ v }} +{% endfor %} + +# Security +[security] +{% for k,v in grafana_security.items() %} +{{ k }} = {{ v }} +{% endfor %} + +# Users management and registration +{% if grafana_users != {} %} +[users] +{% for k,v in grafana_users.items() %} +{{ k }} = {{ v }} +{% endfor %} +{% endif %} +[emails] +welcome_email_on_sign_up = {{ grafana_welcome_email_on_sign_up }} + +# Authentication +{% if grafana_auth != {} %} +[auth] +disable_login_form = {{ grafana_auth.disable_login_form | default('False') }} +oauth_auto_login = {{ grafana_auth.oauth_auto_login | default('False') }} +oauth_allow_insecure_email_lookup = {{ grafana_auth.oauth_allow_insecure_email_lookup | default('False') }} +disable_signout_menu = {{ grafana_auth.disable_signout_menu | default('False') }} +signout_redirect_url = {{ grafana_auth.signout_redirect_url | default('') }} +{% for section, options in grafana_auth.items() %} +{% if options is mapping %} +[auth.{{ section }}] +{% if "enabled" not in options %} +enabled = True +{% endif %} +{% for k, v in options.items() %} +{{ k }} = {{ v }} +{% endfor %} +{% else %} +{{ section }} = {{ options }} +{% endif %} +{% endfor %} +{% endif %} + +# Session +{% if grafana_session != {} %} +[session] +{% for k,v in grafana_session.items() %} +{{ k }} = {{ v }} +{% endfor %} +{% endif %} + +# Analytics +[analytics] +reporting_enabled = "{{ grafana_analytics.reporting_enabled | default(True) }}" +{% if grafana_analytics.google_analytics_ua_id is defined and grafana_analytics.google_analytics_ua_id != '' %} +google_analytics_ua_id = "{{ grafana_analytics.google_analytics_ua_id }}" +{% endif %} + +# Dashboards +[dashboards] +versions_to_keep = 20 + +[dashboards.json] +enabled = true +path = {{ grafana_data_dir }}/dashboards + +# Alerting +[alerting] +{% if grafana_alerting != {} %} +enabled = true +{% for k,v in grafana_alerting.items() %} +{% if k != 'enabled' %} +{{ k }} = {{ v }} +{% endif %} +{% endfor %} +{% else %} +enabled = false +{% endif %} + +# SMTP and email config +{% if grafana_smtp != {} %} +[smtp] +enabled = True +{% for k,v in grafana_smtp.items() %} +{% if k == 'enabled' %}{% endif %} +{% if k == 'password' %} +{{ k }} = """{{ v }}""" +{% else %} +{{ k }} = {{ v }} +{% endif %} +{% endfor %} +{% endif %} + +# Logging +[log] +mode = {{ grafana_log.mode | default('console, file') }} +level = {{ grafana_log.level | default('info') }} + +# Metrics +[metrics] +{% if grafana_metrics != {} %} +enabled = true +interval_seconds = {{ grafana_metrics.interval_seconds | default(10) }} +{% if grafana_metrics.basic_auth_username is defined %} +basic_auth_username = {{ grafana_metrics.basic_auth_username }} +{% endif %} +{% if grafana_metrics.basic_auth_password is defined %} +basic_auth_password = """{{ grafana_metrics.basic_auth_password }}""" +{% endif %} +{% if grafana_metrics.graphite is defined %} +[metrics.graphite] +address = {{ grafana_metrics.graphite.address }} +prefix = {{ grafana_metrics.graphite.prefix }} +{% endif %} +{% else %} +enabled = false +{% endif %} + +# Tracing +{% if grafana_tracing != {} %} +[tracing.jaeger] +{% for k,v in grafana_tracing.items() %} +{{ k }} = {{ v }} +{% endfor %} +{% endif %} + +# Grafana.com configuration +[grafana_com] +url = https://grafana.com + +# Snapshots +{% if grafana_snapshots != {} %} +[snapshots] +{% for k,v in grafana_snapshots.items() %} +{{ k }} = {{ v }} +{% endfor %} +{% endif %} + +# External image storage +{% if grafana_image_storage != {} %} +[external_image_storage] +provider = {{ grafana_image_storage.provider }} +[external_image_storage.{{ grafana_image_storage.provider }}] +{% for k,v in grafana_image_storage.items() %} +{% if k != 'provider' %} +{{ k }} = {{ v }} +{% endif %} +{% endfor %} +{% endif %} + +# Panels +{% if grafana_panels != {} %} +[panels] +{% for k,v in grafana_panels.items() %} +{{ k }} = {{ v }} +{% endfor %} +{% endif %} + +# Date formats +{% if grafana_date_formats != {} %} +[date_formats] +{% for k,v in grafana_date_formats.items() %} +{{ k }} = {{ v }} +{% endfor %} +{% endif %} diff --git a/ansible_collections/grafana/grafana/roles/grafana/templates/ldap.toml.j2 b/ansible_collections/grafana/grafana/roles/grafana/templates/ldap.toml.j2 new file mode 100644 index 000000000..b28e0029b --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/templates/ldap.toml.j2 @@ -0,0 +1,39 @@ +{{ ansible_managed | comment }} +# Documentation: http://docs.grafana.org/installation/ldap/ +{% if 'verbose_logging' in grafana_ldap %} +verbose_logging = {{ 'true' if grafana_ldap.verbose_logging else 'false' }} +{% endif %} + +[[servers]] +{% for k,v in grafana_ldap.servers.items() if k != 'attributes' %} +{% if k == 'port' %} +{{ k }} = {{ v | int }} +{% elif v in [True, False] %} +{{ k }} = {{ 'true' if v else 'false' }} +{% else %} +{{ k }} = {{ v | to_nice_json }} +{% endif %} +{% endfor %} + +[servers.attributes] +{% for k,v in grafana_ldap.servers.attributes.items() %} +{{ k }} = {{ v | to_nice_json }} +{% endfor %} + +{% for org in grafana_ldap.group_mappings %} +{% if 'name' in org %} +# {{ org.name }} +{% endif %} +{% for group in org.groups %} +[[servers.group_mappings]] +org_id = {{ org.id }} +{% for k,v in group.items() %} +{% if v in [True, False] %} +{{ k }} = {{ 'true' if v else 'false' }} +{% else %} +{{ k }} = "{{ v }}" +{% endif %} +{% endfor %} + +{% endfor %} +{% endfor %} diff --git a/ansible_collections/grafana/grafana/roles/grafana/templates/tmpfiles.j2 b/ansible_collections/grafana/grafana/roles/grafana/templates/tmpfiles.j2 new file mode 100644 index 000000000..16dda1b9d --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/templates/tmpfiles.j2 @@ -0,0 +1,2 @@ +{{ ansible_managed | comment }} +d {{ grafana_server.socket | dirname }} 0775 grafana grafana diff --git a/ansible_collections/grafana/grafana/roles/grafana/test-requirements.txt b/ansible_collections/grafana/grafana/roles/grafana/test-requirements.txt new file mode 100644 index 000000000..af58c1102 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/test-requirements.txt @@ -0,0 +1,6 @@ +molecule +docker +pytest-testinfra +jmespath +selinux +passlib diff --git a/ansible_collections/grafana/grafana/roles/grafana/vars/distro/debian.yml b/ansible_collections/grafana/grafana/roles/grafana/vars/distro/debian.yml new file mode 100644 index 000000000..ca9773024 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/vars/distro/debian.yml @@ -0,0 +1,8 @@ +--- +grafana_package: "grafana{% if ansible_architecture == 'armv6l' %}-rpi{% endif %}{{ (grafana_version != 'latest') | ternary('=' ~ grafana_version, '') }}" +_grafana_dependencies: + - apt-transport-https + - adduser + - ca-certificates + - libfontconfig + - gnupg2 diff --git a/ansible_collections/grafana/grafana/roles/grafana/vars/distro/redhat.yml b/ansible_collections/grafana/grafana/roles/grafana/vars/distro/redhat.yml new file mode 100644 index 000000000..0721829d0 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/vars/distro/redhat.yml @@ -0,0 +1,5 @@ +--- +grafana_package: "grafana{{ (grafana_version != 'latest') | ternary('-' ~ grafana_version, '') }}" +# https://unix.stackexchange.com/questions/534463/cant-enable-grafana-on-boot-in-fedora-because-systemd-sysv-install-missing +_grafana_dependencies: + - chkconfig diff --git a/ansible_collections/grafana/grafana/roles/grafana/vars/distro/suse.yml b/ansible_collections/grafana/grafana/roles/grafana/vars/distro/suse.yml new file mode 100644 index 000000000..5dfc0fdf1 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana/vars/distro/suse.yml @@ -0,0 +1,2 @@ +--- +grafana_package: "grafana{{ (grafana_version != 'latest') | ternary('-' ~ grafana_version, '') }}" diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/README.md b/ansible_collections/grafana/grafana/roles/grafana_agent/README.md index 8f9d39a6a..6e7eaa942 100644 --- a/ansible_collections/grafana/grafana/roles/grafana_agent/README.md +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/README.md @@ -1,54 +1,68 @@ -Role Name -========= +# Role Name -Ansible Role to deploy Grafana Agent on Linux hosts. Using this Role, Grafana Agent can be deployed on Ubunutu, Debian, CentOS and Fedora linux distributions +Ansible Role to deploy Grafana Agent on Linux hosts. Using this Role, Grafana Agent can be deployed on RedHat, Ubuntu, Debian, CentOS +and Fedora linux distributions. +## Requirements -Requirements ------------- +Please ensure that `curl` is intalled on Ansible controller. -To use this role, You need a YAML file having the Grafana Agent configuration +To use this role, You need a YAML file having the Grafana Agent configuration. -Role Variables --------------- +## Role Variables -A description of the variables for this role. +All variables which can be overridden are stored in [./defaults/main.yaml](./defaults/main.yaml) file as well as in table below. -| Variable | Required | Default | Choices | Comments | -|-------------------------|----------|----------------------|--------------------------------------------------------------------------------------------------------------------|---------------------------------------------| -| install_unzip | no | true | true, false | This will install unzip on the Linux host | -| update_package_cache | no | yes | yes, no | Force dnf/apt to check if cache is out of date and redownload if needed.| -| agent_version | no | 0.29.0 | 0.29.0, 0.28.1, 0.28.0, 0.27.1, 0.27.0 | Version of the Grafana agent to install| -| linux_architecture | no | linux-amd64 | linux-amd64, linux-arm64, linux-armv6, linux-armv7, linux-ppc64le | Type of linux architecture of the remote host| -| agent_binary_location | no | /usr/local/bin | | Path where the agent binary will be copied to on the remote host| -| agent_config_location | no | /etc/grafana | | Path where the agent configuration will be copied to on the remote host| -| agent_config_local_path | yes | agent-config.yml | | Path to the agent configuration file on local| -| systemd_service_state | no | restarted | reloaded, restarted, started, stopped | Operation performed on the systemd service| -| systemd_config | no | | | Configuration for grafana-agent systemd service| +| Variable | Default | Description | +| :------ | :------ | :--------- | +| `grafana_agent_version` | `latest` | version of the agent to install | +| `grafana_agent_base_download_url` | `https://github.com/{{ _grafana_agent_github_org }}/{{ _grafana_agent_github_repo }}/releases/download` | base download url. Github or mirror to download from | +| `grafana_agent_install_dir` | `/opt/grafana-agent/bin` | directory to install the binary to | +| `grafana_agent_binary` | `grafana-agent` | name to use for the binary | +| `grafana_agent_config_dir` | `/etc/grafana-agent` | directory to store the configuration files in | +| `grafana_agent_config_filename` | `config.yaml` | name of the configuration file for the agent | +| `grafana_agent_env_file` | `service.env` | name of the environment file loaded by the system unit file | +| `grafana_agent_local_tmp_dir` | `/tmp/grafana-agent` | temporary directory to create on the controller/localhost where the archive will be downloaded to | +| `grafana_agent_data_dir` | `/var/lib/grafana-agent` | the data directory to create for the wal and positions | +| `grafana_agent_wal_dir` | `"{{ grafana_agent_data_dir }}/data"` | wal directory to use, should be a sub-folder of grafana_agent_data_dir, will automatically be created when the agent starts | +| `grafana_agent_positions_dir` | `"{{ grafana_agent_data_dir }}/data"` | positions directory to use, should be a sub-folder of grafana_agent_data_dir, will automatically be created when the agent starts | +| `grafana_agent_mode` | `static` | mode to run Grafana Agent in. Can be "flow" or "static", [Flow Docs](https://grafana.com/docs/agent/latest/flow/) | +| `grafana_agent_user` | `grafana-agent` | os user to create for the agent to run as | +| `grafana_agent_user_group` | `grafana-agent` | os user group to create for the agent | +| `grafana_agent_user_groups` | `[]` | Configurable user groups that the Grafana agent can be put in so that it can access logs | +| `grafana_agent_user_shell` | `/usr/sbin/nologin` | the shell for the user | +| `grafana_agent_user_createhome` | `false` | whether or not to create a home directory for the user | +| `grafana_agent_local_binary_file` | `""` | full path to the local binary if already downloaded or built on the controller, this should only be set, if ansible is not downloading the binary and you have manually downloaded the binary | +| `grafana_agent_flags_extra` | see [./defaults/main.yaml](./defaults/main.yaml) | dictionary of additional command-line flags, run grafana-agent --help for a complete list. [Docs](https://grafana.com/docs/agent/latest/configuration/flags/) | +| `grafana_agent_env_vars` | `{}` | sets Environment variables in the systemd service configuration. | +| `grafana_agent_env_file_vars` | `{}` | dictionary of key/pair values to write to the environment file that is loaded by the service, with the flag `--config.expand-env=true` any generated config files will support the expansion of environment variables at runtime by referencing ${ENVVAR}. be aware of boolean values, when output they will result in the proper-cased string "True" and "False" | +| `grafana_agent_provisioned_config_file` | `""` | path to a config file on the controller that will be used instead of the provided configs below if specified. | +| `grafana_agent_server_config` | see [./defaults/main.yaml](./defaults/main.yaml) | Configures the server of the Agent used to enable self-scraping, [Docs](https://grafana.com/docs/agent/latest/configuration/server-config/) | +| `grafana_agent_metrics_config` | see [./defaults/main.yaml](./defaults/main.yaml) | Configures metric collection, [Docs](https://grafana.com/docs/agent/latest/configuration/metrics-config/) | +| `grafana_agent_logs_config` | see [./defaults/main.yaml](./defaults/main.yaml) | Configures logs collection, [Docs](https://grafana.com/docs/agent/latest/configuration/logs-config/) | +| `grafana_agent_traces_config` | see [./defaults/main.yaml](./defaults/main.yaml) | Configures traces collection, [Docs](https://grafana.com/docs/agent/latest/configuration/traces-config/) | +| `grafana_agent_integrations_config` | see [./defaults/main.yaml](./defaults/main.yaml) | Configures integrations for the agent, [Docs](https://grafana.com/docs/agent/latest/configuration/integrations/) | -Example Playbook ----------------- +## OS Support +The Grafana Agent role has been tested on below Operating Systems +- Ubuntu 22.10, Ubunutu 22.04 LTS, Ubunutu 20.04 LTS, Ubunutu 18.04 LTS +- Fedora 37, Fedora 36 +- Debian 11, Debian 10, Debian 9 +- CentOS 9 Stream, CentOS 8 Stream, CentOS 7 +- AlmaLinux 9, AlmaLinux 8 +- RockyLinux 9, RockyLinux 8 -Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: +## Example Playbooks -```yaml -- name: Install Grafana Agent - hosts: all +See [examples](../../examples) - tasks: - - name: Install Grafana Agent - ansible.builtin.include_role: - name: grafana.grafana.grafana_agent: - vars: - agent_config_local_path: ../agent-config.yml -``` -License -------- +## License See [LICENSE](https://github.com/grafana/grafana-ansible-collection/blob/main/LICENSE) -Author Information ------------------- -- [Grafana Labs](https://github.com/grafana) -- [Ishan Jain](https://github.com/ishanjainn) +## Author Information +- [Grafana Labs](https://github.com/grafana) +- [Ishan Jain](https://github.com/ishanjainn) +- [Aaron Benton](https://github.com/bentonam) +- [Vitaly Zhuravlev](https://github.com/v-zhuravlev) diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/defaults/main.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/defaults/main.yaml new file mode 100644 index 000000000..4ea702db0 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/defaults/main.yaml @@ -0,0 +1,193 @@ +--- +# version of the agent to install +grafana_agent_version: latest + +# base download url. Github or mirror to download from +grafana_agent_base_download_url: "https://github.com/{{ _grafana_agent_github_org }}/{{ _grafana_agent_github_repo }}/releases/download" + +# directory to install the binary to +grafana_agent_install_dir: /opt/grafana-agent/bin + +# name to use for the binary +grafana_agent_binary: grafana-agent + +# directory to store the configuration files in +grafana_agent_config_dir: /etc/grafana-agent + +# name of the configuration file for the agent +grafana_agent_config_filename: config.yaml + +# name of the environment file loaded by the system unit file +grafana_agent_env_file: service.env + +# temporary directory to create on the controller/localhost where the archive will be downloaded to +grafana_agent_local_tmp_dir: /tmp/grafana-agent + +# data directory to create for the wal and positions +grafana_agent_data_dir: /var/lib/grafana-agent + +# wal directory to use, should be a sub-folder of grafana_agent_data_dir, will automatically be created when the agent starts +grafana_agent_wal_dir: "{{ grafana_agent_data_dir }}/wal" + +# positions directory to use, should be a sub-folder of grafana_agent_data_dir, will automatically be created when the agent starts +grafana_agent_positions_dir: "{{ grafana_agent_data_dir }}/positions" + +# mode to run Grafana Agent in. Can be "flow" or "static". +# Docs: https://grafana.com/docs/agent/latest/flow/ +grafana_agent_mode: static + +# os user to create for the agent to run as +grafana_agent_user: grafana-agent + +# os user group to create for the agent +grafana_agent_user_group: grafana-agent + +# Configurable user groups that the grafana agent can be put in so that it can access logs +# (See https://github.com/grafana/grafana-ansible-collection/issues/40) +grafana_agent_user_groups: [] + +# the shell for the user +grafana_agent_user_shell: /usr/sbin/nologin + +# whether or not to create a home directory for the user +grafana_agent_user_createhome: false + +# full path to the local binary if already downloaded or built on the controller +# this should only be set, if ansible is not downloading the binary and you have +# manually downloaded the binary +grafana_agent_local_binary_file: "" + +# dictionary of additional command-line flags, run grafana-agent --help for a complete list +# Docs: https://grafana.com/docs/agent/latest/static/configuration/flags/ +grafana_agent_flags_extra: + config.expand-env: 'true' + config.enable-read-api: 'false' + server.register-instrumentation: 'true' + server.http.address: 127.0.0.1:12345 + server.grpc.address: 127.0.0.1:12346 + +# sets Environment variables in the systemd service configuration. +grafana_agent_env_vars: {} + +# dictionary of key/pair values to write to the environment file that is loaded by the service, with the flag --config.expand-env=true +# any generated config files will support the expansion of environment variables at runtime by referencing ${ENVVAR}. +# be aware of boolean values, when output they will result in the proper-cased string "True" and "False" +grafana_agent_env_file_vars: {} + +# path to a config file on the controller that will be used instead of the provided configs below if specified. +grafana_agent_provisioned_config_file: "" + +################################################################################################# +# Configures the server of the Agent used to enable self-scraping # +################################################################################################# +# Docs: https://grafana.com/docs/agent/latest/static/configuration/server-config/ +# the entire dictionary value for this object is copied to the server: block in the config file +grafana_agent_server_config: + # Log only messages with the given severity or above. Supported values [debug, + # info, warn, error]. This level affects logging for all Agent-level logs, not + # just the HTTP and gRPC server. + # + # Note that some integrations use their own loggers which ignore this + # setting. + log_level: info + +################################################################################################# +# Configures metric collection # +################################################################################################# +# Docs: https://grafana.com/docs/agent/latest/static/configuration/metrics-config/ +# the entire dictionary value for this object is copied to the metrics: block in the config file +grafana_agent_metrics_config: + # Configure values for all Prometheus instances + # Docs: https://grafana.com/docs/agent/latest/static/configuration/metrics-config/#global_config + global: + # How frequently should Prometheus instances scrape. + scrape_interval: 1m + + # How long to wait before timing out a scrape from a target. + scrape_timeout: 10s + + # A dictionary of key/pair static labels to add for all metrics. + external_labels: {} + + # Default set of remote_write endpoints. If an instance doesn't define any + # remote_writes, it will use this list. + # Docs: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write + remote_write: [] + + # The list of Prometheus instances to launch with the agent. + # Docs: https://grafana.com/docs/agent/latest/static/configuration/metrics-config/#metrics_instance_config + configs: [] + # - name: name-of-scrape-job + # # Docs: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config + # scrape_configs: [] + # # Optional list of remote_write targets, if not specified metrics.global.remote_write is used + # # Docs: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write + # remote_write: [] + + # Configure the directory used by instances to store their WAL. + # + # The Grafana Agent assumes that all folders within wal_directory are managed by + # the agent itself. + wal_directory: "{{ grafana_agent_wal_dir }}" + # Configures how long ago an abandoned (not associated with an instance) WAL + # may be written to before being eligible to be deleted + wal_cleanup_age: 12h + # Configures how often checks for abandoned WALs to be deleted are performed. + # A value of 0 disables periodic cleanup of abandoned WALs + wal_cleanup_period: 30m + +################################################################################################# +# Configures logs collection # +################################################################################################# +# Docs: https://grafana.com/docs/agent/latest/static/configuration/logs-config/ +# the entire dictionary value for this object is copied to the logs: block in the config file +grafana_agent_logs_config: + # Directory to store Loki Promtail positions files in. Positions files are + # required to read logs, and are used to store the last read offset of log + # sources. The positions files will be stored in + # /.yml. + # + # Optional only if every config has a positions.filename manually provided. + # + # This directory will be automatically created if it doesn't exist. + positions_directory: "{{ grafana_agent_positions_dir }}" + # Configure values for all Loki Promtail instances. + global: + # Docs: https://grafana.com/docs/agent/latest/static/configuration/logs-config/#logs_instance_config + clients: [] + +################################################################################################# +# Configures traces collection # +################################################################################################# +# Docs: https://grafana.com/docs/agent/latest/static/configuration/traces-config/ +# the entire dictionary value for this object is copied to the traces: block in the config file +grafana_agent_traces_config: + # Docs: https://grafana.com/docs/agent/latest/static/configuration/traces-config/#traces_instance_config + configs: [] + +################################################################################################# +# Configures integrations for the agent # +################################################################################################# +# Docs: https://grafana.com/docs/agent/latest/static/configuration/integrations/ +# the entire dictionary value for this object is copied to the integrations: block in the config file +grafana_agent_integrations_config: + # Automatically collect metrics from enabled integrations. If disabled, + # integrations will be run but not scraped and thus not remote_written. Metrics + # for integrations will be exposed at /integrations//metrics + # and can be scraped by an external process. + scrape_integrations: true + # Controls the Agent integration + agent: + # Enables the Agent integration, allowing the Agent to automatically + # collect and send metrics about itself. + enabled: true + # Allows for relabeling labels on the target. + relabel_configs: [] + # Relabel metrics coming from the integration, allowing to drop series + # from the integration that you don't care about. + metric_relabel_configs: [] + + # Controls the node_exporter integration + # Docs: https://grafana.com/docs/agent/latest/static/configuration/integrations/node-exporter-config/ + node_exporter: + enabled: true diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/defaults/main.yml b/ansible_collections/grafana/grafana/roles/grafana_agent/defaults/main.yml deleted file mode 100644 index 13a060e03..000000000 --- a/ansible_collections/grafana/grafana/roles/grafana_agent/defaults/main.yml +++ /dev/null @@ -1,20 +0,0 @@ -install_unzip: true -update_package_cache: yes -agent_version: 0.29.0 -linux_architecture: linux-amd64 -agent_binary_location: /usr/local/bin -agent_config_location: /etc/grafana -agent_config_local_path: agent-config.yml - -systemd_service_state: restarted -systemd_config: | - [Unit] - Description=Grafana Agent - - [Service] - User=grafana-agent - ExecStart={{ agent_binary_location }}/agent-{{ linux_architecture }} --config.file={{ agent_config_location }}/agent-config.yaml - Restart=always - - [Install] - WantedBy=multi-user.target \ No newline at end of file diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/handlers/main.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/handlers/main.yaml new file mode 100644 index 000000000..b5b01aabc --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/handlers/main.yaml @@ -0,0 +1,12 @@ +--- +- name: Restart Grafana Agent + become: true + ansible.builtin.systemd: + name: grafana-agent + state: restarted + daemon_reload: true + listen: "restart grafana-agent" + +- name: Check Grafana Agent is started properly + ansible.builtin.include_tasks: ga-started.yaml + listen: "restart grafana-agent" diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/meta/main.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/meta/main.yaml new file mode 100644 index 000000000..7ef93089c --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/meta/main.yaml @@ -0,0 +1,25 @@ +--- +dependencies: [] + +galaxy_info: + role_name: grafana_agent + author: Ishan Jain + description: Ansible Role to deploy Grafana Agent on Linux hosts. + license: "GPL-3.0-or-later" + min_ansible_version: "2.11" + platforms: + - name: Fedora + versions: + - "all" + - name: Debian + versions: + - "all" + - name: Ubuntu + versions: + - "all" + - name: EL + versions: + - "all" + galaxy_tags: + - grafana + - observability diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/meta/main.yml b/ansible_collections/grafana/grafana/roles/grafana_agent/meta/main.yml deleted file mode 100644 index c99271d78..000000000 --- a/ansible_collections/grafana/grafana/roles/grafana_agent/meta/main.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- -dependencies: [] - -galaxy_info: - role_name: grafana_agent - author: Ishan Jain - description: Ansible Role to deploy Grafana Agent on Linux hosts. - license: "GPL-3.0-or-later" - min_ansible_version: "2.11" - platforms: - - name: Fedora - versions: - - "all" - - name: Debian - versions: - - "all" - - name: Ubuntu - versions: - - "all" - - name: EL - versions: - - "all" - galaxy_tags: - - grafana - - observability \ No newline at end of file diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/configure.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/configure.yaml new file mode 100644 index 000000000..6e2bdf7f8 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/configure.yaml @@ -0,0 +1,51 @@ +--- +# these tasks are ran in both install and configure, as directories could have changed +- name: Configure directories + ansible.builtin.import_tasks: install/directories.yaml + +- name: Create a symbolic link + ansible.builtin.file: + src: "{{ grafana_agent_install_dir }}/{{ grafana_agent_binary }}" + dest: "/usr/local/bin/{{ grafana_agent_binary }}" + owner: root + group: root + state: link + +- name: Overwrite/Create Grafana Agent service + ansible.builtin.template: + src: grafana-agent.service.j2 + dest: "{{ _grafana_agent_systemd_dir }}/{{ _grafana_agent_systemd_unit }}" + owner: root + group: root + mode: 0644 + notify: "restart grafana-agent" + +- name: Create the Service Environment file + ansible.builtin.template: + src: EnvironmentFile.j2 + dest: "{{ grafana_agent_config_dir }}/{{ grafana_agent_env_file }}" + owner: root + group: "{{ grafana_agent_user_group }}" + mode: 0640 + notify: "restart grafana-agent" + +- name: Create Grafana Agent config + ansible.builtin.template: + src: config.yaml.j2 + dest: "{{ grafana_agent_config_dir }}/{{ grafana_agent_config_filename }}" + force: true + owner: root + group: "{{ grafana_agent_user_group }}" + mode: 0640 + notify: "restart grafana-agent" + when: grafana_agent_provisioned_config_file | length == 0 + +- name: Copy Grafana Agent config + ansible.builtin.copy: + src: "{{ grafana_agent_provisioned_config_file }}" + dest: "{{ grafana_agent_config_dir }}/{{ grafana_agent_config_filename }}" + owner: root + group: "{{ grafana_agent_user_group }}" + mode: 0640 + notify: "restart grafana-agent" + when: grafana_agent_provisioned_config_file | length > 0 diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/ga-started.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/ga-started.yaml new file mode 100644 index 000000000..cf66893d9 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/ga-started.yaml @@ -0,0 +1,29 @@ +--- +- name: Health check Grafana Agent + ansible.builtin.uri: + url: "{{ _grafana_agent_healthcheck_endpoint }}" + follow_redirects: none + method: GET + register: _result + failed_when: false + until: _result.status == 200 + retries: 3 + delay: 5 + changed_when: false + when: not ansible_check_mode + +- name: Check system logs if Grafana Agent is not started + when: not ansible_check_mode and _result.status != 200 + block: + - name: Run journalctl + ansible.builtin.shell: + cmd: "journalctl -u grafana-agent -b -n20 --no-pager" + register: journal_ret + changed_when: false + - name: Output Grafana agent logs + ansible.builtin.debug: + var: journal_ret.stdout_lines + - name: Rise alerts + ansible.builtin.assert: + that: false + fail_msg: "Service grafana-agent hasn't started." diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install.yaml new file mode 100644 index 000000000..ff101eb77 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install.yaml @@ -0,0 +1,19 @@ +--- +# user and group creation +- name: Configure user groups + ansible.builtin.import_tasks: install/user-group.yaml + +# directory creation +- name: Configure directories + ansible.builtin.import_tasks: install/directories.yaml + +# download and install agent +- name: Download and install Grafana Agent + ansible.builtin.import_tasks: install/download-install.yaml + when: (grafana_agent_local_binary_file is not defined) or (grafana_agent_local_binary_file | length == 0) + +# local install of agent +- name: Local install of Grafana Agent + ansible.builtin.import_tasks: + file: install/local-install.yaml + when: __grafana_agent_local_install diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/directories.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/directories.yaml new file mode 100644 index 000000000..13f3851a4 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/directories.yaml @@ -0,0 +1,26 @@ +--- +- name: Create install directories + block: + - name: Create Grafana Agent install directory + ansible.builtin.file: + path: "{{ grafana_agent_install_dir }}" + state: directory + owner: root + group: "{{ grafana_agent_user_group }}" + mode: 0770 + + - name: Create Grafana Agent conf directory + ansible.builtin.file: + path: "{{ grafana_agent_config_dir }}" + state: directory + owner: root + group: "{{ grafana_agent_user_group }}" + mode: 0770 + + - name: Create Grafana Agent data directory + ansible.builtin.file: + path: "{{ grafana_agent_data_dir }}" + state: directory + owner: root + group: "{{ grafana_agent_user_group }}" + mode: 0775 diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/download-install.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/download-install.yaml new file mode 100644 index 000000000..6cb1c96b3 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/download-install.yaml @@ -0,0 +1,48 @@ +--- +- name: Download Grafana Agent binary to controller (localhost) + block: + - name: Create Grafana Agent temp directory + become: false + ansible.builtin.file: + path: "{{ grafana_agent_local_tmp_dir }}" + state: directory + mode: 0751 + delegate_to: localhost + check_mode: false + run_once: true + + - name: Download Grafana Agent archive to local folder + become: false + ansible.builtin.get_url: + url: "{{ _grafana_agent_download_url }}" + dest: "{{ grafana_agent_local_tmp_dir }}/grafana-agent_{{ _grafana_agent_cpu_arch }}_{{ grafana_agent_version }}.zip" + mode: 0664 + register: _download_archive + until: _download_archive is succeeded + retries: 5 + delay: 2 + delegate_to: localhost + check_mode: false + run_once: true + + - name: Extract grafana-agent.zip + become: false + ansible.builtin.unarchive: + src: "{{ grafana_agent_local_tmp_dir }}/grafana-agent_{{ _grafana_agent_cpu_arch }}_{{ grafana_agent_version }}.zip" + dest: "{{ grafana_agent_local_tmp_dir }}" + remote_src: false + delegate_to: localhost + run_once: true + + - name: Set local path + ansible.builtin.set_fact: + __grafana_agent_local_binary_file: "{{ grafana_agent_local_tmp_dir }}/{{ grafana_agent_binary }}" + + - name: Propagate downloaded binary + ansible.builtin.copy: + src: "{{ grafana_agent_local_tmp_dir }}/{{ _grafana_agent_download_binary_file }}" + dest: "{{ grafana_agent_install_dir }}/{{ grafana_agent_binary }}" + mode: 0755 + owner: root + group: root + when: not ansible_check_mode diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/local-install.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/local-install.yaml new file mode 100644 index 000000000..a2859bb41 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/local-install.yaml @@ -0,0 +1,10 @@ +--- +- name: Install from local + block: + - name: "Propagate local binary {{ grafana_agent_local_binary_file }}" + ansible.builtin.copy: + src: "{{ grafana_agent_local_binary_file }}" + dest: "{{ grafana_agent_install_dir }}/{{ grafana_agent_binary }}" + mode: 0755 + owner: root + group: root diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/user-group.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/user-group.yaml new file mode 100644 index 000000000..7b6ba7a00 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/install/user-group.yaml @@ -0,0 +1,38 @@ +--- +- name: Grafana Agent group creation + block: + - name: "Check if the group exists ({{ grafana_agent_user_group }})" + ansible.builtin.getent: + database: group + key: "{{ grafana_agent_user_group }}" + fail_key: false + + - name: Set whether not the user group exists + ansible.builtin.set_fact: + __grafana_agent_user_group_exists: "{{ ansible_facts.getent_group[grafana_agent_user_group] is not none }}" + + - name: Add user group "{{ grafana_agent_user_group }}" + ansible.builtin.group: + name: "{{ grafana_agent_user_group }}" + system: true + state: present + when: not __grafana_agent_user_group_exists and grafana_agent_user_group != 'root' + + - name: Grafana Agent user group exists + ansible.builtin.debug: + msg: |- + The user group \"{{ grafana_agent_user_group }}\" already exists and will not be modified, + if modifying permissions please perform a separate task + when: __grafana_agent_user_group_exists + +- name: Grafana Agent user creation + block: + - name: Add user "{{ grafana_agent_user }}" + ansible.builtin.user: + name: "{{ grafana_agent_user }}" + comment: "Grafana Agent account" + groups: "{{ [ grafana_agent_user_group ] + grafana_agent_user_groups }}" + system: true + shell: "{{ grafana_agent_user_shell }}" + createhome: "{{ grafana_agent_user_createhome }}" + when: grafana_agent_user != 'root' diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/main.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/main.yaml new file mode 100644 index 000000000..7677b0a62 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/main.yaml @@ -0,0 +1,48 @@ +--- +- name: Preflight tasks + ansible.builtin.include_tasks: + file: preflight.yaml + apply: + become: true + tags: + - grafana_agent_install + - grafana_agent_configure + - grafana_agent_run + tags: + - grafana_agent_install + - grafana_agent_configure + - grafana_agent_run + +- name: Install tasks + ansible.builtin.include_tasks: + file: install.yaml + apply: + become: true + tags: + - grafana_agent_install + tags: + - grafana_agent_install + +- name: Configuration tasks + ansible.builtin.include_tasks: + file: configure.yaml + apply: + become: true + tags: + - grafana_agent_configure + tags: + - grafana_agent_configure + +- name: Flush handlers + ansible.builtin.meta: flush_handlers + +- name: Ensure Grafana Agent is started and enabled on boot + become: true + ansible.builtin.systemd: + name: grafana-agent + enabled: true + state: started + tags: + - grafana_agent_install + - grafana_agent_configure + - grafana_agent_run diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/main.yml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/main.yml deleted file mode 100644 index 0c5752c3b..000000000 --- a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/main.yml +++ /dev/null @@ -1,59 +0,0 @@ -- name: Install unzip on Ubuntu/Debian - ansible.builtin.apt: - name: unzip - state: present - update_cache: "{{ update_package_cache }}" - when: install_unzip | bool and (ansible_distribution == "Ubuntu" or ansible_distribution == "Debian") - -- name: Install unzip on Fedora/CentOS - ansible.builtin.dnf: - name: unzip - state: latest - update_cache: "{{ update_package_cache }}" - when: install_unzip | bool and (ansible_distribution == "Fedora" or ansible_distribution == "CentOS") - -- name: Download Grafana Agent binary from GitHub - ansible.builtin.get_url: - url: "https://github.com/grafana/agent/releases/download/v{{ agent_version }}/agent-{{ linux_architecture }}.zip" - dest: "/tmp/agent-linux.zip" - mode: '0644' - -- name: Unarchive the Grafana Agent binary - ansible.builtin.unarchive: - src: "/tmp/agent-linux.zip" - dest: "{{ agent_binary_location }}" - remote_src: yes - mode: '0755' - -- name: Create directory for Grafana Agent Configuration file - ansible.builtin.file: - path: "{{ agent_config_location }}" - state: directory - mode: '0755' - -- name: Create configuration file for Grafana Agent - ansible.builtin.copy: - src: "{{ agent_config_local_path }}" - dest: "{{ agent_config_location }}/agent-config.yaml" - -- name: Add user 'grafana-agent' - ansible.builtin.user: - name: grafana-agent - create_home: no - shell: /bin/false - -- name: Create service file for Grafana Agent - ansible.builtin.copy: - dest: "/etc/systemd/system/grafana-agent.service" - content: "{{ systemd_config }}" - -- name: Start Grafana Agent service - ansible.builtin.systemd: - daemon_reload: yes - name: grafana-agent - enabled: yes - state: "{{ systemd_service_state }}" - -- name: Checking grafana-agent service status - ansible.builtin.shell: - cmd: systemctl is-active grafana-agent \ No newline at end of file diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight.yaml new file mode 100644 index 000000000..09b86d6bb --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight.yaml @@ -0,0 +1,12 @@ +--- +- name: Preflight variable checks + ansible.builtin.import_tasks: preflight/vars.yaml + +- name: Systemd variable checks + ansible.builtin.import_tasks: preflight/systemd.yaml + +- name: Install variable checks + ansible.builtin.import_tasks: preflight/install.yaml + +- name: Download variable checks + ansible.builtin.import_tasks: preflight/download.yaml diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/download.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/download.yaml new file mode 100644 index 000000000..d885c9b6a --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/download.yaml @@ -0,0 +1,36 @@ +--- +- name: Get Grafana Agent version from Github + when: grafana_agent_version == 'latest' and not __grafana_agent_local_install + block: + - name: Get the latest published Grafana Agent # noqa command-instead-of-module + ansible.builtin.shell: | + curl -s https://api.github.com/repos/{{ _grafana_agent_github_org }}/{{ _grafana_agent_github_repo }}/releases/latest \ + | grep -m 1 tag_name \ + | cut -d '"' -f 4 | cut -c 2- + changed_when: false + run_once: true + delegate_to: localhost + become: false + register: _grafana_agent_version_request + + - name: Fail if cannot get Grafana Agent Version + ansible.builtin.fail: + msg: Issue getting the Grafana Agent Version + when: _grafana_agent_version_request == "" + + - name: Set the Grafana Agent version + ansible.builtin.set_fact: + grafana_agent_version: "{{ _grafana_agent_version_request.stdout }}" + + - name: Grafana Agent version to download + ansible.builtin.debug: + var: grafana_agent_version + +- name: Set the Grafana Agent download URL + ansible.builtin.set_fact: + _grafana_agent_download_url: |- + {{ grafana_agent_base_download_url }}/v{{ grafana_agent_version }}/{{ _grafana_agent_download_archive_file }} + +- name: Grafana Agent download URL + ansible.builtin.debug: + var: _grafana_agent_download_url diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/install.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/install.yaml new file mode 100644 index 000000000..833ececc1 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/install.yaml @@ -0,0 +1,72 @@ +--- +- name: Default to non-local install + ansible.builtin.set_fact: + __grafana_agent_local_install: false + +- name: Fail when grafana_agent_local_binary_file is defined but the file doesn't exist + when: grafana_agent_local_binary_file is defined and grafana_agent_local_binary_file | length > 0 + block: + - name: Check if grafana_agent_local_binary_file exists + ansible.builtin.stat: + path: "{{ grafana_agent_local_binary_file }}" + register: __grafana_agent_local_binary_check + become: false + delegate_to: localhost + check_mode: false + + - name: Fail when the grafana_agent_local_binary_file does not exist + ansible.builtin.fail: + msg: "The grafana_agent_local_binary_file ({{ grafana_agent_local_binary_file }}) was specified but does not exist" + when: not __grafana_agent_local_binary_check.stat.exists + + - name: Change to local install + ansible.builtin.set_fact: + __grafana_agent_local_install: true + +- name: Fail when grafana_agent_provisioned_config_file is defined but the file doesn't exist + when: grafana_agent_provisioned_config_file is defined and grafana_agent_provisioned_config_file | length > 0 + block: + - name: Check if grafana_agent_provisioned_config_file exists + ansible.builtin.stat: + path: "{{ grafana_agent_provisioned_config_file }}" + register: __grafana_agent_provisioned_config_file_check + become: false + delegate_to: localhost + check_mode: false + + - name: Fail when the grafana_agent_provisioned_config_file does not exist + ansible.builtin.fail: + msg: "The grafana_agent_provisioned_config_file ({{ grafana_agent_provisioned_config_file }}) was specified but does not exist" + when: not __grafana_agent_provisioned_config_file_check.stat.exists + +- name: Check if grafana_agent is already installed on the host + ansible.builtin.stat: + path: "{{ grafana_agent_install_dir }}/{{ grafana_agent_binary }}" + register: __grafana_agent_is_installed + check_mode: false + +- name: Is Grafana Agent already installed on the host + ansible.builtin.debug: + var: __grafana_agent_is_installed.stat.exists + +- name: Install checks + when: __grafana_agent_is_installed.stat.exists and not __grafana_agent_local_install + block: + - name: Gather currently installed grafana-agent version from the host + ansible.builtin.shell: + cmd: | + {{ grafana_agent_install_dir }}/{{ grafana_agent_binary }} --version | \ + head -n 1 | \ + awk '{ print $3; }' | \ + cut -d 'v' -f 2 + changed_when: false + register: __grafana_agent_current_version_output + check_mode: false + + - name: Set Grafana Agent installed version for the host + ansible.builtin.set_fact: + __grafana_agent_installed_version: "{{ __grafana_agent_current_version_output.stdout }}" + + - name: Grafana Agent installed version on host + ansible.builtin.debug: + var: __grafana_agent_installed_version diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/systemd.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/systemd.yaml new file mode 100644 index 000000000..c66b62e93 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/systemd.yaml @@ -0,0 +1,28 @@ +--- +- name: Assert usage of systemd as an init system + ansible.builtin.assert: + that: ansible_service_mgr == 'systemd' + msg: This role only works with systemd + +- name: Get systemd version # noqa command-instead-of-module + ansible.builtin.command: systemctl --version + changed_when: false + check_mode: false + register: __systemd_version + +- name: Set systemd version fact + ansible.builtin.set_fact: + grafana_agent_systemd_version: "{{ __systemd_version.stdout_lines[0] | regex_replace('^systemd\\s(\\d+).*$', '\\1') }}" + +- name: Fail when _grafana_agent_systemd_dir the directory doesn't exist + block: + - name: Check if _grafana_agent_systemd_dir exists + ansible.builtin.stat: + path: "{{ _grafana_agent_systemd_dir }}" + register: ___grafana_agent_systemd_dir_check + check_mode: false + + - name: Fail when the _grafana_agent_systemd_dir directory does not exist + ansible.builtin.fail: + msg: "The _grafana_agent_systemd_dir ({{ _grafana_agent_systemd_dir }}) does not exist" + when: not ___grafana_agent_systemd_dir_check.stat.exists diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/vars.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/vars.yaml new file mode 100644 index 000000000..dc133a4a1 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/tasks/preflight/vars.yaml @@ -0,0 +1,72 @@ +--- +# Performs initial variable validation +- name: Fail when variables are not defined + ansible.builtin.fail: + msg: "The {{ item }} property must be set" + when: ( vars[item] is not defined ) + with_items: + - grafana_agent_version + - grafana_agent_install_dir + - grafana_agent_binary + - grafana_agent_config_dir + - grafana_agent_config_filename + - grafana_agent_env_file + - grafana_agent_local_tmp_dir + - grafana_agent_wal_dir + - grafana_agent_positions_dir + - grafana_agent_mode + - _grafana_agent_systemd_dir + - _grafana_agent_systemd_unit + - grafana_agent_user + - grafana_agent_user_group + - grafana_agent_user_shell + - grafana_agent_user_createhome + - grafana_agent_local_binary_file + - grafana_agent_flags_extra + - grafana_agent_env_vars + - grafana_agent_env_file_vars + - grafana_agent_provisioned_config_file + - grafana_agent_metrics_config + - grafana_agent_logs_config + - grafana_agent_traces_config + - grafana_agent_integrations_config + +- name: Fail when variables do not have a length + ansible.builtin.fail: + msg: "The {{ item }} property must be valued" + when: ( vars[item] | string | length == 0 ) + with_items: + - grafana_agent_version + - grafana_agent_install_dir + - grafana_agent_binary + - grafana_agent_config_dir + - grafana_agent_config_filename + - grafana_agent_env_file + - grafana_agent_local_tmp_dir + - grafana_agent_wal_dir + - grafana_agent_positions_dir + - grafana_agent_mode + - _grafana_agent_systemd_dir + - _grafana_agent_systemd_unit + - grafana_agent_user + - grafana_agent_user_group + - grafana_agent_user_shell + - grafana_agent_user_createhome + +- name: Fail when variables are not a number + ansible.builtin.fail: + msg: "The {{ item }} property must be number" + when: ( vars[item] is defined and vars[item] is not number) + with_items: [] + +- name: Fail when flags are not a boolean + ansible.builtin.fail: + msg: "The {{ item }} property must be a boolean true or false" + when: ( vars[item] | bool | string | lower ) not in ['true', 'false'] + with_items: + - grafana_agent_user_createhome + +- name: Fail when the agent mode is not "flow" or "static" + ansible.builtin.fail: + msg: "The grafana_agent_mode property must be a boolean 'flow' or 'static'" + when: grafana_agent_mode not in ['flow', 'static'] diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/templates/EnvironmentFile.j2 b/ansible_collections/grafana/grafana/roles/grafana_agent/templates/EnvironmentFile.j2 new file mode 100644 index 000000000..875d941ab --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/templates/EnvironmentFile.j2 @@ -0,0 +1,9 @@ +{{ ansible_managed | comment }} +# Grafana Agent Environment File +AGENT_MODE={{ grafana_agent_mode }} + +GOMAXPROCS={{ ansible_processor_vcpus|default(ansible_processor_count) }} + +{% for key, value in grafana_agent_env_file_vars.items() %} +{{key}}={{value}} +{% endfor %} diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/templates/config.yaml.j2 b/ansible_collections/grafana/grafana/roles/grafana_agent/templates/config.yaml.j2 new file mode 100644 index 000000000..0e427756d --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/templates/config.yaml.j2 @@ -0,0 +1,37 @@ +--- +{{ ansible_managed | comment }} + +################################################################################################# +# Configures the server of the Agent used to enable self-scraping # +################################################################################################# +# Docs: https://grafana.com/docs/agent/latest/configuration/server-config/ +server: + {{ grafana_agent_server_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2) }} + +################################################################################################# +# Configures metric collection # +################################################################################################# +# Docs: https://grafana.com/docs/agent/latest/configuration/metrics-config/ +metrics: + {{ grafana_agent_metrics_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2) }} + +################################################################################################# +# Configures logs collection # +################################################################################################# +# Docs: https://grafana.com/docs/agent/latest/configuration/logs-config/ +logs: + {{ grafana_agent_logs_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2) }} + +################################################################################################# +# Configures traces collection # +################################################################################################# +# Docs: https://grafana.com/docs/agent/latest/configuration/traces-config/ +traces: + {{ grafana_agent_traces_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2) }} + +################################################################################################# +# Configures integrations for the agent # +################################################################################################# +# Docs: https://grafana.com/docs/agent/latest/configuration/integrations/ +integrations: + {{ grafana_agent_integrations_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2) }} diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/templates/grafana-agent.service.j2 b/ansible_collections/grafana/grafana/roles/grafana_agent/templates/grafana-agent.service.j2 new file mode 100644 index 000000000..8a52b5c53 --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/templates/grafana-agent.service.j2 @@ -0,0 +1,62 @@ +{{ ansible_managed | comment }} + +[Unit] +Description=Grafana Agent +Documentation=https://grafana.com/docs/agent/latest/ +After=network-online.target + +[Service] +Type=simple +User={{ grafana_agent_user }} +Group={{ grafana_agent_user_group }} +WorkingDirectory={{ grafana_agent_data_dir }} +{% for key, value in grafana_agent_env_vars.items() %} +Environment={{key}}={{value}} +{% endfor %} +EnvironmentFile={{ grafana_agent_config_dir }}/{{ grafana_agent_env_file}} + +{% if grafana_agent_mode == 'flow' %} +ExecStart={{ grafana_agent_install_dir }}/{{ grafana_agent_binary }} run \ +{% for flag, flag_value in grafana_agent_flags_extra.items() %} +{% if not flag_value %} + --{{ flag }} \ +{% elif flag_value is string %} + --{{ flag }}={{ flag_value }} \ +{% elif flag_value is sequence %} +{% for flag_value_item in flag_value %} + --{{ flag }}={{ flag_value_item }} \ +{% endfor %} +{% endif %} +{% endfor %} + {{ grafana_agent_config_dir }}/{{ grafana_agent_config_filename }} +{% else %} +ExecStart={{ grafana_agent_install_dir }}/{{ grafana_agent_binary }} \ +{% for flag, flag_value in grafana_agent_flags_extra.items() %} +{% if not flag_value %} + --{{ flag }} \ +{% elif flag_value is string %} + --{{ flag }}={{ flag_value }} \ +{% elif flag_value is sequence %} +{% for flag_value_item in flag_value %} + --{{ flag }}={{ flag_value_item }} \ +{% endfor %} +{% endif %} +{% endfor %} + --config.file={{ grafana_agent_config_dir }}/{{ grafana_agent_config_filename }} +{% endif %} + +SyslogIdentifier=grafana-agent +Restart=always + +{% if grafana_agent_systemd_version | int >= 232 %} +ProtectSystem=strict +ProtectControlGroups=true +ProtectKernelModules=true +ProtectKernelTunables=yes +{% else %} +ProtectSystem=full +{% endif %} +ReadWritePaths=/tmp {{ grafana_agent_data_dir }} {{ grafana_agent_positions_dir }} {{ grafana_agent_wal_dir }} + +[Install] +WantedBy=multi-user.target diff --git a/ansible_collections/grafana/grafana/roles/grafana_agent/vars/main.yaml b/ansible_collections/grafana/grafana/roles/grafana_agent/vars/main.yaml new file mode 100644 index 000000000..75353fc8f --- /dev/null +++ b/ansible_collections/grafana/grafana/roles/grafana_agent/vars/main.yaml @@ -0,0 +1,29 @@ +--- +_grafana_agent_github_org: grafana +_grafana_agent_github_repo: agent + +# set the go cpu arch +_download_cpu_arch_map: + i386: '386' + x86_64: amd64 + aarch64: arm64 + armv7l: armv7 + armv6l: armv6 + +_grafana_agent_cpu_arch: "{{ _download_cpu_arch_map[ansible_architecture] | default(ansible_architecture) }}" + +# set the go os family +_grafana_agent_os_family: "{{ ansible_system | lower }}" + +# set the name of the archive file to download +_grafana_agent_download_archive_file: "grafana-agent-{{ _grafana_agent_os_family }}-{{ _grafana_agent_cpu_arch }}.zip" + +# set the name of the binary file +_grafana_agent_download_binary_file: "grafana-agent-{{ _grafana_agent_os_family }}-{{ _grafana_agent_cpu_arch }}" + +# systemd info +_grafana_agent_systemd_dir: /lib/systemd/system/ +_grafana_agent_systemd_unit: grafana-agent.service + +# Server http address, used in self health check after start +_grafana_agent_healthcheck_endpoint: "http://{{ grafana_agent_flags_extra['server.http.address'] if grafana_agent_flags_extra['server.http.address'] is defined else '127.0.0.1:12345' }}/-/ready" diff --git a/ansible_collections/grafana/grafana/tests/integration/targets/alert_contact_point/tasks/main.yml b/ansible_collections/grafana/grafana/tests/integration/targets/alert_contact_point/tasks/main.yml index c6727fa63..a038d4493 100644 --- a/ansible_collections/grafana/grafana/tests/integration/targets/alert_contact_point/tasks/main.yml +++ b/ansible_collections/grafana/grafana/tests/integration/targets/alert_contact_point/tasks/main.yml @@ -1,17 +1,18 @@ +--- - name: Create Alerting contact point grafana.grafana.alert_contact_point: name: ops-email uid: opsemail type: email - settings: { - addresses: "ops@mydomain.com,devs@mydomain.com" - } - stack_slug: "{{ stack_name }}" + settings: + addresses: ops@mydomain.com,devs@mydomain.com + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: present register: add_result -- assert: +- name: Add Check + ansible.builtin.assert: that: - add_result.failed == false - add_result.output.provenance == "api" @@ -21,15 +22,15 @@ name: ops-email uid: opsemail type: email - settings: { - addresses: "ops@mydomain.com,devs@mydomain.com" - } - stack_slug: "{{ stack_name }}" + settings: + addresses: ops@mydomain.com,devs@mydomain.com + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: present register: idempotent_result -- assert: +- name: Changed Check + ansible.builtin.assert: that: - idempotent_result.changed == false - idempotent_result.output.provenance == "api" @@ -39,15 +40,15 @@ name: ops-email uid: opsemail type: email - settings: { - addresses: "ops@mydomain.com,devs@mydomain.com,admin@mydomain.com" - } - stack_slug: "{{ stack_name }}" + settings: + addresses: "ops@mydomain.com,devs@mydomain.com,admin@mydomain.com" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: present register: update_result -- assert: +- name: Failed Check + ansible.builtin.assert: that: - update_result.failed == false - update_result.output.provenance == "api" @@ -57,15 +58,15 @@ name: ops-email uid: opsemail type: email - settings: { - addresses: "ops@mydomain.com,devs@mydomain.com,admin@mydomain.com" - } - stack_slug: "{{ stack_name }}" + settings: + addresses: "ops@mydomain.com,devs@mydomain.com,admin@mydomain.com" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: absent register: delete_result -- assert: +- name: Delete Check + ansible.builtin.assert: that: - delete_result.failed == false - - delete_result.output.message == "contactpoint deleted" \ No newline at end of file + - delete_result.output.message == "contactpoint deleted" diff --git a/ansible_collections/grafana/grafana/tests/integration/targets/alert_notification_policy/tasks/main.yml b/ansible_collections/grafana/grafana/tests/integration/targets/alert_notification_policy/tasks/main.yml index 681ff53a5..c88bb3f76 100644 --- a/ansible_collections/grafana/grafana/tests/integration/targets/alert_notification_policy/tasks/main.yml +++ b/ansible_collections/grafana/grafana/tests/integration/targets/alert_notification_policy/tasks/main.yml @@ -1,6 +1,6 @@ - name: Set Notification policy tree grafana.grafana.alert_notification_policy: - stack_slug: "{{ stack_name }}" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" routes: [ { @@ -13,4 +13,3 @@ - assert: that: - result.failed == false - - result.output.provenance == "api" \ No newline at end of file diff --git a/ansible_collections/grafana/grafana/tests/integration/targets/cloud_api_key/tasks/main.yml b/ansible_collections/grafana/grafana/tests/integration/targets/cloud_api_key/tasks/main.yml index 86c3fcfc5..3e83a6810 100644 --- a/ansible_collections/grafana/grafana/tests/integration/targets/cloud_api_key/tasks/main.yml +++ b/ansible_collections/grafana/grafana/tests/integration/targets/cloud_api_key/tasks/main.yml @@ -1,17 +1,19 @@ +--- - name: Create Grafana Cloud API key grafana.grafana.cloud_api_key: name: ansible-integration-test role: Admin org_slug: "{{ org_name }}" existing_cloud_api_key: "{{ grafana_cloud_api_key }}" - fail_if_already_created: False + fail_if_already_created: false state: present register: add_result -- assert: +- name: Add Check + ansible.builtin.assert: that: - add_result.output.name == "ansible-integration-test" - when: add_result.output.name is defined + when: add_result.output.name is defined - name: Re-run previous task grafana.grafana.cloud_api_key: @@ -19,13 +21,13 @@ role: Admin org_slug: "{{ org_name }}" existing_cloud_api_key: "{{ grafana_cloud_api_key }}" - fail_if_already_created: False + fail_if_already_created: false state: present register: update_result -- assert: +- name: Update Check + ansible.builtin.assert: that: - - update_result.changed == false - update_result.output == "A Cloud API key with the same name already exists" - name: Delete Grafana Cloud API key @@ -37,7 +39,7 @@ state: absent register: delete_result -- assert: +- name: Delete Check + ansible.builtin.assert: that: - - delete_result.changed == true - delete_result.output == "Cloud API key is deleted" diff --git a/ansible_collections/grafana/grafana/tests/integration/targets/cloud_plugin/tasks/main.yml b/ansible_collections/grafana/grafana/tests/integration/targets/cloud_plugin/tasks/main.yml index 125de8025..2bb0ab265 100644 --- a/ansible_collections/grafana/grafana/tests/integration/targets/cloud_plugin/tasks/main.yml +++ b/ansible_collections/grafana/grafana/tests/integration/targets/cloud_plugin/tasks/main.yml @@ -1,55 +1,56 @@ +--- - name: Add a plugin grafana.grafana.cloud_plugin: name: grafana-github-datasource version: 1.0.14 - stack_slug: "{{ stack_name }}" + stack_slug: "{{ test_stack_name }}" cloud_api_key: "{{ grafana_cloud_api_key }}" state: present register: add_result -- assert: +- name: Add Check + ansible.builtin.assert: that: - - add_result.changed == true - add_result.pluginName == "GitHub" - name: Idempotency Check grafana.grafana.cloud_plugin: name: grafana-github-datasource version: 1.0.14 - stack_slug: "{{ stack_name }}" + stack_slug: "{{ test_stack_name }}" cloud_api_key: "{{ grafana_cloud_api_key }}" state: present register: idempotency_result -- assert: +- name: Idempotency Check + ansible.builtin.assert: that: - - idempotency_result.changed == false - idempotency_result.pluginName == "GitHub" - name: Update a plugin grafana.grafana.cloud_plugin: name: grafana-github-datasource version: 1.0.15 - stack_slug: "{{ stack_name }}" + stack_slug: "{{ test_stack_name }}" cloud_api_key: "{{ grafana_cloud_api_key }}" state: present register: update_result -- assert: +- name: Update Check + ansible.builtin.assert: that: - - update_result.changed == true - update_result.pluginName == "GitHub" - name: Delete a plugin grafana.grafana.cloud_plugin: name: grafana-github-datasource version: 1.0.15 - stack_slug: "{{ stack_name }}" + stack_slug: "{{ test_stack_name }}" cloud_api_key: "{{ grafana_cloud_api_key }}" state: absent register: delete_result -- assert: +- name: Delete Check + ansible.builtin.assert: that: - - delete_result.changed == true - - delete_result.pluginName == "GitHub" \ No newline at end of file + - delete_result.pluginName == "GitHub" diff --git a/ansible_collections/grafana/grafana/tests/integration/targets/cloud_stack/tasks/main.yml b/ansible_collections/grafana/grafana/tests/integration/targets/cloud_stack/tasks/main.yml deleted file mode 100644 index 861624bf0..000000000 --- a/ansible_collections/grafana/grafana/tests/integration/targets/cloud_stack/tasks/main.yml +++ /dev/null @@ -1,30 +0,0 @@ -- name: Create a Grafana Cloud stack - grafana.grafana.cloud_stack: - name: "{{ test_stack_name }}" - stack_slug: "{{ test_stack_name }}" - cloud_api_key: "{{ grafana_cloud_api_key }}" - org_slug: "{{ org_name }}" - state: present - register: create_result - -- assert: - that: - - create_result.url == "https://" + "{{ test_stack_name }}" + ".grafana.net" - -- name: Sleep for 30 seconds - ansible.builtin.wait_for: - timeout: 30 - -- name: Delete a Grafana Cloud stack - grafana.grafana.cloud_stack: - name: "{{ test_stack_name }}" - stack_slug: "{{ test_stack_name }}" - cloud_api_key: "{{ grafana_cloud_api_key }}" - org_slug: "{{ org_name }}" - state: absent - register: delete_result - -- assert: - that: - - delete_result.changed == true - - delete_result.url == "https://" + "{{ test_stack_name }}" + ".grafana.net" diff --git a/ansible_collections/grafana/grafana/tests/integration/targets/create_cloud_stack/tasks/main.yml b/ansible_collections/grafana/grafana/tests/integration/targets/create_cloud_stack/tasks/main.yml new file mode 100644 index 000000000..642b528b7 --- /dev/null +++ b/ansible_collections/grafana/grafana/tests/integration/targets/create_cloud_stack/tasks/main.yml @@ -0,0 +1,18 @@ +--- +- name: Create a Grafana Cloud stack + grafana.grafana.cloud_stack: + name: "{{ test_stack_name }}" + stack_slug: "{{ test_stack_name }}" + cloud_api_key: "{{ grafana_cloud_api_key }}" + org_slug: "{{ org_name }}" + state: present + register: create_result + +- name: Create Check + ansible.builtin.assert: + that: + - create_result.url == "https://" + "{{ test_stack_name }}" + ".grafana.net" + +- name: Sleep for 45 seconds + ansible.builtin.wait_for: + timeout: 45 diff --git a/ansible_collections/grafana/grafana/tests/integration/targets/dashboard/tasks/main.yml b/ansible_collections/grafana/grafana/tests/integration/targets/dashboard/tasks/main.yml index 242a2883c..8b2f88b50 100644 --- a/ansible_collections/grafana/grafana/tests/integration/targets/dashboard/tasks/main.yml +++ b/ansible_collections/grafana/grafana/tests/integration/targets/dashboard/tasks/main.yml @@ -1,47 +1,48 @@ +--- - name: Create/Update a dashboard grafana.grafana.dashboard: - dashboard: { - "dashboard": { - "uid": test1234, - "title": "Ansible Integration Test", - "tags": [ "templated" ], - "timezone": "browser", - "schemaVersion": 16, - "version": 0, - "refresh": "25s" - }, - "overwrite": true - } - stack_slug: "{{ stack_name }}" + dashboard: + dashboard: + uid: test1234 + title: Ansible Integration Test + tags: + - templated + timezone: browser + schemaVersion: 16 + refresh: 25s + version: 0 + overwrite: true + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: present register: result_present -- assert: +- name: Create/Update Check + ansible.builtin.assert: that: - result_present.changed == true - result_present.output.status == "success" - name: Delete dashboard grafana.grafana.dashboard: - dashboard: { - "dashboard": { - "uid": test1234, - "title": "Ansible Integration Test", - "tags": [ "templated" ], - "timezone": "browser", - "schemaVersion": 16, - "version": 0, - "refresh": "25s" - }, - "overwrite": true - } - stack_slug: "{{ stack_name }}" + dashboard: + dashboard: + uid: test1234 + title: Ansible Integration Test + tags: + - templated + timezone: browser + schemaVersion: 16 + version: 0 + refresh: 25s + overwrite: true + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: absent register: result_absent -- assert: +- name: Delete Check + ansible.builtin.assert: that: - result_absent.changed == true - - result_absent.output.message == "Dashboard Ansible Integration Test deleted" \ No newline at end of file + - result_absent.output.message == "Dashboard Ansible Integration Test deleted" diff --git a/ansible_collections/grafana/grafana/tests/integration/targets/datasource/tasks/main.yml b/ansible_collections/grafana/grafana/tests/integration/targets/datasource/tasks/main.yml index 1925b4778..16e5a4ae0 100644 --- a/ansible_collections/grafana/grafana/tests/integration/targets/datasource/tasks/main.yml +++ b/ansible_collections/grafana/grafana/tests/integration/targets/datasource/tasks/main.yml @@ -1,23 +1,48 @@ +--- - name: Create/Update a Data Source grafana.grafana.datasource: - dataSource: { - name: "ansible-integration", - type: "influxdb", - url: "https://grafana.github.com/grafana-ansible-collection", - user: "user", + dataSource: + name: ansible-integration + type: influxdb + url: https://grafana.github.com/grafana-ansible-collection + user: user secureJsonData: - { password: "password" }, - database: "db-name", - id: 123, - uid: "ansibletest", - access: "proxy" - } - stack_slug: "{{ stack_name }}" + password: password + database: db-name + id: 123 + uid: ansibletest + access: proxy + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: present register: create_result -- assert: +- name: Create Check + ansible.builtin.assert: that: - create_result.changed == true - - create_result.output.message == "Datasource added" or create_result.output.message == "Datasource updated" \ No newline at end of file + - create_result.output.message == "Datasource added" or create_result.output.message == "Datasource updated" + +- name: Delete a Data Source + grafana.grafana.datasource: + dataSource: + name: ansible-integration + type: influxdb + url: https://grafana.github.com/grafana-ansible-collection + user: user + secureJsonData: + password: password + database: db-name + id: 123 + uid: ansibletest + access: proxy + grafana_url: "{{ grafana_url }}" + grafana_api_key: "{{ grafana_api_key }}" + state: absent + register: delete_result + +- name: Delete Check + ansible.builtin.assert: + that: + - delete_result.changed == true + - delete_result.output.response == "Data source deleted" diff --git a/ansible_collections/grafana/grafana/tests/integration/targets/delete_cloud_stack/tasks/main.yml b/ansible_collections/grafana/grafana/tests/integration/targets/delete_cloud_stack/tasks/main.yml new file mode 100644 index 000000000..39c2e9cc4 --- /dev/null +++ b/ansible_collections/grafana/grafana/tests/integration/targets/delete_cloud_stack/tasks/main.yml @@ -0,0 +1,19 @@ +--- +- name: Delete a Grafana Cloud stack + grafana.grafana.cloud_stack: + name: "{{ test_stack_name }}" + stack_slug: "{{ test_stack_name }}" + cloud_api_key: "{{ grafana_cloud_api_key }}" + org_slug: "{{ org_name }}" + state: absent + register: delete_result + +- name: Delete Check + ansible.builtin.assert: + that: + - delete_result.changed == true + - delete_result.url == "https://" + "{{ test_stack_name }}" + ".grafana.net" + +- name: Sleep for 45 seconds + ansible.builtin.wait_for: + timeout: 45 diff --git a/ansible_collections/grafana/grafana/tests/integration/targets/folder/tasks/main.yml b/ansible_collections/grafana/grafana/tests/integration/targets/folder/tasks/main.yml index 452aca67e..14d66c3fa 100644 --- a/ansible_collections/grafana/grafana/tests/integration/targets/folder/tasks/main.yml +++ b/ansible_collections/grafana/grafana/tests/integration/targets/folder/tasks/main.yml @@ -1,14 +1,16 @@ +--- - name: Create/Update a Folder in Grafana grafana.grafana.folder: title: Ansible Integration test uid: test123 overwrite: true - stack_slug: "{{ stack_name }}" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: present register: create_result -- assert: +- name: Create Check + ansible.builtin.assert: that: - create_result.failed == false @@ -17,12 +19,29 @@ title: Ansible Integration test uid: test123 overwrite: true - stack_slug: "{{ stack_name }}" + grafana_url: "{{ grafana_url }}" grafana_api_key: "{{ grafana_api_key }}" state: absent register: delete_result -- assert: +- name: Delete Check + ansible.builtin.assert: that: - delete_result.output.status == 200 - delete_result.output.response == "Folder has been succesfuly deleted" + +- name: Delete Idempotency Check + grafana.grafana.folder: + title: Ansible Integration test + uid: test123 + overwrite: true + grafana_url: "{{ grafana_url }}" + grafana_api_key: "{{ grafana_api_key }}" + state: absent + register: delete_result + +- name: Delete Check + ansible.builtin.assert: + that: + - delete_result.output.status == 200 + - delete_result.output.response == "Folder does not exist" diff --git a/ansible_collections/grafana/grafana/tests/integration/targets/molecule-grafana-alternative/runme.sh b/ansible_collections/grafana/grafana/tests/integration/targets/molecule-grafana-alternative/runme.sh new file mode 100755 index 000000000..87129f7e4 --- /dev/null +++ b/ansible_collections/grafana/grafana/tests/integration/targets/molecule-grafana-alternative/runme.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +version="0.1.3" +src="https://github.com/gardar/ansible-test-molecule/releases/download/$version/ansible-test-molecule.sh" + +# shellcheck disable=SC1090 +if [[ -v GITHUB_TOKEN ]] +then + source <(curl -L -s -H "Authorization: token $GITHUB_TOKEN" $src) +else + source <(curl -L -s $src) +fi diff --git a/ansible_collections/grafana/grafana/tests/integration/targets/molecule-grafana-default/runme.sh b/ansible_collections/grafana/grafana/tests/integration/targets/molecule-grafana-default/runme.sh new file mode 100755 index 000000000..87129f7e4 --- /dev/null +++ b/ansible_collections/grafana/grafana/tests/integration/targets/molecule-grafana-default/runme.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +version="0.1.3" +src="https://github.com/gardar/ansible-test-molecule/releases/download/$version/ansible-test-molecule.sh" + +# shellcheck disable=SC1090 +if [[ -v GITHUB_TOKEN ]] +then + source <(curl -L -s -H "Authorization: token $GITHUB_TOKEN" $src) +else + source <(curl -L -s $src) +fi diff --git a/ansible_collections/grafana/grafana/tools/includes/logging.sh b/ansible_collections/grafana/grafana/tools/includes/logging.sh new file mode 100755 index 000000000..261349582 --- /dev/null +++ b/ansible_collections/grafana/grafana/tools/includes/logging.sh @@ -0,0 +1,123 @@ +#!/usr/bin/env bash + +LOG_LEVEL=${LOG_LEVEL:=6} # 7 = debug -> 0 = emergency +NO_COLOR="${NO_COLOR:-}" +# shellcheck disable=SC2034 +TRACE="0" + +# _log +# ----------------------------------- +# Handles all logging, all log messages are output to stderr so stdout can still be piped +# Example: _log "info" "Some message" +# ----------------------------------- +# shellcheck disable=SC2034 +_log () { + local log_level="${1}" # first option is the level, the rest is the message + shift + local color_success="\\x1b[32m" + local color_debug="\\x1b[36m" + local color_info="\\x1b[90m" + local color_notice="\\x1b[34m" + local color_warning="\\x1b[33m" + local color_error="\\x1b[31m" + local color_critical="\\x1b[1;31m" + local color_alert="\\x1b[1;33;41m" + local color_emergency="\\x1b[1;4;5;33;41m" + local colorvar="color_${log_level}" + local color="${!colorvar:-${color_error}}" + local color_reset="\\x1b[0m" + + # If no color is set or a non-recognized terminal is used don't use colors + if [[ "${NO_COLOR:-}" = "true" ]] || { [[ "${TERM:-}" != "xterm"* ]] && [[ "${TERM:-}" != "screen"* ]]; } || [[ ! -t 2 ]]; then + if [[ "${NO_COLOR:-}" != "false" ]]; then + color=""; + color_reset=""; + fi + fi + + # all remaining arguments are to be printed + local log_line="" + + while IFS=$'\n' read -r log_line; do + echo -e "$(date +"%Y-%m-%d %H:%M:%S %Z") ${color}[${log_level}]${color_reset} ${log_line}" 1>&2 + done <<< "${@:-}" +} + +# emergency +# ----------------------------------- +# Handles emergency logging +# ----------------------------------- +emergency() { + _log emergency "${@}"; exit 1; +} + +# success +# ----------------------------------- +# Handles success logging +# ----------------------------------- +success() { + _log success "${@}"; true; +} + +# alert +# ----------------------------------- +# Handles alert logging +# ----------------------------------- +alert() { + [[ "${LOG_LEVEL:-0}" -ge 1 ]] && _log alert "${@}"; + true; +} + +# critical +# ----------------------------------- +# Handles critical logging +# ----------------------------------- +critical() { + [[ "${LOG_LEVEL:-0}" -ge 2 ]] && _log critical "${@}"; + true; +} + +# error +# ----------------------------------- +# Handles error logging +# ----------------------------------- +error() { + [[ "${LOG_LEVEL:-0}" -ge 3 ]] && _log error "${@}"; + true; +} + +# warning +# ----------------------------------- +# Handles warning logging +# ----------------------------------- +warning() { + [[ "${LOG_LEVEL:-0}" -ge 4 ]] && _log warning "${@}"; + true; +} + +# notice +# ----------------------------------- +# Handles notice logging +# ----------------------------------- +notice() { + [[ "${LOG_LEVEL:-0}" -ge 5 ]] && _log notice "${@}"; + true; +} + +# info +# ----------------------------------- +# Handles info logging +# ----------------------------------- +info() { + [[ "${LOG_LEVEL:-0}" -ge 6 ]] && _log info "${@}"; + true; +} + +# debug +# ----------------------------------- +# Handles debug logging and prepends the name of the that called debug in front of the message +# ----------------------------------- +debug() { + [[ "${LOG_LEVEL:-0}" -ge 7 ]] && _log debug "${FUNCNAME[1]}() ${*}"; + true; +} diff --git a/ansible_collections/grafana/grafana/tools/includes/utils.sh b/ansible_collections/grafana/grafana/tools/includes/utils.sh new file mode 100755 index 000000000..13264ea49 --- /dev/null +++ b/ansible_collections/grafana/grafana/tools/includes/utils.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash + +# heading +# ----------------------------------- +# Print standard heading +# ----------------------------------- +heading() { + local title="${1}" + local message="${2}" + local width="75" + local orange="\\033[38;5;202m" + local reset="\\033[0m" + local bold="\\x1b[1m" + echo "" + echo -e "${orange} ▒▒▓▓▒▒▒▓ ${reset} ____ __ _ _ " + echo -e "${orange} ▓▓▓ ▒ ${reset} / ___| _ __ __ _ / _| __ _ _ __ __ _ | | __ _ | |__ ___ " + echo -e "${orange} ▒▓ ▒▒▒▒▓ ${reset} | | _ | '__| / _ || |_ / _ || '_ \\ / _ | | | / _ || '_ \\ / __|" + echo -e "${orange} ▒▓▓ ▒ ▒▒ ${reset} | |_| || | | (_| || _|| (_| || | | || (_| | | |___ | (_| || |_) | \\__\\" + echo -e "${orange} ▒▓▒ ▒▓ ${reset} \\____||_| \\__,_||_| \\__,_||_| |_| \\__,_| |_____| \\__,_||_.__/ |___/" + echo -e "${orange} ▒▒▒ ▒▒▒ ${reset} " + echo -e "${orange} ▒▒▒▒▒ ${reset} $(repeat $(( ((width - ${#title}) - 2) / 2)) " ")${bold}$title${reset}" + echo -e "${reset} $(repeat $(( ((width - ${#message}) - 2) / 2)) " ")$message${reset}" + echo "" +} + +# repeat +# ----------------------------------- +# Repeat a Character N number of times +# ----------------------------------- +repeat(){ + local times="${1:-80}" + local character="${2:-=}" + local start=1 + local range + range=$(seq "$start" "$times") + local str="" + # shellcheck disable=SC2034 + for i in $range; do + str="$str${character}" + done + echo "$str" +} + +# lintWarning +# ----------------------------------- +# Output a Lint Warning Message +# ----------------------------------- +lintWarning() { + local msg="${1}" + local color_warning="\\x1b[33m" + local color_reset="\\x1b[0m" + local bold="\\x1b[1m" + echo -e " ‣ ${color_warning}${bold}[warn]${color_reset} $msg" +} + +# lintError +# ----------------------------------- +# Output a Lint Error Message +# ----------------------------------- +lintError() { + local msg="${1}" + local color_error="\\x1b[31m" + local color_reset="\\x1b[0m" + local bold="\\x1b[1m" + echo -e " ‣ ${color_error}${bold}[error]${color_reset} $msg" +} diff --git a/ansible_collections/grafana/grafana/tools/lint-ansible.sh b/ansible_collections/grafana/grafana/tools/lint-ansible.sh new file mode 100755 index 000000000..47cb90b2f --- /dev/null +++ b/ansible_collections/grafana/grafana/tools/lint-ansible.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +source "$(pwd)/tools/includes/utils.sh" + +source "./tools/includes/logging.sh" + +# output the heading +heading "Grafana Ansible Collection" "Performing Ansible Linting using ansible-lint" + +# make sure pipenv exists +if [[ "$(command -v pipenv)" = "" ]]; then + echo >&2 "pipenv command is required, see (https://pipenv.pypa.io/en/latest/) or run: brew install pipenv"; + exit 1; +fi + +# make sure yamllint exists +if [[ "$(pipenv run pip freeze | grep -c "ansible-lint")" == "0" ]]; then + echo >&2 "ansible-lint command is required, see (https://pypi.org/project/ansible-lint/). Run \"make install\" to install it."; + exit 1; +fi + +# determine whether or not the script is called directly or sourced +(return 0 2>/dev/null) && sourced=1 || sourced=0 + +# run yamllint +echo "$(pwd)/.ansible-lint" +pipenv run ansible-lint --config-file "$(pwd)/.ansible-lint" --strict +statusCode="$?" + +if [[ "$statusCode" == "0" ]]; then + echo "no issues found" + echo "" +fi + +echo "" +# if the script was called by another, send a valid exit code +if [[ "$sourced" == "1" ]]; then + return "$statusCode" +fi diff --git a/ansible_collections/grafana/grafana/tools/lint-editorconfig.sh b/ansible_collections/grafana/grafana/tools/lint-editorconfig.sh new file mode 100755 index 000000000..9150f001b --- /dev/null +++ b/ansible_collections/grafana/grafana/tools/lint-editorconfig.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +source "$(pwd)/tools/includes/utils.sh" + +source "./tools/includes/logging.sh" + +# output the heading +heading "Grafana Ansible Collection" "Performing Editorconfig Linting using editorconfig-checker" + +# check to see if remark is installed +if [[ ! -f "$(pwd)"/node_modules/.bin/editorconfig-checker ]]; then + emergency "editorconfig-checker node module is not installed, please run: make install"; +fi + +# determine whether or not the script is called directly or sourced +(return 0 2>/dev/null) && sourced=1 || sourced=0 + +statusCode=0 +./node_modules/.bin/editorconfig-checker -config="$(pwd)/.editorconfig" -exclude "LICENSE|.+\.txt|.+\.py" +currentCode="$?" +# only override the statusCode if it is 0 +if [[ "$statusCode" == 0 ]]; then + statusCode="$currentCode" +fi + +if [[ "$statusCode" == "0" ]]; then + echo "no issues found" + echo "" +fi + +echo "" + +# if the script was called by another, send a valid exit code +if [[ "$sourced" == "1" ]]; then + return "$statusCode" +else + exit "$statusCode" +fi diff --git a/ansible_collections/grafana/grafana/tools/lint-markdown.sh b/ansible_collections/grafana/grafana/tools/lint-markdown.sh new file mode 100755 index 000000000..4d919ed26 --- /dev/null +++ b/ansible_collections/grafana/grafana/tools/lint-markdown.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +source "$(pwd)/tools/includes/utils.sh" + +source "./tools/includes/logging.sh" + +# output the heading +heading "Grafana Ansible Collection" "Performing Markdown Linting using markdownlint" + +# check to see if remark is installed +if [[ ! -f "$(pwd)"/node_modules/.bin/markdownlint-cli2 ]]; then + emergency "markdownlint-cli2 node module is not installed, please run: make install"; +fi + +# determine whether or not the script is called directly or sourced +(return 0 2>/dev/null) && sourced=1 || sourced=0 + +statusCode=0 +while read -r dir; do + info "Checking file/directory: $dir" + ./node_modules/.bin/markdownlint-cli2-config "$(pwd)/.markdownlint.yaml" "$dir" + currentCode="$?" + # if the current code is 0, output the file name for logging purposes + if [[ "$currentCode" == 0 ]]; then + echo -e "\\x1b[32m$dir\\x1b[0m: no issues found" + fi + # only override the statusCode if it is 0 + if [[ "$statusCode" == 0 ]]; then + statusCode="$currentCode" + fi + echo "" +done < <(find . -type f -name "*.md" -not -path "./node_modules/*" -not -path "./.git/*" -print0 | \ + xargs -0 dirname | \ + sort -nr | \ + uniq | \ + sort | \ + xargs printf -- '%s/*.md\n' | \ + sed 's|\./\*\.md|./README.md|' + ) + +echo "" +echo "" + +# if the script was called by another, send a valid exit code +if [[ "$sourced" == "1" ]]; then + return "$statusCode" +else + exit "$statusCode" +fi diff --git a/ansible_collections/grafana/grafana/tools/lint-shell.sh b/ansible_collections/grafana/grafana/tools/lint-shell.sh new file mode 100755 index 000000000..633c7bed1 --- /dev/null +++ b/ansible_collections/grafana/grafana/tools/lint-shell.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +source "$(pwd)/tools/includes/utils.sh" + +source "./tools/includes/logging.sh" + +# output the heading +heading "Grafana Ansible Collection" "Performing Shell Linting using shellcheck" + +# check to see if shellcheck is installed +if [[ "$(command -v shellcheck)" = "" ]]; then + emergency "shellcheck is required if running lint locally, see: (https://shellcheck.net) or run: brew install nvm && nvm install 18"; +fi + +# determine whether or not the script is called directly or sourced +(return 0 2>/dev/null) && sourced=1 || sourced=0 + +statusCode=0 +while read -r file; do + shellcheck \ + --external-sources \ + --shell bash \ + --source-path "$(dirname "$file")" \ + "$file" + currentCode="$?" + # if the current code is 0, output the file name for logging purposes + if [[ "$currentCode" == 0 ]]; then + echo -e "\\x1b[32m$file\\x1b[0m: no issues found" + else + echo "" + fi + # only override the statusCode if it is 0 + if [[ "$statusCode" == 0 ]]; then + statusCode="$currentCode" + fi +done < <(find . -type f -name "*.sh" -not -path "./node_modules/*" -not -path "./.git/*") + +echo "" +echo "" + +# if the script was called by another, send a valid exit code +if [[ "$sourced" == "1" ]]; then + return "$statusCode" +else + exit "$statusCode" +fi diff --git a/ansible_collections/grafana/grafana/tools/lint-text.sh b/ansible_collections/grafana/grafana/tools/lint-text.sh new file mode 100755 index 000000000..17e4b5df5 --- /dev/null +++ b/ansible_collections/grafana/grafana/tools/lint-text.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +source "$(pwd)/tools/includes/utils.sh" + +source "./tools/includes/logging.sh" + +# output the heading +heading "Grafana Ansible Collections" "Performing Text Linting using textlint" + +# check to see if remark is installed +if [[ ! -f "$(pwd)"/node_modules/.bin/textlint ]]; then + emergency "remark node module is not installed, please run: make install"; +fi + +# determine whether or not the script is called directly or sourced +(return 0 2>/dev/null) && sourced=1 || sourced=0 + +statusCode=0 +while read -r file; do + "$(pwd)"/node_modules/.bin/textlint --config "$(pwd)/.textlintrc" "$file" + currentCode="$?" + # if the current code is 0, output the file name for logging purposes + if [[ "$currentCode" == 0 ]]; then + echo -e "\\x1b[32m$file\\x1b[0m: no issues found" + fi + # only override the statusCode if it is 0 + if [[ "$statusCode" == 0 ]]; then + statusCode="$currentCode" + fi +done < <(find . -type f -name "*.md" -not -path "./node_modules/*" -not -path "./.git/*") + +echo "" +echo "" + +# if the script was called by another, send a valid exit code +if [[ "$sourced" == "1" ]]; then + return "$statusCode" +else + exit "$statusCode" +fi diff --git a/ansible_collections/grafana/grafana/tools/lint-yaml.sh b/ansible_collections/grafana/grafana/tools/lint-yaml.sh new file mode 100755 index 000000000..51deee6f7 --- /dev/null +++ b/ansible_collections/grafana/grafana/tools/lint-yaml.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +source "$(pwd)/tools/includes/utils.sh" + +source "./tools/includes/logging.sh" + +# output the heading +heading "Grafana Ansible Collection" "Performing YAML Linting using yamllint" + +# make sure pipenv exists +if [[ "$(command -v pipenv)" = "" ]]; then + echo >&2 "pipenv command is required, see (https://pipenv.pypa.io/en/latest/) or run: brew install pipenv"; + exit 1; +fi + +# make sure yamllint exists +if [[ "$(pipenv run pip freeze | grep -c "yamllint")" == "0" ]]; then + echo >&2 "yamllint command is required, see (https://pypi.org/project/yamllint/). Run \"make install\" to install it."; + exit 1; +fi + +# determine whether or not the script is called directly or sourced +(return 0 2>/dev/null) && sourced=1 || sourced=0 + +# run yamllint +pipenv run yamllint --strict --config-file "$(pwd)/.yamllint" . +statusCode="$?" + +if [[ "$statusCode" == "0" ]]; then + echo "no issues found" + echo "" +fi + +# if the script was called by another, send a valid exit code +if [[ "$sourced" == "1" ]]; then + return "$statusCode" +fi diff --git a/ansible_collections/grafana/grafana/tools/setup.sh b/ansible_collections/grafana/grafana/tools/setup.sh new file mode 100755 index 000000000..9a047e3bd --- /dev/null +++ b/ansible_collections/grafana/grafana/tools/setup.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +source "$(pwd)/tools/includes/utils.sh" + +source "./tools/includes/logging.sh" + +# output the heading +heading "Grafana Ansible Collection" "Performing Setup Checks" + +# make sure Node exists +info "Checking to see if Node is installed" +if [[ "$(command -v node)" = "" ]]; then + warning "node is required if running lint locally, see: (https://nodejs.org) or run: brew install nvm && nvm install 18"; +else + success "node is installed" +fi + +# make sure yarn exists +info "Checking to see if yarn is installed" +if [[ "$(command -v yarn)" = "" ]]; then + warning "yarn is required if running lint locally, see: (https://yarnpkg.com) or run: brew install yarn"; +else + success "yarn is installed" +fi + +# make sure shellcheck exists +info "Checking to see if shellcheck is installed" +if [[ "$(command -v shellcheck)" = "" ]]; then + warning "shellcheck is required if running lint locally, see: (https://shellcheck.net) or run: brew install nvm && nvm install 18"; +else + success "shellcheck is installed" +fi + +# make sure pipenv exists +if [[ "$(command -v pipenv)" = "" ]]; then + warning "pipenv command is required, see (https://pipenv.pypa.io/en/latest/) or run: brew install pipenv"; +else + success "pipenv is installed" +fi diff --git a/ansible_collections/grafana/grafana/yarn.lock b/ansible_collections/grafana/grafana/yarn.lock new file mode 100644 index 000000000..d39b9d6d5 --- /dev/null +++ b/ansible_collections/grafana/grafana/yarn.lock @@ -0,0 +1,1721 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@azu/format-text@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@azu/format-text/-/format-text-1.0.2.tgz#abd46dab2422e312bd1bfe36f0d427ab6039825d" + integrity sha512-Swi4N7Edy1Eqq82GxgEECXSSLyn6GOb5htRFPzBDdUkECGXtlf12ynO5oJSpWKPwCaUssOu7NfhDcCWpIC6Ywg== + +"@azu/style-format@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@azu/style-format/-/style-format-1.0.1.tgz#b3643af0c5fee9d53e69a97c835c404bdc80f792" + integrity sha512-AHcTojlNBdD/3/KxIKlg8sxIWHfOtQszLvOpagLTO+bjC3u7SAszu1lf//u7JJC50aUSH+BVWDD/KvaA6Gfn5g== + dependencies: + "@azu/format-text" "^1.0.1" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@textlint/ast-node-types@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/ast-node-types/-/ast-node-types-12.6.1.tgz#35ecefe74e701d7f632c083d4fda89cab1b89012" + integrity sha512-uzlJ+ZsCAyJm+lBi7j0UeBbj+Oy6w/VWoGJ3iHRHE5eZ8Z4iK66mq+PG/spupmbllLtz77OJbY89BYqgFyjXmA== + +"@textlint/ast-node-types@^13.0.2": + version "13.3.1" + resolved "https://registry.yarnpkg.com/@textlint/ast-node-types/-/ast-node-types-13.3.1.tgz#469cab986e43f4ffb39aa5c31d148888a36d2286" + integrity sha512-/qeEjW3hIFpGwESsCkJRroja7mBOlo9wqyx8G4fwayq4FZRvJMm/9DhIo77jd/4wm/VSJcVVr+fs+rVa4jrY5A== + +"@textlint/ast-tester@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/ast-tester/-/ast-tester-12.6.1.tgz#853a438829dbb0aec0456a437b5e3894692e970b" + integrity sha512-Gxiq6xmDR3PnX0RqRGth/Lu5fyFWoXNPfGxXTLORPFpfs8JKPh/eXGhlwc1f0v4VQzPay2KwVl6SGXvJD5qLXw== + dependencies: + "@textlint/ast-node-types" "^12.6.1" + debug "^4.3.4" + +"@textlint/ast-traverse@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/ast-traverse/-/ast-traverse-12.6.1.tgz#644e46c5ef2e946e1fe1ef2452686c8ba2131392" + integrity sha512-Y/j7ip7yDuTjuIV4kTRPVnkJKfpI71U+eqXFnrM9sE2xBA9IsqzqiLQeDY+S5hhfQzmcEnZFtAP0hqrYaT6gNA== + dependencies: + "@textlint/ast-node-types" "^12.6.1" + +"@textlint/config-loader@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/config-loader/-/config-loader-12.6.1.tgz#151e97d9258361267056dbf47fe4a034c84a193e" + integrity sha512-mvChF2pFusxyQC4gFzIgNcZ4izUt7ci+JdXZtGV+DOzykVUuGhgGo3TFTi/ccgYyqZdq9MxJG6I+dvYB1A2Fog== + dependencies: + "@textlint/kernel" "^12.6.1" + "@textlint/module-interop" "^12.6.1" + "@textlint/types" "^12.6.1" + "@textlint/utils" "^12.6.1" + debug "^4.3.4" + rc-config-loader "^4.1.2" + try-resolve "^1.0.1" + +"@textlint/feature-flag@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/feature-flag/-/feature-flag-12.6.1.tgz#20f8a3cf86be939186adc33744ef66084b06067a" + integrity sha512-cY/AraTLdzbwDyAhdpaXB7n1Lw6zA+k+7UaT8mmxMmjs0uYGzdMQa499I0rQatctJ6izrdZXYW0NdUQfG2ugiA== + +"@textlint/fixer-formatter@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/fixer-formatter/-/fixer-formatter-12.6.1.tgz#b05f28b635c8628f588414da7baab01cd1db6daf" + integrity sha512-BMhvoKQbME9LXvl6CfIM/hZckb+IMiAA6ioDvdM3o63N+xDypS42uzJNpRgzXKGYL1Dv/7R1hsmDzz3fgvGhBw== + dependencies: + "@textlint/module-interop" "^12.6.1" + "@textlint/types" "^12.6.1" + chalk "^4.1.2" + debug "^4.3.4" + diff "^4.0.2" + is-file "^1.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + try-resolve "^1.0.1" + +"@textlint/kernel@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/kernel/-/kernel-12.6.1.tgz#6e8e57a0ebd2bfe5ce5c218bb4eedd7b20c793e0" + integrity sha512-GjNaI36pYx/boy1Xf7NPJFbS0uWHhY9y9DMMl/8ZJZoldN7XrCvJFivNdeYQxu+LTmfGGaUJoTjDpnllOs6XSQ== + dependencies: + "@textlint/ast-node-types" "^12.6.1" + "@textlint/ast-tester" "^12.6.1" + "@textlint/ast-traverse" "^12.6.1" + "@textlint/feature-flag" "^12.6.1" + "@textlint/source-code-fixer" "^12.6.1" + "@textlint/types" "^12.6.1" + "@textlint/utils" "^12.6.1" + debug "^4.3.4" + deep-equal "^1.1.1" + structured-source "^4.0.0" + +"@textlint/linter-formatter@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/linter-formatter/-/linter-formatter-12.6.1.tgz#90314ddaa036197c36ccb75cc8fa3fb318895350" + integrity sha512-1fQy17vNZy5qem8I71MGEir7gVLSUWcIE4ruQbONiIko9as+AYibt6xX6GtTX+aJejuJJcb+KTeAxKJ+6FA8vg== + dependencies: + "@azu/format-text" "^1.0.1" + "@azu/style-format" "^1.0.0" + "@textlint/module-interop" "^12.6.1" + "@textlint/types" "^12.6.1" + chalk "^4.1.2" + debug "^4.3.4" + is-file "^1.0.0" + js-yaml "^3.14.1" + lodash "^4.17.21" + optionator "^0.9.1" + pluralize "^2.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + table "^6.8.1" + text-table "^0.2.0" + try-resolve "^1.0.1" + +"@textlint/markdown-to-ast@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/markdown-to-ast/-/markdown-to-ast-12.6.1.tgz#fcccb5733b3e76cd0db78a323763ab101f2d803b" + integrity sha512-T0HO+VrU9VbLRiEx/kH4+gwGMHNMIGkp0Pok+p0I33saOOLyhfGvwOKQgvt2qkxzQEV2L5MtGB8EnW4r5d3CqQ== + dependencies: + "@textlint/ast-node-types" "^12.6.1" + debug "^4.3.4" + mdast-util-gfm-autolink-literal "^0.1.3" + remark-footnotes "^3.0.0" + remark-frontmatter "^3.0.0" + remark-gfm "^1.0.0" + remark-parse "^9.0.0" + traverse "^0.6.7" + unified "^9.2.2" + +"@textlint/module-interop@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/module-interop/-/module-interop-12.6.1.tgz#82adf942281a8880e1ad70b305d8caba87356830" + integrity sha512-COyRctLVh2ktAObmht3aNtqUvP0quoellKu1c2RrXny1po+Mf7PkvEKIxphtArE4JXMAmu01cDxfH6X88+eYIg== + +"@textlint/source-code-fixer@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/source-code-fixer/-/source-code-fixer-12.6.1.tgz#a674d6250863e5e8aaf2ac4dc2cb679ff37d2c49" + integrity sha512-J9UZ3uitT+T50ug5X6AoIOwn6kTl54ZmPYBPB9bmH4lwBamN7e4gT65lSweHY1D21elOkq+3bO/OAJMfQfAVHg== + dependencies: + "@textlint/types" "^12.6.1" + debug "^4.3.4" + +"@textlint/text-to-ast@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/text-to-ast/-/text-to-ast-12.6.1.tgz#8f24a424ee08fb82235e5f0dc63ab9e6475388b1" + integrity sha512-22tgSBaNerpwb66eCivjXmdZ3CDX2Il38vpuAGchiI+cl+sENU9dpuntxwEJdZQePX5qrkmw8XGj5kgyMF015A== + dependencies: + "@textlint/ast-node-types" "^12.6.1" + +"@textlint/textlint-plugin-markdown@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/textlint-plugin-markdown/-/textlint-plugin-markdown-12.6.1.tgz#744e36c468141826edaa7d96eb6beb28a5709ef3" + integrity sha512-fRKsFCL2fGeu0Bt+08FuEc2WHiI8IMDRvy6KT1pmNWO5irS4yL2/OXNknLH3erXvwcJw/hQnd5WEl4hQzS0Erw== + dependencies: + "@textlint/markdown-to-ast" "^12.6.1" + +"@textlint/textlint-plugin-text@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/textlint-plugin-text/-/textlint-plugin-text-12.6.1.tgz#92570b4f53ab15b2e8412f928a54c8833fb97b94" + integrity sha512-ZUfG0Xb8qGymIPNp2eFTq9bHvkJo3N3Ia1Aff5W9fsgZib1/Eb55U16Sp60TjhBFns0/p7L7usBC3nd3+tB5mQ== + dependencies: + "@textlint/text-to-ast" "^12.6.1" + +"@textlint/types@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/types/-/types-12.6.1.tgz#d00c5d625287a113c2807587c2c0cdc1c7f182d8" + integrity sha512-t1SZYahu2olnF8MUhlP6qDIEDyl7WmyIaBYxQdE2qU6xUkZWXS2zIxoAT/pVgvFCzDw3KO5HhIYGVeWRp90dTg== + dependencies: + "@textlint/ast-node-types" "^12.6.1" + +"@textlint/utils@^12.6.1": + version "12.6.1" + resolved "https://registry.yarnpkg.com/@textlint/utils/-/utils-12.6.1.tgz#95d00b4b57197987b97bc8342e127d652a7454e1" + integrity sha512-HJkqYXT2FAAHDM5XLFpQLF/CEdm8c2ltMeKmPBSSty1VfPXQMi8tGPT1b58b8KWh6dVmi7w0YYB7NrquuzXOKA== + +"@types/mdast@^3.0.0": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" + integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + dependencies: + "@types/unist" "*" + +"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" + integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + +ajv@^8.0.1: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +bail@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" + integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +boundary@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/boundary/-/boundary-2.0.0.tgz#169c8b1f0d44cf2c25938967a328f37e0a4e5efc" + integrity sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +ccount@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" + integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== + +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + +charenc@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +crypt@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== + +debug@^4.0.0, debug@^4.1.1, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +deep-equal@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +define-properties@^1.1.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +diff@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +editorconfig-checker@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/editorconfig-checker/-/editorconfig-checker-5.0.1.tgz#cb4bf7a9b80f1b63b141b8897d7cc326fce0d3ae" + integrity sha512-6hXq9VVDkyCxVYKdGtIj+yhVR1fi/6W6Ykz/+kItLPARulJvr2/VXgWZ5OGWx1UYm2RD6XOzWyx1JF6DLgQ/8Q== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +entities@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" + integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.11: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +fault@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" + integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== + dependencies: + format "^0.2.0" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + dependencies: + locate-path "^2.0.0" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + +format@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-stdin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" + integrity sha512-jZV7n6jGE3Gt7fgSTJoz91Ak5MuTLwMwkoYdjxuJ/AmjIsE1UC03y/IWkZCQGEvVNS9qoRNwy5BCqxImv0FVeA== + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@^7.1.3, glob@^7.2.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globby@13.1.3: + version "13.1.3" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.3.tgz#f62baf5720bcb2c1330c8d4ef222ee12318563ff" + integrity sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw== + dependencies: + dir-glob "^3.0.1" + fast-glob "^3.2.11" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^4.0.0" + +graceful-fs@^4.1.2: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-buffer@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-buffer@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-file/-/is-file-1.0.0.tgz#28a44cfbd9d3db193045f22b65fce8edf9620596" + integrity sha512-ZGMuc+xA8mRnrXtmtf2l/EkIW2zaD2LSBWlaOVEF6yH4RTndHob65V4SwWWdtGKVthQfXPVKsXqw4TDUjbVxVQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-regex@^1.0.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== + +js-yaml@^3.12.0, js-yaml@^3.14.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json5@^2.1.1, json5@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +linkify-it@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-4.0.1.tgz#01f1d5e508190d06669982ba31a7d9f56a5751ec" + integrity sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw== + dependencies: + uc.micro "^1.0.1" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A== + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw== + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash@^4.17.15, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +longest-streak@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" + integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== + +markdown-it@13.0.1: + version "13.0.1" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-13.0.1.tgz#c6ecc431cacf1a5da531423fc6a42807814af430" + integrity sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q== + dependencies: + argparse "^2.0.1" + entities "~3.0.1" + linkify-it "^4.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +markdown-table@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-2.0.0.tgz#194a90ced26d31fe753d8b9434430214c011865b" + integrity sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A== + dependencies: + repeat-string "^1.0.0" + +markdownlint-cli2-formatter-default@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.3.tgz#5aecd6e576ad18801b76e58bbbaf0e916c583ab8" + integrity sha512-QEAJitT5eqX1SNboOD+SO/LNBpu4P4je8JlR02ug2cLQAqmIhh8IJnSK7AcaHBHhNADqdGydnPpQOpsNcEEqCw== + +markdownlint-cli2@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/markdownlint-cli2/-/markdownlint-cli2-0.6.0.tgz#ffa6aee4098e61f781e5e69528db60f7f39f737c" + integrity sha512-Bv20r6WGdcHMWi8QvAFZ3CBunf4i4aYmVdTfpAvXODI/1k3f09DZZ0i0LcX9ZMhlVxjoOzbVDz1NWyKc5hwTqg== + dependencies: + globby "13.1.3" + markdownlint "0.27.0" + markdownlint-cli2-formatter-default "0.0.3" + micromatch "4.0.5" + strip-json-comments "5.0.0" + yaml "2.2.1" + +markdownlint@0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.27.0.tgz#9dabf7710a4999e2835e3c68317f1acd0bc89049" + integrity sha512-HtfVr/hzJJmE0C198F99JLaeada+646B5SaG2pVoEakLFI6iRGsvMqrnnrflq8hm1zQgwskEgqSnhDW11JBp0w== + dependencies: + markdown-it "13.0.1" + +md5@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" + integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== + dependencies: + charenc "0.0.2" + crypt "0.0.2" + is-buffer "~1.1.6" + +mdast-util-find-and-replace@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-1.1.1.tgz#b7db1e873f96f66588c321f1363069abf607d1b5" + integrity sha512-9cKl33Y21lyckGzpSmEQnIDjEfeeWelN5s1kUW1LwdB0Fkuq2u+4GdqcGEygYxJE8GVqCl0741bYXHgamfWAZA== + dependencies: + escape-string-regexp "^4.0.0" + unist-util-is "^4.0.0" + unist-util-visit-parents "^3.0.0" + +mdast-util-footnote@^0.1.0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/mdast-util-footnote/-/mdast-util-footnote-0.1.7.tgz#4b226caeab4613a3362c144c94af0fdd6f7e0ef0" + integrity sha512-QxNdO8qSxqbO2e3m09KwDKfWiLgqyCurdWTQ198NpbZ2hxntdc+VKS4fDJCmNWbAroUdYnSthu+XbZ8ovh8C3w== + dependencies: + mdast-util-to-markdown "^0.6.0" + micromark "~2.11.0" + +mdast-util-from-markdown@^0.8.0: + version "0.8.5" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz#d1ef2ca42bc377ecb0463a987910dae89bd9a28c" + integrity sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-string "^2.0.0" + micromark "~2.11.0" + parse-entities "^2.0.0" + unist-util-stringify-position "^2.0.0" + +mdast-util-frontmatter@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-frontmatter/-/mdast-util-frontmatter-0.2.0.tgz#8bd5cd55e236c03e204a036f7372ebe9e6748240" + integrity sha512-FHKL4w4S5fdt1KjJCwB0178WJ0evnyyQr5kXTM3wrOVpytD0hrkvd+AOOjU9Td8onOejCkmZ+HQRT3CZ3coHHQ== + dependencies: + micromark-extension-frontmatter "^0.2.0" + +mdast-util-gfm-autolink-literal@^0.1.0, mdast-util-gfm-autolink-literal@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-0.1.3.tgz#9c4ff399c5ddd2ece40bd3b13e5447d84e385fb7" + integrity sha512-GjmLjWrXg1wqMIO9+ZsRik/s7PLwTaeCHVB7vRxUwLntZc8mzmTsLVr6HW1yLokcnhfURsn5zmSVdi3/xWWu1A== + dependencies: + ccount "^1.0.0" + mdast-util-find-and-replace "^1.1.0" + micromark "^2.11.3" + +mdast-util-gfm-strikethrough@^0.2.0: + version "0.2.3" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-0.2.3.tgz#45eea337b7fff0755a291844fbea79996c322890" + integrity sha512-5OQLXpt6qdbttcDG/UxYY7Yjj3e8P7X16LzvpX8pIQPYJ/C2Z1qFGMmcw+1PZMUM3Z8wt8NRfYTvCni93mgsgA== + dependencies: + mdast-util-to-markdown "^0.6.0" + +mdast-util-gfm-table@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-table/-/mdast-util-gfm-table-0.1.6.tgz#af05aeadc8e5ee004eeddfb324b2ad8c029b6ecf" + integrity sha512-j4yDxQ66AJSBwGkbpFEp9uG/LS1tZV3P33fN1gkyRB2LoRL+RR3f76m0HPHaby6F4Z5xr9Fv1URmATlRRUIpRQ== + dependencies: + markdown-table "^2.0.0" + mdast-util-to-markdown "~0.6.0" + +mdast-util-gfm-task-list-item@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.6.tgz#70c885e6b9f543ddd7e6b41f9703ee55b084af10" + integrity sha512-/d51FFIfPsSmCIRNp7E6pozM9z1GYPIkSy1urQ8s/o4TC22BZ7DqfHFWiqBD23bc7J3vV1Fc9O4QIHBlfuit8A== + dependencies: + mdast-util-to-markdown "~0.6.0" + +mdast-util-gfm@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-0.1.2.tgz#8ecddafe57d266540f6881f5c57ff19725bd351c" + integrity sha512-NNkhDx/qYcuOWB7xHUGWZYVXvjPFFd6afg6/e2g+SV4r9q5XUcCbV4Wfa3DLYIiD+xAEZc6K4MGaE/m0KDcPwQ== + dependencies: + mdast-util-gfm-autolink-literal "^0.1.0" + mdast-util-gfm-strikethrough "^0.2.0" + mdast-util-gfm-table "^0.1.0" + mdast-util-gfm-task-list-item "^0.1.0" + mdast-util-to-markdown "^0.6.1" + +mdast-util-to-markdown@^0.6.0, mdast-util-to-markdown@^0.6.1, mdast-util-to-markdown@~0.6.0: + version "0.6.5" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe" + integrity sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ== + dependencies: + "@types/unist" "^2.0.0" + longest-streak "^2.0.0" + mdast-util-to-string "^2.0.0" + parse-entities "^2.0.0" + repeat-string "^1.0.0" + zwitch "^1.0.0" + +mdast-util-to-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" + integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromark-extension-footnote@^0.3.0: + version "0.3.2" + resolved "https://registry.yarnpkg.com/micromark-extension-footnote/-/micromark-extension-footnote-0.3.2.tgz#129b74ef4920ce96719b2c06102ee7abb2b88a20" + integrity sha512-gr/BeIxbIWQoUm02cIfK7mdMZ/fbroRpLsck4kvFtjbzP4yi+OPVbnukTc/zy0i7spC2xYE/dbX1Sur8BEDJsQ== + dependencies: + micromark "~2.11.0" + +micromark-extension-frontmatter@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/micromark-extension-frontmatter/-/micromark-extension-frontmatter-0.2.2.tgz#61b8e92e9213e1d3c13f5a59e7862f5ca98dfa53" + integrity sha512-q6nPLFCMTLtfsctAuS0Xh4vaolxSFUWUWR6PZSrXXiRy+SANGllpcqdXFv2z07l0Xz/6Hl40hK0ffNCJPH2n1A== + dependencies: + fault "^1.0.0" + +micromark-extension-gfm-autolink-literal@~0.5.0: + version "0.5.7" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.7.tgz#53866c1f0c7ef940ae7ca1f72c6faef8fed9f204" + integrity sha512-ePiDGH0/lhcngCe8FtH4ARFoxKTUelMp4L7Gg2pujYD5CSMb9PbblnyL+AAMud/SNMyusbS2XDSiPIRcQoNFAw== + dependencies: + micromark "~2.11.3" + +micromark-extension-gfm-strikethrough@~0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.5.tgz#96cb83356ff87bf31670eefb7ad7bba73e6514d1" + integrity sha512-PpOKlgokpQRwUesRwWEp+fHjGGkZEejj83k9gU5iXCbDG+XBA92BqnRKYJdfqfkrRcZRgGuPuXb7DaK/DmxOhw== + dependencies: + micromark "~2.11.0" + +micromark-extension-gfm-table@~0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.3.tgz#4d49f1ce0ca84996c853880b9446698947f1802b" + integrity sha512-hVGvESPq0fk6ALWtomcwmgLvH8ZSVpcPjzi0AjPclB9FsVRgMtGZkUcpE0zgjOCFAznKepF4z3hX8z6e3HODdA== + dependencies: + micromark "~2.11.0" + +micromark-extension-gfm-tagfilter@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-0.3.0.tgz#d9f26a65adee984c9ccdd7e182220493562841ad" + integrity sha512-9GU0xBatryXifL//FJH+tAZ6i240xQuFrSL7mYi8f4oZSbc+NvXjkrHemeYP0+L4ZUT+Ptz3b95zhUZnMtoi/Q== + +micromark-extension-gfm-task-list-item@~0.3.0: + version "0.3.3" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-0.3.3.tgz#d90c755f2533ed55a718129cee11257f136283b8" + integrity sha512-0zvM5iSLKrc/NQl84pZSjGo66aTGd57C1idmlWmE87lkMcXrTxg1uXa/nXomxJytoje9trP0NDLvw4bZ/Z/XCQ== + dependencies: + micromark "~2.11.0" + +micromark-extension-gfm@^0.3.0: + version "0.3.3" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-0.3.3.tgz#36d1a4c089ca8bdfd978c9bd2bf1a0cb24e2acfe" + integrity sha512-oVN4zv5/tAIA+l3GbMi7lWeYpJ14oQyJ3uEim20ktYFAcfX1x3LNlFGGlmrZHt7u9YlKExmyJdDGaTt6cMSR/A== + dependencies: + micromark "~2.11.0" + micromark-extension-gfm-autolink-literal "~0.5.0" + micromark-extension-gfm-strikethrough "~0.6.5" + micromark-extension-gfm-table "~0.4.0" + micromark-extension-gfm-tagfilter "~0.3.0" + micromark-extension-gfm-task-list-item "~0.3.0" + +micromark@^2.11.3, micromark@~2.11.0, micromark@~2.11.3: + version "2.11.4" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a" + integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA== + dependencies: + debug "^4.0.0" + parse-entities "^2.0.0" + +micromatch@4.0.5, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +misspellings@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/misspellings/-/misspellings-1.1.0.tgz#53d500266cbd09cda9d94c4cf392e60589b5b324" + integrity sha512-4QT2u/8X7PccbiHUcsZeEZrt3jGIVEpfcQ1RU01wDHKHVNtNhaP+0Xmsg7YPxD7OCc8bO802BTEWeGPvAXBwuw== + +mkdirp@^0.5.1, mkdirp@^0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== + dependencies: + p-limit "^1.1.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== + +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-glob-pattern@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-to-glob-pattern/-/path-to-glob-pattern-1.0.2.tgz#473e6a3a292a9d13fbae3edccee72d3baba8c619" + integrity sha512-ryF65N5MBB9XOjE5mMOi+0bMrh1F0ORQmqDSSERvv5zD62Cfc5QC6rK1AR1xuDIG1I091CkNENblbteWy1bXgw== + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg== + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== + +pluralize@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-2.0.0.tgz#72b726aa6fac1edeee42256c7d8dc256b335677f" + integrity sha512-TqNZzQCD4S42De9IfnnBvILN7HAW7riLqsCyp8lgjXeysyPlX5HhqKAcJHHHb9XskE4/a+7VGC9zzx8Ls0jOAw== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +rc-config-loader@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rc-config-loader/-/rc-config-loader-3.0.0.tgz#1484ed55d6fb8b21057699c8426370f7529c52a7" + integrity sha512-bwfUSB37TWkHfP+PPjb/x8BUjChFmmBK44JMfVnU7paisWqZl/o5k7ttCH+EQLnrbn2Aq8Fo1LAsyUiz+WF4CQ== + dependencies: + debug "^4.1.1" + js-yaml "^3.12.0" + json5 "^2.1.1" + require-from-string "^2.0.2" + +rc-config-loader@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/rc-config-loader/-/rc-config-loader-4.1.2.tgz#e57fc874bde9b1e48d8a8564f2f824f91eafd920" + integrity sha512-qKTnVWFl9OQYKATPzdfaZIbTxcHziQl92zYSxYC6umhOqyAsoj8H8Gq/+aFjAso68sBdjTz3A7omqeAkkF1MWg== + dependencies: + debug "^4.3.4" + js-yaml "^4.1.0" + json5 "^2.2.2" + require-from-string "^2.0.2" + +read-pkg-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" + integrity sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw== + dependencies: + find-up "^2.0.0" + read-pkg "^3.0.0" + +read-pkg@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ== + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA== + dependencies: + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" + +regexp.prototype.flags@^1.2.0: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + +remark-footnotes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-3.0.0.tgz#5756b56f8464fa7ed80dbba0c966136305d8cb8d" + integrity sha512-ZssAvH9FjGYlJ/PBVKdSmfyPc3Cz4rTWgZLI4iE/SX8Nt5l3o3oEjv3wwG5VD7xOjktzdwp5coac+kJV9l4jgg== + dependencies: + mdast-util-footnote "^0.1.0" + micromark-extension-footnote "^0.3.0" + +remark-frontmatter@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-3.0.0.tgz#ca5d996361765c859bd944505f377d6b186a6ec6" + integrity sha512-mSuDd3svCHs+2PyO29h7iijIZx4plX0fheacJcAoYAASfgzgVIcXGYSq9GFyYocFLftQs8IOmmkgtOovs6d4oA== + dependencies: + mdast-util-frontmatter "^0.2.0" + micromark-extension-frontmatter "^0.2.0" + +remark-gfm@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-1.0.0.tgz#9213643001be3f277da6256464d56fd28c3b3c0d" + integrity sha512-KfexHJCiqvrdBZVbQ6RopMZGwaXz6wFJEfByIuEwGf0arvITHjiKKZ1dpXujjH9KZdm1//XJQwgfnJ3lmXaDPA== + dependencies: + mdast-util-gfm "^0.1.0" + micromark-extension-gfm "^0.3.0" + +remark-parse@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640" + integrity sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw== + dependencies: + mdast-util-from-markdown "^0.8.0" + +repeat-string@^1.0.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve@^1.10.0: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +"semver@2 || 3 || 4 || 5": + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.12" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" + integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-json-comments@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-5.0.0.tgz#ec101b766476a703031bc607e3c712569de2aa06" + integrity sha512-V1LGY4UUo0jgwC+ELQ2BNWfPa17TIuwBLg+j1AA/9RPzKINl1lhxVEu2r+ZTTO8aetIsUzE5Qj6LMSBkoGYKKw== + +strip-json-comments@^3.0.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +structured-source@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/structured-source/-/structured-source-4.0.0.tgz#0c9e59ee43dedd8fc60a63731f60e358102a4948" + integrity sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA== + dependencies: + boundary "^2.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +table@^6.8.1: + version "6.8.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" + integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +textlint-rule-common-misspellings@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/textlint-rule-common-misspellings/-/textlint-rule-common-misspellings-1.0.1.tgz#8c4133cf3bb59aa159199d2c9bced12413365774" + integrity sha512-f5KWhQFJzJBUX3RirAS25aSkAaaOHeSHtBeb7d49O+vxnAX3dZBS5DB/e5M1kR4tifW4qae64oqWZygoGYWkjQ== + dependencies: + misspellings "^1.0.1" + textlint-rule-helper "^1.1.5" + +textlint-rule-helper@^1.1.5: + version "1.2.0" + resolved "https://registry.yarnpkg.com/textlint-rule-helper/-/textlint-rule-helper-1.2.0.tgz#be68d47a5146b16dd116278c9aeb7bd35631ccda" + integrity sha512-yJmVbmyuUPOndKsxOijpx/G7mwybXXf4M10U2up0BeIZSN+6drUl+aSKAoC+RUHY7bG4ogLwRcmWoNG1lSrRIQ== + dependencies: + unist-util-visit "^1.1.0" + +textlint-rule-helper@^2.0.0, textlint-rule-helper@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/textlint-rule-helper/-/textlint-rule-helper-2.3.0.tgz#5ab84db686d42fd2e39a63b40310501bb336520d" + integrity sha512-Ug78Saahb/qVImttL0NSFyT5/JJ5wXvOPepR2pYAjNi54BsQAAz/hAyyEgKuYeR0+yjFb0KPhby4f880X5vqHA== + dependencies: + "@textlint/ast-node-types" "^13.0.2" + structured-source "^4.0.0" + unist-util-visit "^2.0.3" + +textlint-rule-no-todo@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/textlint-rule-no-todo/-/textlint-rule-no-todo-2.0.1.tgz#86351ed3521ce8faa3b8224f88887f3cecbf2920" + integrity sha512-+adoWaBgoTN2g0WNcrERhVq7gdPKQIf1z7Ol+6XwMGv8XmuoFp5vJljHKtCmJBmGhBihjty2b8oaza2MY6UNlw== + dependencies: + textlint-rule-helper "^2.0.0" + +textlint-rule-terminology@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/textlint-rule-terminology/-/textlint-rule-terminology-3.0.4.tgz#5e51fffe4dc5d1f82c2fa0482137e5c75a7eaaae" + integrity sha512-obQ3y0hqX6OWCrM8K5K6WSJGE4BOyNfGF6hUGPet56taTm/xzkRu8XA6vpn2GFr4zom/oMa0sBJ3OtDWCgrS/g== + dependencies: + lodash "^4.17.15" + strip-json-comments "^3.0.1" + textlint-rule-helper "^2.1.1" + +textlint@^12.5.1: + version "12.6.1" + resolved "https://registry.yarnpkg.com/textlint/-/textlint-12.6.1.tgz#a8eb605ddfc45f7504e4876e4c50d1a1d5d25cbc" + integrity sha512-ro33XJnA9UpQVeheGbPalYa5qpyA2R2yZdIgfC8xEvlOTF5SWJkdeNMm24Ml6d36bgwbqIO2yISKu7vlzBxHRA== + dependencies: + "@textlint/ast-node-types" "^12.6.1" + "@textlint/ast-traverse" "^12.6.1" + "@textlint/config-loader" "^12.6.1" + "@textlint/feature-flag" "^12.6.1" + "@textlint/fixer-formatter" "^12.6.1" + "@textlint/kernel" "^12.6.1" + "@textlint/linter-formatter" "^12.6.1" + "@textlint/module-interop" "^12.6.1" + "@textlint/textlint-plugin-markdown" "^12.6.1" + "@textlint/textlint-plugin-text" "^12.6.1" + "@textlint/types" "^12.6.1" + "@textlint/utils" "^12.6.1" + debug "^4.3.4" + deep-equal "^1.1.1" + file-entry-cache "^5.0.1" + get-stdin "^5.0.1" + glob "^7.2.3" + is-file "^1.0.0" + md5 "^2.3.0" + mkdirp "^0.5.6" + optionator "^0.9.1" + path-to-glob-pattern "^1.0.2" + rc-config-loader "^3.0.0" + read-pkg "^1.1.0" + read-pkg-up "^3.0.0" + structured-source "^4.0.0" + try-resolve "^1.0.1" + unique-concat "^0.2.2" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +traverse@^0.6.7: + version "0.6.7" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.7.tgz#46961cd2d57dd8706c36664acde06a248f1173fe" + integrity sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg== + +trough@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" + integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== + +try-resolve@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/try-resolve/-/try-resolve-1.0.1.tgz#cfde6fabd72d63e5797cfaab873abbe8e700e912" + integrity sha512-yHeaPjCBzVaXwWl5IMUapTaTC2rn/eBYg2fsG2L+CvJd+ttFbk0ylDnpTO3wVhosmE1tQEvcebbBeKLCwScQSQ== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + +unified@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" + integrity sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ== + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^2.0.0" + trough "^1.0.0" + vfile "^4.0.0" + +unique-concat@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/unique-concat/-/unique-concat-0.2.2.tgz#9210f9bdcaacc5e1e3929490d7c019df96f18712" + integrity sha512-nFT3frbsvTa9rrc71FJApPqXF8oIhVHbX3IWgObQi1mF7WrW48Ys70daL7o4evZUtmUf6Qn6WK0LbHhyO0hpXw== + +unist-util-is@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-3.0.0.tgz#d9e84381c2468e82629e4a5be9d7d05a2dd324cd" + integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== + +unist-util-is@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" + integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== + +unist-util-stringify-position@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" + integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== + dependencies: + "@types/unist" "^2.0.2" + +unist-util-visit-parents@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9" + integrity sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g== + dependencies: + unist-util-is "^3.0.0" + +unist-util-visit-parents@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" + integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + +unist-util-visit@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3" + integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw== + dependencies: + unist-util-visit-parents "^2.0.0" + +unist-util-visit@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" + integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + unist-util-visit-parents "^3.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +vfile-message@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" + integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^2.0.0" + +vfile@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" + integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + unist-util-stringify-position "^2.0.0" + vfile-message "^2.0.0" + +word-wrap@^1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + +yaml@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.2.1.tgz#3014bf0482dcd15147aa8e56109ce8632cd60ce4" + integrity sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw== + +zwitch@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" + integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== -- cgit v1.2.3