Ishanjainn patch 1 (#9)

* Update ansible-test.yml

* Update ansible-test.yml

* Update alert_notification_policy.py

* Add meta class

* Add meta class

* Updating LIcense

* indentation

* Import requests

* adding requests

* Update ansible-test.yml

* Update dashboard.py

* Update dashboard.py

* Update dashboard.py

* Adding reqeusts

* Fixes

* Updated fixes

* updated fix

* action-test

* fixed

* Update ansible-test.yml

* Update ansible-test.yml
This commit is contained in:
Ishan Jain 2022-08-11 15:10:32 +05:30 committed by GitHub
parent 3c3d7655e7
commit 1f1de060ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 196 additions and 302 deletions

View File

@ -1,40 +1,20 @@
# README FIRST
# 1. replace "NAMESPACE" and "COLLECTION_NAME" with the correct name in the env section (e.g. with 'community' and 'mycollection')
# 2. If you don't have unit tests remove that section
# 3. If your collection depends on other collections ensure they are installed, see "Install collection dependencies"
# If you need help please ask in #ansible-community on the Libera.chat IRC network
name: CI
on:
# Run CI against all pushes (direct commits, also merged PRs), Pull Requests
push:
branches:
- main
- stable-*
pull_request:
# Run CI once per day (at 06:00 UTC)
# This ensures that even if there haven't been commits that we are still testing against latest version of ansible-test for each ansible-base version
schedule:
- cron: '0 6 * * *'
env:
NAMESPACE: NAMESPACE
COLLECTION_NAME: COLLECTION_NAME
NAMESPACE: grafana
COLLECTION_NAME: grafana
jobs:
###
# Sanity tests (REQUIRED)
#
# https://docs.ansible.com/ansible/latest/dev_guide/testing_sanity.html
sanity:
name: Sanity (Ⓐ${{ matrix.ansible }})
strategy:
matrix:
ansible:
# It's important that Sanity is tested against all stable-X.Y branches
# Testing against `devel` may fail as new tests are added.
# - stable-2.9 # Only if your collection supports Ansible 2.9
- stable-2.10
- stable-2.11
- stable-2.12
@ -42,9 +22,6 @@ jobs:
runs-on: ubuntu-latest
steps:
# ansible-test requires the collection to be in a directory in the form
# .../ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}/
- name: Check out code
uses: actions/checkout@v3
with:
@ -53,162 +30,19 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v3
with:
# it is just required to run that once as "ansible-test sanity" in the docker image
# will run on all python versions it supports.
python-version: '3.10'
python-version: '3.9'
# Install the head of the given branch (devel, stable-2.10)
- name: Install ansible-base (${{ matrix.ansible }})
run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check
# run ansible-test sanity inside of Docker.
# The docker container has all the pinned dependencies that are required
# and all python versions ansible supports.
- name: Run sanity tests
run: ansible-test sanity --docker -v --color --coverage
working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}
# ansible-test support producing code coverage date
- name: Generate coverage report
run: ansible-test coverage xml -v --requirements --group-by command --group-by version
working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}
# See the reports at https://codecov.io/gh/GITHUBORG/REPONAME
- uses: codecov/codecov-action@v3
with:
fail_ci_if_error: false
###
# Unit tests (OPTIONAL)
#
# https://docs.ansible.com/ansible/latest/dev_guide/testing_units.html
units:
runs-on: ubuntu-latest
name: Units (Ⓐ${{ matrix.ansible }})
strategy:
# As soon as the first unit test fails, cancel the others to free up the CI queue
fail-fast: true
matrix:
ansible:
# - stable-2.9 # Only if your collection supports Ansible 2.9
- stable-2.10
- stable-2.11
- stable-2.12
- devel
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:
# it is just required to run that once as "ansible-test units" in the docker image
# will run on all python versions it supports.
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
# OPTIONAL If your unit test requires Python libraries from other collections
# Install them like this
- name: Install collection dependencies
run: ansible-galaxy collection install ansible.netcommon ansible.utils -p .
# Run the unit tests
- name: Run unit test
run: ansible-test units -v --color --docker --coverage
working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}
# ansible-test support producing code coverage date
- name: Generate coverage report
run: ansible-test coverage xml -v --requirements --group-by command --group-by version
working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}
# See the reports at https://codecov.io/gh/GITHUBORG/REPONAME
- uses: codecov/codecov-action@v3
with:
fail_ci_if_error: false
###
# Integration tests (RECOMMENDED)
#
# https://docs.ansible.com/ansible/latest/dev_guide/testing_integration.html
# If the application you are testing is available as a docker container and you want to test
# multiple versions see the following for an example:
# https://github.com/ansible-collections/community.zabbix/tree/master/.github/workflows
integration:
runs-on: ubuntu-latest
name: I (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }})
strategy:
fail-fast: false
matrix:
ansible:
# - stable-2.9 # Only if your collection supports Ansible 2.9
- stable-2.10
- stable-2.11
- stable-2.12
- devel
python:
- '2.6'
- '2.7'
- '3.5'
- '3.6'
- '3.7'
- '3.8'
- '3.9'
- '3.10'
exclude:
# Because ansible-test doesn't support Python 3.9 for Ansible 2.9
# and Python 3.10 is supported in 2.12 or later.
- ansible: stable-2.9
python: '3.9'
- ansible: stable-2.9
python: '3.10'
- ansible: stable-2.10
python: '3.10'
- ansible: stable-2.11
python: '3.10'
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:
# it is just required to run that once as "ansible-test integration" in the docker image
# will run on all python versions it supports.
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
# OPTIONAL If your integration test requires Python libraries or modules from other collections
# Install them like this
- name: Install collection dependencies
run: ansible-galaxy collection install ansible.netcommon -p .
# Run the integration tests
- name: Run integration test
run: ansible-test integration -v --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --docker --coverage
working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}
# ansible-test support producing code coverage date
- name: Generate coverage report
run: ansible-test coverage xml -v --requirements --group-by command --group-by version
working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}
# See the reports at https://codecov.io/gh/GITHUBORG/REPONAME
- uses: codecov/codecov-action@v3
with:
fail_ci_if_error: false

