summaryrefslogtreecommitdiff
path: root/src/services/api/graphql/utils
diff options
context:
space:
mode:
authorJohn Estabrook <jestabro@vyos.io>2022-10-23 11:06:03 -0500
committerJohn Estabrook <jestabro@vyos.io>2022-10-25 09:03:06 -0500
commit7038b761302be2ec90338981830b8cd7cf887381 (patch)
tree1eb7c93dba0694b8c6dbce1ec522a2a61b06a439 /src/services/api/graphql/utils
parent093ac258c11894b07afd9e85a61778d23e356718 (diff)
downloadvyos-1x-7038b761302be2ec90338981830b8cd7cf887381.tar.gz
vyos-1x-7038b761302be2ec90338981830b8cd7cf887381.zip
graphql: T4574: reorganize directory structure for clarity
Diffstat (limited to 'src/services/api/graphql/utils')
-rw-r--r--src/services/api/graphql/utils/composite_function.py11
-rw-r--r--src/services/api/graphql/utils/config_session_function.py28
-rwxr-xr-xsrc/services/api/graphql/utils/schema_from_composite.py119
-rwxr-xr-xsrc/services/api/graphql/utils/schema_from_config_session.py119
-rwxr-xr-xsrc/services/api/graphql/utils/schema_from_op_mode.py183
-rw-r--r--src/services/api/graphql/utils/util.py100
6 files changed, 0 insertions, 560 deletions
diff --git a/src/services/api/graphql/utils/composite_function.py b/src/services/api/graphql/utils/composite_function.py
deleted file mode 100644
index bc9d80fbb..000000000
--- a/src/services/api/graphql/utils/composite_function.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# typing information for composite functions: those that invoke several
-# elementary requests, and return the result as a single dict
-import typing
-
-def system_status():
- pass
-
-queries = {'system_status': system_status}
-
-mutations = {}
-
diff --git a/src/services/api/graphql/utils/config_session_function.py b/src/services/api/graphql/utils/config_session_function.py
deleted file mode 100644
index fc0dd7a87..000000000
--- a/src/services/api/graphql/utils/config_session_function.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# typing information for native configsession functions; used to generate
-# schema definition files
-import typing
-
-def show_config(path: list[str], configFormat: typing.Optional[str]):
- pass
-
-def show(path: list[str]):
- pass
-
-queries = {'show_config': show_config,
- 'show': show}
-
-def save_config_file(fileName: typing.Optional[str]):
- pass
-def load_config_file(fileName: str):
- pass
-def add_system_image(location: str):
- pass
-def delete_system_image(name: str):
- pass
-
-mutations = {'save_config_file': save_config_file,
- 'load_config_file': load_config_file,
- 'add_system_image': add_system_image,
- 'delete_system_image': delete_system_image}
-
-
diff --git a/src/services/api/graphql/utils/schema_from_composite.py b/src/services/api/graphql/utils/schema_from_composite.py
deleted file mode 100755
index d5e0ecdf6..000000000
--- a/src/services/api/graphql/utils/schema_from_composite.py
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2022 VyOS maintainers and contributors
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 or later as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-# A utility to generate GraphQL schema defintions from typing information of
-# composite functions comprising several requests.
-
-import os
-import json
-from inspect import signature, getmembers, isfunction, isclass, getmro
-from jinja2 import Template
-
-from vyos.defaults import directories
-if __package__ is None or __package__ == '':
- from util import snake_to_pascal_case, map_type_name
- from composite_function import queries, mutations
-else:
- from . util import snake_to_pascal_case, map_type_name
- from . composite_function import queries, mutations
-
-SCHEMA_PATH = directories['api_schema']
-
-schema_data: dict = {'schema_name': '',
- 'schema_fields': []}
-
-query_template = """
-input {{ schema_name }}Input {
- key: String!
- {%- for field_entry in schema_fields %}
- {{ field_entry }}
- {%- endfor %}
-}
-
-type {{ schema_name }} {
- result: Generic
-}
-
-type {{ schema_name }}Result {
- data: {{ schema_name }}
- success: Boolean!
- errors: [String]
-}
-
-extend type Query {
- {{ schema_name }}(data: {{ schema_name }}Input) : {{ schema_name }}Result @compositequery
-}
-"""
-
-mutation_template = """
-input {{ schema_name }}Input {
- key: String!
- {%- for field_entry in schema_fields %}
- {{ field_entry }}
- {%- endfor %}
-}
-
-type {{ schema_name }} {
- result: Generic
-}
-
-type {{ schema_name }}Result {
- data: {{ schema_name }}
- success: Boolean!
- errors: [String]
-}
-
-extend type Mutation {
- {{ schema_name }}(data: {{ schema_name }}Input) : {{ schema_name }}Result @compositemutation
-}
-"""
-
-def create_schema(func_name: str, func: callable, template: str) -> str:
- sig = signature(func)
-
- field_dict = {}
- for k in sig.parameters:
- field_dict[sig.parameters[k].name] = map_type_name(sig.parameters[k].annotation)
-
- schema_fields = []
- for k,v in field_dict.items():
- schema_fields.append(k+': '+v)
-
- schema_data['schema_name'] = snake_to_pascal_case(func_name)
- schema_data['schema_fields'] = schema_fields
-
- j2_template = Template(template)
- res = j2_template.render(schema_data)
-
- return res
-
-def generate_composite_definitions():
- results = []
- for name,func in queries.items():
- res = create_schema(name, func, query_template)
- results.append(res)
-
- for name,func in mutations.items():
- res = create_schema(name, func, mutation_template)
- results.append(res)
-
- out = '\n'.join(results)
- with open(f'{SCHEMA_PATH}/composite.graphql', 'w') as f:
- f.write(out)
-
-if __name__ == '__main__':
- generate_composite_definitions()
diff --git a/src/services/api/graphql/utils/schema_from_config_session.py b/src/services/api/graphql/utils/schema_from_config_session.py
deleted file mode 100755
index b6609357e..000000000
--- a/src/services/api/graphql/utils/schema_from_config_session.py
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2022 VyOS maintainers and contributors
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 or later as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-# A utility to generate GraphQL schema defintions from typing information of
-# (wrappers of) native configsession functions.
-
-import os
-import json
-from inspect import signature, getmembers, isfunction, isclass, getmro
-from jinja2 import Template
-
-from vyos.defaults import directories
-if __package__ is None or __package__ == '':
- from util import snake_to_pascal_case, map_type_name
- from config_session_function import queries, mutations
-else:
- from . util import snake_to_pascal_case, map_type_name
- from . config_session_function import queries, mutations
-
-SCHEMA_PATH = directories['api_schema']
-
-schema_data: dict = {'schema_name': '',
- 'schema_fields': []}
-
-query_template = """
-input {{ schema_name }}Input {
- key: String!
- {%- for field_entry in schema_fields %}
- {{ field_entry }}
- {%- endfor %}
-}
-
-type {{ schema_name }} {
- result: Generic
-}
-
-type {{ schema_name }}Result {
- data: {{ schema_name }}
- success: Boolean!
- errors: [String]
-}
-
-extend type Query {
- {{ schema_name }}(data: {{ schema_name }}Input) : {{ schema_name }}Result @configsessionquery
-}
-"""
-
-mutation_template = """
-input {{ schema_name }}Input {
- key: String!
- {%- for field_entry in schema_fields %}
- {{ field_entry }}
- {%- endfor %}
-}
-
-type {{ schema_name }} {
- result: Generic
-}
-
-type {{ schema_name }}Result {
- data: {{ schema_name }}
- success: Boolean!
- errors: [String]
-}
-
-extend type Mutation {
- {{ schema_name }}(data: {{ schema_name }}Input) : {{ schema_name }}Result @configsessionmutation
-}
-"""
-
-def create_schema(func_name: str, func: callable, template: str) -> str:
- sig = signature(func)
-
- field_dict = {}
- for k in sig.parameters:
- field_dict[sig.parameters[k].name] = map_type_name(sig.parameters[k].annotation)
-
- schema_fields = []
- for k,v in field_dict.items():
- schema_fields.append(k+': '+v)
-
- schema_data['schema_name'] = snake_to_pascal_case(func_name)
- schema_data['schema_fields'] = schema_fields
-
- j2_template = Template(template)
- res = j2_template.render(schema_data)
-
- return res
-
-def generate_config_session_definitions():
- results = []
- for name,func in queries.items():
- res = create_schema(name, func, query_template)
- results.append(res)
-
- for name,func in mutations.items():
- res = create_schema(name, func, mutation_template)
- results.append(res)
-
- out = '\n'.join(results)
- with open(f'{SCHEMA_PATH}/configsession.graphql', 'w') as f:
- f.write(out)
-
-if __name__ == '__main__':
- generate_config_session_definitions()
diff --git a/src/services/api/graphql/utils/schema_from_op_mode.py b/src/services/api/graphql/utils/schema_from_op_mode.py
deleted file mode 100755
index 57d63628b..000000000
--- a/src/services/api/graphql/utils/schema_from_op_mode.py
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2022 VyOS maintainers and contributors
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 or later as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-# A utility to generate GraphQL schema defintions from standardized op-mode
-# scripts.
-
-import os
-import json
-from inspect import signature, getmembers, isfunction, isclass, getmro
-from jinja2 import Template
-
-from vyos.defaults import directories
-if __package__ is None or __package__ == '':
- from util import load_as_module, is_op_mode_function_name, is_show_function_name
- from util import snake_to_pascal_case, map_type_name
-else:
- from . util import load_as_module, is_op_mode_function_name, is_show_function_name
- from . util import snake_to_pascal_case, map_type_name
-
-OP_MODE_PATH = directories['op_mode']
-SCHEMA_PATH = directories['api_schema']
-DATA_DIR = directories['data']
-
-op_mode_include_file = os.path.join(DATA_DIR, 'op-mode-standardized.json')
-op_mode_error_schema = 'op_mode_error.graphql'
-
-schema_data: dict = {'schema_name': '',
- 'schema_fields': []}
-
-query_template = """
-input {{ schema_name }}Input {
- key: String!
- {%- for field_entry in schema_fields %}
- {{ field_entry }}
- {%- endfor %}
-}
-
-type {{ schema_name }} {
- result: Generic
-}
-
-type {{ schema_name }}Result {
- data: {{ schema_name }}
- op_mode_error: OpModeError
- success: Boolean!
- errors: [String]
-}
-
-extend type Query {
- {{ schema_name }}(data: {{ schema_name }}Input) : {{ schema_name }}Result @genopquery
-}
-"""
-
-mutation_template = """
-input {{ schema_name }}Input {
- key: String!
- {%- for field_entry in schema_fields %}
- {{ field_entry }}
- {%- endfor %}
-}
-
-type {{ schema_name }} {
- result: Generic
-}
-
-type {{ schema_name }}Result {
- data: {{ schema_name }}
- op_mode_error: OpModeError
- success: Boolean!
- errors: [String]
-}
-
-extend type Mutation {
- {{ schema_name }}(data: {{ schema_name }}Input) : {{ schema_name }}Result @genopmutation
-}
-"""
-
-error_template = """
-interface OpModeError {
- name: String!
- message: String!
- vyos_code: Int!
-}
-{% for name in error_names %}
-type {{ name }} implements OpModeError {
- name: String!
- message: String!
- vyos_code: Int!
-}
-{%- endfor %}
-"""
-
-def create_schema(func_name: str, base_name: str, func: callable) -> str:
- sig = signature(func)
-
- field_dict = {}
- for k in sig.parameters:
- field_dict[sig.parameters[k].name] = map_type_name(sig.parameters[k].annotation)
-
- # It is assumed that if one is generating a schema for a 'show_*'
- # function, that 'get_raw_data' is present and 'raw' is desired.
- if 'raw' in list(field_dict):
- del field_dict['raw']
-
- schema_fields = []
- for k,v in field_dict.items():
- schema_fields.append(k+': '+v)
-
- schema_data['schema_name'] = snake_to_pascal_case(func_name + '_' + base_name)
- schema_data['schema_fields'] = schema_fields
-
- if is_show_function_name(func_name):
- j2_template = Template(query_template)
- else:
- j2_template = Template(mutation_template)
-
- res = j2_template.render(schema_data)
-
- return res
-
-def create_error_schema():
- from vyos import opmode
-
- e = Exception
- err_types = getmembers(opmode, isclass)
- err_types = [k for k in err_types if issubclass(k[1], e)]
- # drop base class, to be replaced by interface type. Find the class
- # programmatically, in case the base class name changes.
- for i in range(len(err_types)):
- if err_types[i][1] in getmro(err_types[i-1][1]):
- del err_types[i]
- break
- err_names = [k[0] for k in err_types]
- error_data = {'error_names': err_names}
- j2_template = Template(error_template)
- res = j2_template.render(error_data)
-
- return res
-
-def generate_op_mode_definitions():
- out = create_error_schema()
- with open(f'{SCHEMA_PATH}/{op_mode_error_schema}', 'w') as f:
- f.write(out)
-
- with open(op_mode_include_file) as f:
- op_mode_files = json.load(f)
-
- for file in op_mode_files:
- basename = os.path.splitext(file)[0].replace('-', '_')
- module = load_as_module(basename, os.path.join(OP_MODE_PATH, file))
-
- funcs = getmembers(module, isfunction)
- funcs = list(filter(lambda ft: is_op_mode_function_name(ft[0]), funcs))
-
- funcs_dict = {}
- for (name, thunk) in funcs:
- funcs_dict[name] = thunk
-
- results = []
- for name,func in funcs_dict.items():
- res = create_schema(name, basename, func)
- results.append(res)
-
- out = '\n'.join(results)
- with open(f'{SCHEMA_PATH}/{basename}.graphql', 'w') as f:
- f.write(out)
-
-if __name__ == '__main__':
- generate_op_mode_definitions()
diff --git a/src/services/api/graphql/utils/util.py b/src/services/api/graphql/utils/util.py
deleted file mode 100644
index da2bcdb5b..000000000
--- a/src/services/api/graphql/utils/util.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright 2022 VyOS maintainers and contributors <maintainers@vyos.io>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this library. If not, see <http://www.gnu.org/licenses/>.
-
-import os
-import re
-import typing
-import importlib.util
-
-from vyos.defaults import directories
-
-def load_as_module(name: str, path: str):
- spec = importlib.util.spec_from_file_location(name, path)
- mod = importlib.util.module_from_spec(spec)
- spec.loader.exec_module(mod)
- return mod
-
-def load_op_mode_as_module(name: str):
- path = os.path.join(directories['op_mode'], name)
- name = os.path.splitext(name)[0].replace('-', '_')
- return load_as_module(name, path)
-
-def is_op_mode_function_name(name):
- if re.match(r"^(show|clear|reset|restart)", name):
- return True
- return False
-
-def is_show_function_name(name):
- if re.match(r"^show", name):
- return True
- return False
-
-def _nth_split(delim: str, n: int, s: str):
- groups = s.split(delim)
- l = len(groups)
- if n > l-1 or n < 1:
- return (s, '')
- return (delim.join(groups[:n]), delim.join(groups[n:]))
-
-def _nth_rsplit(delim: str, n: int, s: str):
- groups = s.split(delim)
- l = len(groups)
- if n > l-1 or n < 1:
- return (s, '')
- return (delim.join(groups[:l-n]), delim.join(groups[l-n:]))
-
-# Since we have mangled possible hyphens in the file name while constructing
-# the snake case of the query/mutation name, we will need to recover the
-# file name by searching with mangling:
-def _filter_on_mangled(test):
- def func(elem):
- mangle = os.path.splitext(elem)[0].replace('-', '_')
- return test == mangle
- return func
-
-# Find longest name in concatenated string that matches the basename of an
-# op-mode script. Should one prefer to concatenate in the reverse order
-# (script_name + '_' + function_name), use _nth_rsplit.
-def split_compound_op_mode_name(name: str, files: list):
- for i in range(1, name.count('_') + 1):
- pair = _nth_split('_', i, name)
- f = list(filter(_filter_on_mangled(pair[1]), files))
- if f:
- pair = (pair[0], f[0])
- return pair
- return (name, '')
-
-def snake_to_pascal_case(name: str) -> str:
- res = ''.join(map(str.title, name.split('_')))
- return res
-
-def map_type_name(type_name: type, optional: bool = False) -> str:
- if type_name == str:
- return 'String!' if not optional else 'String = null'
- if type_name == int:
- return 'Int!' if not optional else 'Int = null'
- if type_name == bool:
- return 'Boolean!' if not optional else 'Boolean = false'
- if typing.get_origin(type_name) == list:
- if not optional:
- return f'[{map_type_name(typing.get_args(type_name)[0])}]!'
- return f'[{map_type_name(typing.get_args(type_name)[0])}]'
- # typing.Optional is typing.Union[_, NoneType]
- if (typing.get_origin(type_name) is typing.Union and
- typing.get_args(type_name)[1] == type(None)):
- return f'{map_type_name(typing.get_args(type_name)[0], optional=True)}'
-
- # scalar 'Generic' is defined in schema.graphql
- return 'Generic'