Skip to content

Commit

Permalink
Add testing and fixed bug when spacing issue
Browse files Browse the repository at this point in the history
  • Loading branch information
FragmentedPacket committed Mar 25, 2022
1 parent d5a1fdc commit 52e9eda
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 17 deletions.
40 changes: 25 additions & 15 deletions plugins/filter/graphql.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
"""GraphQL related filter plugins."""
# Copyright (c) 2022, Network to Code (@networktocode) <info@networktocode.com>
# 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

__metaclass__ = type


def build_graphql_filter_string(filter: dict) -> str:
Expand All @@ -16,7 +22,7 @@ def build_graphql_filter_string(filter: dict) -> str:
temp_string = f"{key}: "
value_string = f"{value}"

# GraphQL variables do not need quotes
# GraphQL variables do not need quotes (This isn't completely support with inventory yet, but code added here)
if isinstance(value, str) and not key.startswith("$"):
value_string = "'" + value_string + "'"

Expand All @@ -34,29 +40,33 @@ def convert_to_graphql_string(query: dict, start=0) -> str:
Returns:
str: GraphQL query string
"""
graphql_string = f""""""
graphql_string = """"""
loop_index = 0
query_len = len(query)
for k, v in query.items():
loop_string = "{}".format(" " * (start * 2))
loop_index += 1
loop_string = "".rjust(start * 2, " ")
loop_filter = None

# Determine what to do
if not v:
loop_string += f"{k}\n"
loop_string += f"{k}"
elif isinstance(v, dict):
if v.get("filters"):
loop_filter = build_graphql_filter_string(v.pop("filters"))
# Increment start for recursion
start += 1
loop_string += "{0} {1}\n".format(k, loop_filter + " {" if loop_filter else " {")
loop_string += convert_to_graphql_string(v, start)
# Decrement start to continue at the same level we were at prior to recursion
start -= 1
loop_string += "{0}{1}\n".format(" " * (start * 2), "}")
loop_string += "{0} {1}\n".format(k, loop_filter + " {" if loop_filter else "{")
loop_string += convert_to_graphql_string(v, start + 1)
loop_string += "{0}{1}".format(" " * (start * 2), "}")
else:
loop_string += '{0} {1}\n'.format(k, "{")
# We want to keep the doubling spaces, but add 2 more
loop_string += "{0} {1}\n".format(k, "{")
# We want to keep the double spaces, but add 2 more
loop_string += "{0}".format(" " * (start * 2 + 2))
loop_string += f"{v}\n"
loop_string += "{0}{1}\n".format(" " * (start * 2), "}")
# loop_string += "}\n"
loop_string += "{0}{1}".format(" " * (start * 2), "}")

if loop_index != query_len or start > 0:
loop_string += "\n"

graphql_string += loop_string

return graphql_string.replace("'", '"')
Expand Down
14 changes: 12 additions & 2 deletions plugins/inventory/gql_inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,22 @@
# inventory.yml file in YAML format
# Example command line: ansible-inventory -v --list -i inventory.yml
# Add additional query parameter with query key
# Add additional query parameter with query key and use filters
plugin: networktocode.nautobot.gql_inventory
api_endpoint: http://localhost:8000
validate_certs: True
query:
tags: name
serial:
site:
filters:
tenant: "den"
name:
description:
contact_name:
description:
region:
name:
# To group by use group_by key
# Specify the full path to the data you would like to use to group by.
Expand Down Expand Up @@ -134,6 +144,7 @@
from ansible.module_utils.urls import open_url

from ansible.module_utils.six.moves.urllib import error as urllib_error

# from jinja2 import Environment, FileSystemLoader
from ansible_collections.networktocode.nautobot.plugins.filter.graphql import convert_to_graphql_string

Expand Down Expand Up @@ -251,7 +262,6 @@ def main(self):
"primary_ip4": "address",
"device_role": "name",
"site": "name",

}
}
base_query["devices"].update(self.gql_query)
Expand Down
Empty file added tests/unit/filter/__init__.py
Empty file.
65 changes: 65 additions & 0 deletions tests/unit/filter/test_data/graphql_string.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
[
{
"query": {
"serial": null,
"asset_tag": null
},
"expected": "serial\nasset_tag"
},
{
"query": {
"serial": null,
"asset_tag": null,
"site": {
"name": null,
"contact_name": null,
"description": null,
"region": {
"name": null,
"parent": {
"name": null
}
}
}
},
"expected": "serial\nasset_tag\nsite {\n name\n contact_name\n description\n region {\n name\n parent {\n name\n }\n }\n}"
},
{
"query": {
"serial": null,
"asset_tag": null,
"site": {
"filters": {
"role": "core",
"tenant": "den"
},
"name": null,
"contact_name": null,
"description": null,
"region": {
"filters": {
"$tenant": "den"
},
"name": null,
"parent": {
"name": null
}
}
}
},
"expected": "serial\nasset_tag\nsite (role: \"core\", tenant: \"den\") {\n name\n contact_name\n description\n region ($tenant: den) {\n name\n parent {\n name\n }\n }\n}"
},
{
"query": {
"device": {
"name": null,
"platform": "napalm_driver",
"status": "name",
"primary_ip4": "address",
"device_role": "name",
"site": "name"
}
},
"expected": "device {\n name\n platform {\n napalm_driver\n }\n status {\n name\n }\n primary_ip4 {\n address\n }\n device_role {\n name\n }\n site {\n name\n }\n}"
}
]
25 changes: 25 additions & 0 deletions tests/unit/filter/test_graphql.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Tests for Nautobot GraphQL filter plugins."""

import json
import pytest
from ansible_collections.networktocode.nautobot.plugins.filter.graphql import (
convert_to_graphql_string,
build_graphql_filter_string,
)


def load_test_data(test):
with open(f"tests/unit/filter/test_data/{test}.json", "r") as f:
data = json.loads(f.read())
return data


@pytest.mark.parametrize(("test_data"), load_test_data("graphql_string"))
def test_convert_to_graphql_string(test_data):
result = convert_to_graphql_string(test_data["query"])
assert result == test_data["expected"]


def test_build_graphql_filter_string():
gql_filters = {"role": "core", "$tenant": "den", "device_type": "c9300"}
assert build_graphql_filter_string(gql_filters) == "(role: 'core', $tenant: den, device_type: 'c9300')"

0 comments on commit 52e9eda

Please sign in to comment.