View File

@ -5,20 +5,5 @@ Grafana.Grafana Release Notes
.. contents:: Topics
v0.0.2
v0.0.7
======
v0.0.1
======
New Modules
-----------
- grafana.grafana.alert_contact_point - Manage Alerting Contact points in Grafana
- grafana.grafana.alert_notification_policy - Sets the notification policy tree in Grafana Alerting
- grafana.grafana.cloud_api_key - Manage Grafana Cloud API keys
- grafana.grafana.cloud_plugin - Manage Grafana Cloud Plugins
- grafana.grafana.cloud_stack - Manage Grafana Cloud stack
- grafana.grafana.dashboard - Manage Dashboards in Grafana
- grafana.grafana.datasource - Manage Data sources in Grafana
- grafana.grafana.folder - Manage Folders in Grafana

View File

@ -54,4 +54,4 @@ plugins:
shell: {}
strategy: {}
vars: {}
version: 0.0.2
version: 0.0.7

View File

@ -1,31 +1,4 @@
ancestor: null
releases:
0.0.1:
modules:
- description: Manage Alerting Contact points in Grafana
name: alert_contact_point
namespace: ''
- description: Sets the notification policy tree in Grafana Alerting
name: alert_notification_policy
namespace: ''
- description: Manage Grafana Cloud API keys
name: cloud_api_key
namespace: ''
- description: Manage Grafana Cloud Plugins
name: cloud_plugin
namespace: ''
- description: Manage Grafana Cloud stack
name: cloud_stack
namespace: ''
- description: Manage Dashboards in Grafana
name: dashboard
namespace: ''
- description: Manage Data sources in Grafana
name: datasource
namespace: ''
- description: Manage Folders in Grafana
name: folder
namespace: ''
release_date: '2022-08-11'
0.0.2:
0.0.7:
release_date: '2022-08-11'

View File

@ -1,26 +1,13 @@
namespace: grafana
name: grafana
version: 0.0.6
version: 0.0.7
readme: README.md
authors:
- Grafana Labs <grafana.com>
- Ishan Jain <ishan.jain@grafana.com>
description: Ansible collection to manage Grafana resources
license:
- GPL-3.0-or-later
tags: [grafana, observability, monitoring]
repository: https://github.com/grafana/grafana-ansible-collection
issues: https://github.com/grafana/grafana-ansible-collection/issues
build_ignore:
- .idea
issues: https://github.com/grafana/grafana-ansible-collection/issues

View File

@ -1,14 +1,21 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Rainer Leber <rainerleber@gmail.com> <rainer.leber@sva.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
DOCUMENTATION = '''
---
module: grafana.grafana.alert_contact_point
module: alert_contact_point
author:
- Ishan Jain (@ishanjainn)
version_added: "0.0.1"
short_description: Manage Alerting Contact points in Grafana
description:
- Create, Update and delete Contact points using Ansible.
requirements: [ "requests >= 1.0.0" ]
options:
name:
description:
@ -40,6 +47,11 @@ options:
- Grafana API Key used to authenticate with Grafana.
type: str
required : true
stack_slug:
description:
- Name of the Grafana Cloud stack to which the contact points will be added
type: str
required: true
state:
description:
- State for the Grafana CLoud stack.
@ -103,7 +115,13 @@ output:
'''
from ansible.module_utils.basic import AnsibleModule
import requests
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
__metaclass__ = type
def present_alert_contact_point(module):
@ -172,7 +190,7 @@ def main():
settings=dict(type='dict', required=True),
DisableResolveMessage=dict(type='bool', required=False, default=False),
stack_slug=dict(type='str', required=True),
grafana_api_key=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'])
)
@ -196,4 +214,4 @@ def main():
if __name__ == '__main__':
main()
main()

View File

@ -1,43 +1,53 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Rainer Leber <rainerleber@gmail.com> <rainer.leber@sva.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
DOCUMENTATION = '''
---
module: grafana.grafana.alert_notification_policy
module: alert_notification_policy
author:
- Ishan Jain (@ishanjainn)
version_added: "0.0.1"
short_description: Sets the notification policy tree in Grafana Alerting
description:
- Set the notification policy tree using Ansible
requirements: [ "requests >= 1.0.0" ]
options:
Continue:
description:
- Continue matching subsequent sibling nodes if set to `True`.
type: bool
default: false
GroupByStr:
groupByStr:
description:
- List of string.
- Group alerts when you receive a notification based on labels. If empty it will be inherited from the parent policy.
type: list
default: []
MuteTimeIntervals:
elements: str
muteTimeIntervals:
description:
- List of string.
- Add mute timing to policy
type: list
default: []
elements: str
root_policy_receiver:
description:
- Name of the contact point to set as the default receiver
type: str
default: grafana-default-email
Routes:
routes:
description:
- List of objects
- A Route is a node that contains definitions of how to handle alerts.
type: list
required: true
elements: dict
groupInterval:
description:
- The wait time to send a batch of new alerts for that group after the first notification was sent. Inherited from the parent policy if empty.
@ -50,10 +60,10 @@ options:
default: 30s
objectMatchers:
description:
- State for the Grafana CLoud stack.
type: str
default: present
choices: [ present, absent ]
- Matchers is a slice of Matchers that is sortable, implements Stringer, and provides a Matches method to match a LabelSet.
type: list
default: []
elements: dict
repeatInterval:
description:
- The waiting time to resend an alert after they have successfully been sent.
@ -119,10 +129,6 @@ output:
description: The waiting time until the initial notification is sent for a new group created by an incoming alert. This is of the parent policy.
returned: on success
type: str
provenance:
description:
returned: on success
type: str
receiver:
description: The name of the default contact point
returned: state is present and on success
@ -138,7 +144,13 @@ output:
'''
from ansible.module_utils.basic import AnsibleModule
import requests
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
__metaclass__ = type
def alert_notification_policy(module):
@ -163,16 +175,16 @@ def alert_notification_policy(module):
def main():
module_args = dict(Continue=dict(type='bool', required=False, default=False),
groupByStr=dict(type='list', required=False, default=[]),
muteTimeIntervals=dict(type='list', required=False, default=[]),
groupByStr=dict(type='list', required=False, default=[], elements='str'),
muteTimeIntervals=dict(type='list', required=False, default=[], elements='str'),
root_policy_receiver=dict(type='str', required=False, default='grafana-default-email'),
routes=dict(type='list', required=True),
routes=dict(type='list', required=True, elements='dict'),
groupInterval=dict(type='str', required=False, default='5m'),
groupWait=dict(type='str', required=False, default='30s'),
repeatInterval=dict(type='str', required=False, default='4h'),
objectMatchers=dict(type='list', required=False, default=[]),
objectMatchers=dict(type='list', required=False, default=[], elements='dict'),
stack_slug=dict(type='str', required=True),
grafana_api_key=dict(type='str', required=True), )
grafana_api_key=dict(type='str', required=True, no_log=True), )
module = AnsibleModule(argument_spec=module_args, supports_check_mode=True)
@ -185,4 +197,4 @@ def main():
if __name__ == '__main__':
main()
main()

View File

@ -1,14 +1,21 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Rainer Leber <rainerleber@gmail.com> <rainer.leber@sva.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
DOCUMENTATION = '''
---
module: grafana.grafana.cloud_api_key
module: cloud_api_key
author:
- Ishan Jain (@ishanjainn)
version_added: "0.0.1"
short_description: Manage Grafana Cloud API keys
description:
- Create and delete Grafana Cloud API keys using Ansible.
requirements: [ "requests >= 1.0.0" ]
options:
name:
description:
@ -20,6 +27,7 @@ options:
- Role to be associated with the CLoud API key.
type: str
required: true
choices: [Admin, Viewer, Editor, MetricsPublisher]
org_slug:
description:
- Name of the Grafana Cloud organization in which Cloud API key will be created
@ -62,7 +70,13 @@ EXAMPLES = '''
'''
from ansible.module_utils.basic import AnsibleModule
import requests
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
__metaclass__ = type
def present_cloud_api_key(module):
@ -100,7 +114,7 @@ def main():
name=dict(type='str', required=True),
role=dict(type='str', required=True, choices=['Admin', 'Viewer', 'Editor', 'MetricsPublisher']),
org_slug=dict(type='str', required=True),
existing_cloud_api_key=dict(type='str', required=True),
existing_cloud_api_key=dict(type='str', required=True, no_log=True),
fail_if_already_created=dict(type='bool', required=False, default='True'),
state=dict(type='str', required=False, default='present', choices=['present', 'absent'])
)
@ -125,4 +139,4 @@ def main():
if __name__ == '__main__':
main()
main()

View File

@ -1,14 +1,21 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Rainer Leber <rainerleber@gmail.com> <rainer.leber@sva.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
DOCUMENTATION = '''
---
module: grafana.grafana.cloud_plugin
module: cloud_plugin
author:
- Ishan Jain (@ishanjainn)
version_added: "0.0.1"
short_description: Manage Grafana Cloud Plugins
description:
- Create, Update and delete Grafana Cloud stacks using Ansible.
requirements: [ "requests >= 1.0.0" ]
options:
name:
description:
@ -79,7 +86,13 @@ RETURN = r'''
'''
from ansible.module_utils.basic import AnsibleModule
import requests
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
__metaclass__ = type
def present_cloud_plugin(module):
@ -121,7 +134,7 @@ def main():
name=dict(type='str', required=True),
version=dict(type='str', required=False, default='latest'),
stack_slug=dict(type='str', required=True),
cloud_api_key=dict(type='str', required=True),
cloud_api_key=dict(type='str', required=True, no_log=True),
state=dict(type='str', required=False, default='present', choices=['present', 'absent'])
)
@ -150,4 +163,4 @@ def main():
if __name__ == '__main__':
main()
main()

View File

@ -1,14 +1,21 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Rainer Leber <rainerleber@gmail.com> <rainer.leber@sva.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
DOCUMENTATION = '''
---
module: grafana.grafana.cloud_stack
module: cloud_stack
author:
- Ishan Jain (@ishanjainn)
version_added: "0.0.1"
short_description: Manage Grafana Cloud stack
description:
- Create and delete Grafana Cloud stacks using Ansible.
requirements: [ "requests >= 1.0.0" ]
options:
name:
description:
@ -33,14 +40,13 @@ options:
choices: [ us, us-azure, eu, au, eu-azure, prod-ap-southeast-0, prod-gb-south-0, prod-eu-west-3]
url:
description:
- If you use a custom domain for the instance, you can provide it here. For example, https://grafana.yourdoman.io.
- If you use a custom domain for the instance, you can provide it here. Will be set to https://<stack_slug>.grafana.net if not provided.
type: str
default: https://<stack_slug>.grafana.net
org_slug:
description:
- Name of the organization under which Cloud stack is created.
type: str
required: false
required: true
state:
description:
- State for the Grafana CLoud stack.
@ -107,7 +113,13 @@ RETURN = r'''
'''
from ansible.module_utils.basic import AnsibleModule
import requests
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
__metaclass__ = type
def present_cloud_stack(module):
@ -127,7 +139,7 @@ def present_cloud_stack(module):
if result.status_code == 200:
return False, True, result.json()
elif (result.status_code == 409 and result.json()['message'] == "That url is not available") or (result.status_code == 403 and result.json()['message'] == "Hosted instance limit reached"):
elif result.status_code in [409, 403] and result.json()['message'] in ["That url is not available", "Hosted instance limit reached"]:
api_url = 'https://grafana.com/api/orgs/' + module.params['org_slug'] + '/instances'
result = requests.get(api_url, headers={"Authorization": 'Bearer ' + module.params['cloud_api_key']})
@ -154,7 +166,7 @@ def main():
module_args = dict(
name=dict(type='str', required=True),
stack_slug=dict(type='str', required=True),
cloud_api_key=dict(type='str', required=True),
cloud_api_key=dict(type='str', required=True, no_log=True),
region=dict(type='str', required=False, default='us',
choices=['us', 'us-azure', 'eu', 'au', 'eu-azure', 'prod-ap-southeast-0', 'prod-gb-south-0',
'prod-eu-west-3']),
@ -191,4 +203,4 @@ def main():
if __name__ == '__main__':
main()
main()

View File

@ -1,14 +1,21 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Rainer Leber <rainerleber@gmail.com> <rainer.leber@sva.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
DOCUMENTATION = '''
---
module: grafana.grafana.dashboard
module: dashboard
author:
- Ishan Jain (@ishanjainn)
version_added: "0.0.1"
short_description: Manage Dashboards in Grafana
description:
- Create, Update and delete Dashboards using Ansible.
requirements: [ "requests >= 1.0.0" ]
options:
dashboard:
description:
@ -17,10 +24,10 @@ options:
required: true
stack_slug:
description:
- Name of the Grafana Cloud stack to which the notification policies will be added
- Name of the Grafana Cloud stack to which the dashboard will be added
type: str
required: true
cloud_api_key:
grafana_api_key:
description:
- CLoud API Key to authenticate with Grafana Cloud.
type: str
@ -38,14 +45,14 @@ EXAMPLES = '''
grafana.grafana.dashboard:
datasource: "{{ lookup('ansible.builtin.file', 'dashboard.json') }}"
stack_slug: "{{ stack_slug }}"
cloud_api_key: "{{ grafana_cloud_api_key }}"
grafana_api_key: "{{ grafana_api_key }}"
state: present
- name: Delete dashboard
grafana.grafana.dashboard:
datasource: "{{ lookup('ansible.builtin.file', 'dashboard.json') }}"
stack_slug: "{{ stack_slug }}"
cloud_api_key: "{{ grafana_cloud_api_key }}"
grafana_api_key: "{{ grafana_api_key }}"
state: absent
'''
@ -90,14 +97,21 @@ output:
'''
from ansible.module_utils.basic import AnsibleModule
import requests
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
__metaclass__ = type
def present_dashboard(module):
api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/dashboards/db'
result = requests.post(api_url, json=module.params['dashboard'], headers={"Authorization": 'Bearer ' + module.params['cloud_api_key']})
result = requests.post(api_url, json=module.params['dashboard'], headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']})
if result.status_code == 200:
return False, True, result.json()
@ -111,7 +125,7 @@ def absent_dashboard(module):
api_url = api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/dashboards/uid/' + module.params['dashboard']['dashboard']['uid']
result = requests.delete(api_url, headers={"Authorization": 'Bearer ' + module.params['cloud_api_key']})
result = requests.delete(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']})
if result.status_code == 200:
return False, True, result.json()
@ -123,7 +137,7 @@ def main():
module_args = dict(
dashboard=dict(type='dict', required=True),
stack_slug=dict(type='str', required=True),
cloud_api_key=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'])
)
@ -147,4 +161,4 @@ def main():
if __name__ == '__main__':
main()
main()

View File

@ -1,14 +1,21 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Rainer Leber <rainerleber@gmail.com> <rainer.leber@sva.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
DOCUMENTATION = '''
---
module: grafana.grafana.datasource
module: datasource
author:
- Ishan Jain (@ishanjainn)
version_added: "0.0.1"
short_description: Manage Data sources in Grafana
description:
- Create, Update and delete Data sources using Ansible.
requirements: [ "requests >= 1.0.0" ]
options:
datasource:
description:
@ -17,10 +24,10 @@ options:
required: true
stack_slug:
description:
- Name of the Grafana Cloud stack to which the notification policies will be added
- Name of the Grafana Cloud stack to which the data source will be added
type: str
required: true
cloud_api_key:
grafana_api_key:
description:
- CLoud API Key to authenticate with Grafana Cloud.
type: str
@ -38,14 +45,14 @@ EXAMPLES = '''
grafana.grafana.datasource:
datasource: "{{ lookup('ansible.builtin.file', 'datasource.json') }}"
stack_slug: "{{ stack_slug }}"
cloud_api_key: "{{ grafana_cloud_api_key }}"
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 }}"
cloud_api_key: "{{ grafana_cloud_api_key }}"
grafana_api_key: "{{ grafana_api_key }}"
state: absent
'''
@ -74,23 +81,29 @@ output:
'''
from ansible.module_utils.basic import AnsibleModule
import requests
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
__metaclass__ = type
def present_datasource(module):
api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/datasources'
result = requests.post(api_url, json=module.params['datasource'], headers={"Authorization": 'Bearer ' + module.params['cloud_api_key']})
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'],
headers={"Authorization": 'Bearer ' + module.params['cloud_api_key']})
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'])
result = requests.put(api_url, json=module.params['datasource'], headers={"Authorization": 'Bearer ' + module.params['cloud_api_key']})
result = requests.put(api_url, json=module.params['datasource'], headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']})
if result.status_code == 200:
return False, True, result.json()
@ -104,7 +117,7 @@ def present_datasource(module):
def absent_datasource(module):
api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/datasources/' + module.params['datasource']['name']
result = requests.delete(api_url, headers={"Authorization": 'Bearer ' + module.params['cloud_api_key']})
result = requests.delete(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']})
if result.status_code == 200:
return False, True, result.json()
@ -116,7 +129,7 @@ def main():
module_args = dict(
datasource=dict(type='dict', required=True),
stack_slug=dict(type='str', required=True),
cloud_api_key=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'])
)
@ -140,4 +153,4 @@ def main():
if __name__ == '__main__':
main()
main()

View File

@ -1,14 +1,21 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Rainer Leber <rainerleber@gmail.com> <rainer.leber@sva.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
DOCUMENTATION = '''
---
module: grafana.grafana.folder
module: folder
author:
- Ishan Jain (@ishanjainn)
version_added: "0.0.1"
short_description: Manage Folders in Grafana
description:
- Create, Update and delete Folders via Ansible.
requirements: [ "requests >= 1.0.0" ]
options:
title:
description:
@ -23,14 +30,19 @@ options:
overwrite:
description:
- Set to false if you dont want to overwrite existing folder with newer version.
type: str
type: bool
required: false
default: true
cloud_api_key:
grafana_api_key:
description:
- CLoud API Key to authenticate with Grafana Cloud.
- Grafana API Key to authenticate with Grafana.
type: str
required : true
stack_slug:
description:
- Name of the Grafana Cloud stack to which the folder will be added
type: str
required: true
state:
description:
- State for the Grafana CLoud stack.
@ -46,14 +58,14 @@ EXAMPLES = '''
uid: folder_name
overwrite: true
stack_slug: "{{ stack_slug }}"
cloud_api_key: "{{ grafana_cloud_api_key }}"
grafana_api_key: "{{ grafana_api_key }}"
state: present
- name: Delete a Folder in Grafana
grafana.grafana.folder:
uid: folder_name
stack_slug: "{{ stack_slug }}"
cloud_api_key: "{{ grafana_cloud_api_key }}"
grafana_api_key: "{{ grafana_api_key }}"
state: absent
'''
@ -126,7 +138,13 @@ output:
'''
from ansible.module_utils.basic import AnsibleModule
import requests
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
__metaclass__ = type
def present_folder(module):
@ -136,7 +154,7 @@ def present_folder(module):
}
api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/folders'
result = requests.post(api_url, json=body, headers={"Authorization": 'Bearer ' + module.params['cloud_api_key']})
result = requests.post(api_url, json=body, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']})
if result.status_code == 200:
return False, True, result.json()
@ -148,7 +166,7 @@ def present_folder(module):
}
api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/folders/' + module.params['uid']
result = requests.put(api_url, json=body, headers={"Authorization": 'Bearer ' + module.params['cloud_api_key']})
result = requests.put(api_url, json=body, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']})
if result.status_code == 200:
return False, True, result.json()
@ -162,7 +180,7 @@ def present_folder(module):
def absent_folder(module):
api_url = 'https://' + module.params['stack_slug'] + '.grafana.net/api/folders/' + module.params['uid']
result = requests.delete(api_url, headers={"Authorization": 'Bearer ' + module.params['cloud_api_key']})
result = requests.delete(api_url, headers={"Authorization": 'Bearer ' + module.params['grafana_api_key']})
if result.status_code == 200:
return False, True, result.json()
@ -176,7 +194,7 @@ def main():
uid=dict(type='str', required=True),
overwrite=dict(type='bool', required=False, default=True),
stack_slug=dict(type='str', required=True),
cloud_api_key=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'])
)
@ -200,4 +218,4 @@ def main():
if __name__ == '__main__':
main()
main()

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
requests