From a5e7b3b678bc509569b021f0c04b55a37226bbdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kr=C3=B6ger?= Date: Tue, 30 Apr 2024 14:11:52 +0200 Subject: [PATCH 01/11] Remove unused imports --- serveradmin/servershell/views.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/serveradmin/servershell/views.py b/serveradmin/servershell/views.py index 0a3239a6..fea02c0e 100644 --- a/serveradmin/servershell/views.py +++ b/serveradmin/servershell/views.py @@ -23,7 +23,7 @@ HttpResponseBadRequest, HttpResponseNotFound, HttpRequest ) -from django.shortcuts import redirect, render, get_object_or_404 +from django.shortcuts import redirect, render from django.template.response import TemplateResponse from django.urls import reverse from django.utils.html import mark_safe, escape as escape_html @@ -34,7 +34,6 @@ from adminapi.filters import Any, ContainedOnlyBy, filter_classes, Not from adminapi.parse import parse_query from adminapi.request import json_encode_extra - from serveradmin.dataset import Query from serveradmin.serverdb.models import ( Servertype, @@ -44,10 +43,6 @@ ) from serveradmin.serverdb.query_committer import commit_query from serveradmin.servershell.helper import get_default_shown_attributes -from serveradmin.servershell.helper.autocomplete import ( - attribute_value_startswith, - attribute_startswith -) from serveradmin.servershell.merged_query_iterator import MergedQuery from serveradmin.servershell.utils import servershell_plugins From 1baca87d27d16ec01d6a535f7f3a3cbd10a70b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kr=C3=B6ger?= Date: Tue, 30 Apr 2024 14:26:56 +0200 Subject: [PATCH 02/11] Add ruff to development dependencies --- Pipfile | 1 + Pipfile.lock | 27 ++++++++++++++++++++++++++- ruff.toml | 9 +++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 ruff.toml diff --git a/Pipfile b/Pipfile index 4ef91b1e..f18a2d9b 100644 --- a/Pipfile +++ b/Pipfile @@ -44,6 +44,7 @@ setuptools = "*" # Generate fake data for tests faker = "<14.0.0" tblib = "*" +ruff ="*" [requires] python_version = "3.9" diff --git a/Pipfile.lock b/Pipfile.lock index a304f804..0ef733c3 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "a408c855a489afeb47d03d4eb74f197595058a3e58d96c29ccf79131e0a1cc80" + "sha256": "faafdd7521cce05872b2169f2b7d8b30b1ddfac48cc834edb238529fe98a6b80" }, "pipfile-spec": 6, "requires": { @@ -1024,6 +1024,31 @@ "markers": "python_version >= '3.8'", "version": "==2.32.3" }, + "ruff": { + "hashes": [ + "sha256:049a191969a10897fe052ef9cc7491b3ef6de79acd7790af7d7897b7a9bfbcb6", + "sha256:1bc09a7419e09662983b1312f6fa5dab829d6ab5d11f18c3760be7ca521c9329", + "sha256:3191e9116b6b5bbe187447656f0c8526f0d36b6fd89ad78ccaad6bdc2fad7df2", + "sha256:38c23fd9bdec4eb437b4c1e3595905a0a8edfccd63a790f818b28c78fe345639", + "sha256:3c3156d3f4b42e57247275a0a7e15a851c165a4fc89c5e8fa30ea6da4f7407b8", + "sha256:490b1e147c1260545f6d041c4092483e3f6d8eba81dc2875eaebcf9140b53905", + "sha256:6fbb2aed66fe742a6a3a0075ed467a459b7cedc5ae01008340075909d819df1e", + "sha256:7c8661b0be91a38bd56db593e9331beaf9064a79028adee2d5f392674bbc5e88", + "sha256:868364fc23f5aa122b00c6f794211e85f7e78f5dffdf7c590ab90b8c4e69b657", + "sha256:92c0c1ff014351c0b0cdfdb1e35fa83b780f1e065667167bb9502d47ca41e6db", + "sha256:96bc89a5c5fd21a04939773f9e0e276308be0935de06845110f43fd5c2e4ead7", + "sha256:a9352b9d767889ec5df1483f94870564e8102d4d7e99da52ebf564b882cdc2c7", + "sha256:b6c0e8d3d2db7e9f6efd884f44b8dc542d5b6b590fc4bb334fdbc624d93a29a2", + "sha256:bcfa478daf61ac8002214eb2ca5f3e9365048506a9d52b11bea3ecea822bb844", + "sha256:c58bfa00e740ca0a6c43d41fb004cd22d165302f360aaa56f7126d544db31a21", + "sha256:dc67e32bc3b29557513eb7eeabb23efdb25753684b913bebb8a0c62495095acb", + "sha256:e4fd5ff5de5f83e0458a138e8a869c7c5e907541aec32b707f57cf9a5e124445", + "sha256:e55c620690a4a7ee6f1cccb256ec2157dc597d109400ae75bbf944fc9d6462e2" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==0.11.0" + }, "setuptools": { "hashes": [ "sha256:34750dcb17d046929f545dec9b8349fe42bf4ba13ddffee78428aec422dbfb73", diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 00000000..8d524f63 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,9 @@ +line-length = 120 +target-version = "py39" + +[lint] +extend-select = ["I"] + +[format] +quote-style = "single" + From cb8753350e4de550a66a18ee4c715408564e5bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kr=C3=B6ger?= Date: Tue, 30 Apr 2024 14:27:18 +0200 Subject: [PATCH 03/11] Reformat code with ruff --- adminapi/api.py | 2 +- adminapi/cli.py | 6 +- adminapi/cmduser.py | 3 +- adminapi/dataset.py | 54 +-- adminapi/datatype.py | 12 +- adminapi/exceptions.py | 6 + adminapi/filters.py | 33 +- adminapi/parse.py | 40 +- adminapi/request.py | 27 +- adminapi/tests/test_cli.py | 8 +- adminapi/tests/test_dataset.py | 6 +- serveradmin/__main__.py | 1 + serveradmin/access_control/admin.py | 2 +- .../access_control/migrations/0001_initial.py | 26 +- .../0002_whitelist_blacklist_toggle.py | 13 +- .../0003_accesscontrolgroup_description.py | 1 - serveradmin/access_control/models.py | 12 +- serveradmin/access_control/tests/test_acl.py | 48 +-- serveradmin/api/__init__.py | 2 +- serveradmin/api/api.py | 6 +- serveradmin/api/apps.py | 4 +- serveradmin/api/decorators.py | 78 ++-- serveradmin/api/migrations/0001_api_lock.py | 4 +- serveradmin/api/urls.py | 6 +- serveradmin/api/utils.py | 2 +- serveradmin/api/views.py | 21 +- serveradmin/apps/admin.py | 20 +- .../apps/management/commands/createapp.py | 29 +- serveradmin/apps/migrations/0001_initial.py | 3 +- .../migrations/0002_public_key_support.py | 10 +- .../apps/migrations/0003_public_key_length.py | 1 - .../migrations/0004_application_last_login.py | 1 - serveradmin/apps/models.py | 20 +- .../management/commands/createdefaultuser.py | 1 + serveradmin/common/templatetags/__init__.py | 1 - serveradmin/common/templatetags/common.py | 2 +- serveradmin/common/utils.py | 5 +- serveradmin/dataset.py | 8 +- .../management/commands/cache_graphite.py | 88 ++--- .../graphite/migrations/0001_initial.py | 120 +++++- ..._template_and_variation_name_validation.py | 1 - serveradmin/graphite/models.py | 142 ++++--- serveradmin/graphite/validators.py | 4 +- serveradmin/graphite/views.py | 62 ++- serveradmin/resources/__init__.py | 1 - .../commands/clear_migration_log.py | 21 +- serveradmin/resources/urls.py | 2 +- serveradmin/resources/views.py | 90 +++-- serveradmin/serverdb/admin.py | 57 ++- serveradmin/serverdb/forms.py | 8 +- .../serverdb/migrations/0001_initial.py | 304 ++++++++++++-- .../migrations/0003_server_indexing.py | 5 +- .../migrations/0005_attribute_clone.py | 7 +- .../migrations/0006_datetime_datatype.py | 24 +- .../migrations/0007_hostname_regex_hyphens.py | 28 +- .../migrations/0008_hostname_length_254.py | 13 +- ...09_servertype_and_attribute_definitions.py | 40 +- .../serverdb/migrations/0010_delete_change.py | 1 - .../migrations/0011_create_change_table.py | 10 +- .../migrations/0012_migrate_change_tables.py | 29 +- .../serverdb/migrations/0013_change_index.py | 1 - .../0014_delete_deprecated_change_models.py | 1 - .../0015_attribute_history_field.py | 4 +- .../0016_optional_servertype_for_relation.py | 7 +- .../migrations/0017_inet_family_choice.py | 5 +- .../migrations/0018_alter_server_hostname.py | 26 +- .../0019_drop_intern_ip_constraint.py | 3 +- serveradmin/serverdb/models.py | 371 ++++++++---------- serveradmin/serverdb/query_committer.py | 194 ++++----- serveradmin/serverdb/query_executer.py | 44 +-- serveradmin/serverdb/signals.py | 2 - serveradmin/serverdb/tests/test_acls.py | 196 +++------ serveradmin/serverdb/tests/test_attribute.py | 12 +- serveradmin/serverdb/tests/test_views.py | 12 +- serveradmin/serverdb/urls.py | 2 +- serveradmin/serverdb/views.py | 111 +++--- serveradmin/servershell/__init__.py | 1 - serveradmin/servershell/helper/__init__.py | 9 +- .../servershell/helper/autocomplete.py | 35 +- .../servershell/merged_query_iterator.py | 2 + .../servershell/templatetags/serversearch.py | 16 +- .../servershell/templatetags/servershell.py | 2 +- serveradmin/servershell/urls.py | 14 +- serveradmin/servershell/utils.py | 4 +- serveradmin/servershell/views.py | 284 ++++++-------- serveradmin/settings.py | 24 +- serveradmin/test_dataset.py | 5 +- serveradmin/urls.py | 8 +- serveradmin/wsgi.py | 8 +- setup.py | 4 +- 90 files changed, 1563 insertions(+), 1425 deletions(-) diff --git a/adminapi/api.py b/adminapi/api.py index d94d70ec..1fd1baa8 100644 --- a/adminapi/api.py +++ b/adminapi/api.py @@ -3,8 +3,8 @@ Copyright (c) 2019 InnoGames GmbH """ -from adminapi.request import send_request from adminapi.exceptions import ApiError +from adminapi.request import send_request API_CALL_ENDPOINT = '/call' diff --git a/adminapi/cli.py b/adminapi/cli.py index 3d35e876..778e2c3b 100644 --- a/adminapi/cli.py +++ b/adminapi/cli.py @@ -2,6 +2,7 @@ Copyright (c) 2019 InnoGames GmbH """ + import sys from argparse import ArgumentParser, ArgumentTypeError @@ -63,10 +64,7 @@ def main(): query = Query(filters, attribute_ids_to_fetch, args.order) if args.one and len(query) > 1: - raise Exception( - 'Expecting exactly one server, found {} servers' - .format(len(query)) - ) + raise Exception('Expecting exactly one server, found {} servers'.format(len(query))) for server in query: if args.reset: diff --git a/adminapi/cmduser.py b/adminapi/cmduser.py index d49fdde2..75287d48 100644 --- a/adminapi/cmduser.py +++ b/adminapi/cmduser.py @@ -4,8 +4,7 @@ """ import os -from os.path import isfile -from os.path import expanduser +from os.path import expanduser, isfile def get_auth_token(): diff --git a/adminapi/dataset.py b/adminapi/dataset.py index 22a992f4..7385d097 100644 --- a/adminapi/dataset.py +++ b/adminapi/dataset.py @@ -27,10 +27,7 @@ def __init__(self, filters=None, restrict=['hostname'], order_by=None): self._results = [] return - self._filters = { - a: f if isinstance(f, BaseFilter) else BaseFilter(f) - for a, f in filters.items() - } + self._filters = {a: f if isinstance(f, BaseFilter) else BaseFilter(f) for a, f in filters.items()} self._restrict = restrict self._order_by = order_by @@ -81,11 +78,7 @@ def _ensure_object_id(restrict): restrict = restrict.copy() restrict.append('object_id') - return [ - i if not isinstance(i, dict) else - {k: _ensure_object_id(v) for k, v in i.items()} - for i in restrict - ] + return [i if not isinstance(i, dict) else {k: _ensure_object_id(v) for k, v in i.items()} for i in restrict] self.__restrict = _ensure_object_id(new_restrict) @@ -105,14 +98,9 @@ def new_object(self, servertype): if self._filters: for attribute, filt in self._filters: if attribute not in obj: - raise DatasetError( - '"{}" is not on the new object'.format(attribute) - ) + raise DatasetError('"{}" is not on the new object'.format(attribute)) if not filt.matches(obj[attribute]): - raise DatasetError( - '"{}" is not consistent with the query' - .format(attribute) - ) + raise DatasetError('"{}" is not consistent with the query'.format(attribute)) self._get_results().append(obj) @@ -145,10 +133,7 @@ def order_by(self, *attribute_ids): def get(self): results = self._get_results() if len(results) != 1: - raise DatasetError( - 'get() requires exactly 1 matched object, {} found'.format( - len(results) - )) + raise DatasetError('get() requires exactly 1 matched object, {} found'.format(len(results))) return results[0] # XXX: Deprecated @@ -216,9 +201,12 @@ def get_free_ip_addrs(self): # Index host and network addresses separately used_hosts = set() used_networks = list() - for obj in type(self)({ - 'intern_ip': Any(*(ContainedOnlyBy(n) for n in networks)), - }, ['intern_ip']): + for obj in type(self)( + { + 'intern_ip': Any(*(ContainedOnlyBy(n) for n in networks)), + }, + ['intern_ip'], + ): addr = obj['intern_ip'] if isinstance(addr, (IPv4Address, IPv6Address)): used_hosts.add(addr) @@ -265,9 +253,7 @@ def get_free_ip_addr(self, lock=True): class Query(BaseQuery): def _fetch_new_object(self, servertype): - response = send_request( - NEW_OBJECT_ENDPOINT, [('servertype', servertype)] - ) + response = send_request(NEW_OBJECT_ENDPOINT, [('servertype', servertype)]) return _format_obj(response['result']) def commit(self): @@ -336,10 +322,7 @@ def commit_state(self): if self._deleted: return 'deleted' for attribute_id, old_value in self.old_values.items(): - if ( - json_encode_extra(self[attribute_id]) != - json_encode_extra(old_value) - ): + if json_encode_extra(self[attribute_id]) != json_encode_extra(old_value): return 'changed' return 'consistent' @@ -366,10 +349,7 @@ def _serialize_changes(self): for key, old_value in self.old_values.items(): new_value = self[key] - if ( - json_encode_extra(old_value) == - json_encode_extra(new_value) - ): + if json_encode_extra(old_value) == json_encode_extra(new_value): continue if isinstance(old_value, MultiAttr): @@ -430,9 +410,7 @@ def __setitem__(self, key, value): if self._deleted: raise DatasetError('Cannot set attributes to deleted object') if key not in self: - raise DatasetError( - 'Cannot set nonexistent attribute "{}"'.format(key) - ) + raise DatasetError('Cannot set nonexistent attribute "{}"'.format(key)) self._save_old_value(key) self.validate(key, value) @@ -611,4 +589,4 @@ def strtobool(val) -> bool: elif val in ('n', 'no', 'f', 'false', 'off', '0'): return False else: - raise ValueError(f"invalid truth value {val}") \ No newline at end of file + raise ValueError(f'invalid truth value {val}') diff --git a/adminapi/datatype.py b/adminapi/datatype.py index 2f298d0a..a23aba4d 100644 --- a/adminapi/datatype.py +++ b/adminapi/datatype.py @@ -2,11 +2,13 @@ Copyright (c) 2019 InnoGames GmbH """ + from datetime import date, datetime -from re import compile as re_compile from ipaddress import IPv4Address, IPv4Network, IPv6Address, IPv6Network +from re import compile as re_compile from netaddr import EUI + try: from netaddr import mac_unix_expanded except ImportError: @@ -14,7 +16,6 @@ from adminapi.exceptions import DatatypeError, FilterValueError - # We use a set of regular expressions to cast to datatypes. This module # is not aware of the attributes types of the server, neither it tries # to match with them one to one. Its purpose is to provide convenience @@ -100,10 +101,7 @@ def validate_value(value, datatype=None): if issubclass(newtype, supertype) and supertype != object: return supertype - raise DatatypeError( - 'Value from {} is not compatible with existing value from {}' - .format(type(value), datatype) - ) + raise DatatypeError('Value from {} is not compatible with existing value from {}'.format(type(value), datatype)) def str_to_datatype(value): @@ -123,7 +121,7 @@ def json_to_datatype(value): if regexp.match(str(value)): # date constructors need a decode format if datatype is date: - return datetime.strptime(value, "%Y-%m-%d").date() + return datetime.strptime(value, '%Y-%m-%d').date() if datatype is datetime: return datetime.strptime(value, '%Y-%m-%d %H:%M:%S%z') diff --git a/adminapi/exceptions.py b/adminapi/exceptions.py index 8cf8e6ce..0233df50 100644 --- a/adminapi/exceptions.py +++ b/adminapi/exceptions.py @@ -6,6 +6,7 @@ class AdminapiException(Exception): """Adminapi exception parent class.""" + pass @@ -15,6 +16,7 @@ class ConfigurationError(AdminapiException): class ApiError(AdminapiException): """An API request wasn't successful""" + def __init__(self, *args, **kwargs): if 'status_code' in kwargs: self.status_code = kwargs.pop('status_code') @@ -25,20 +27,24 @@ def __init__(self, *args, **kwargs): class AuthenticationError(AdminapiException): """No suitable authentication credentials available""" + pass class DatasetError(AdminapiException): """Something went wrong within a dataset instance""" + pass class DatatypeError(AdminapiException): """A query or dataset attribute had the wrong value datatype""" + pass # XXX: Sub-class ValueError for backwards compatibility class FilterValueError(DatatypeError, ValueError): """A filter value made no sense""" + pass diff --git a/adminapi/filters.py b/adminapi/filters.py index eba719d4..e85bc231 100644 --- a/adminapi/filters.py +++ b/adminapi/filters.py @@ -3,7 +3,8 @@ Copyright (c) 2019 InnoGames GmbH """ -from re import compile as re_compile, error as re_error +from re import compile as re_compile +from re import error as re_error from adminapi.datatype import STR_BASED_DATATYPES from adminapi.exceptions import FilterValueError @@ -20,14 +21,9 @@ def __init__(self, value): elif isinstance(value, str): for char in '\'"': if char in value: - raise FilterValueError( - '"{}" character is not allowed on filter values' - .format(char) - ) + raise FilterValueError('"{}" character is not allowed on filter values'.format(char)) else: - raise FilterValueError( - 'Filter value cannot be {}'.format(type(value).__name__) - ) + raise FilterValueError('Filter value cannot be {}'.format(type(value).__name__)) self.value = value @@ -121,13 +117,11 @@ def matches(self, value): class Any(BaseFilter): """Check if the attribute satisfies any of the conditions""" + func = any def __init__(self, *values): - self.values = [ - v if isinstance(v, BaseFilter) else BaseFilter(v) - for v in values - ] + self.values = [v if isinstance(v, BaseFilter) else BaseFilter(v) for v in values] def __repr__(self): return '{}({})'.format( @@ -141,9 +135,7 @@ def serialize(self): @classmethod def deserialize_value(cls, value): if not isinstance(value, list): - raise FilterValueError( - 'Invalid value for {}()'.format(cls.__name__) - ) + raise FilterValueError('Invalid value for {}()'.format(cls.__name__)) return cls(*[cls.deserialize(v) for v in value]) def matches(self, value): @@ -157,6 +149,7 @@ def destiny(self): class All(Any): """Check if an attribute satisfies all of the conditions""" + func = all def destiny(self): @@ -242,9 +235,7 @@ def serialize(self): @classmethod def deserialize_value(cls, value): if value is not None: - raise FilterValueError( - 'Invalid value for {}()'.format(cls.__name__) - ) + raise FilterValueError('Invalid value for {}()'.format(cls.__name__)) return cls() def matches(self, value): @@ -252,8 +243,4 @@ def matches(self, value): # Collect all classes that are subclass of BaseFilter (exclusive) -filter_classes = [ - v - for v in globals().values() - if type(v) == type and BaseFilter in v.mro()[1:] -] +filter_classes = [v for v in globals().values() if type(v) == type and BaseFilter in v.mro()[1:]] diff --git a/adminapi/parse.py b/adminapi/parse.py index 247e5bed..df0a86a2 100644 --- a/adminapi/parse.py +++ b/adminapi/parse.py @@ -4,7 +4,7 @@ """ from adminapi.datatype import DatatypeError, str_to_datatype -from adminapi.filters import BaseFilter, Any, Regexp, filter_classes +from adminapi.filters import Any, BaseFilter, Regexp, filter_classes _trigger_re_chars = ('.*', '.+', '[', ']', '|', '\\', '$', '^', '<') @@ -22,7 +22,7 @@ def parse_query(term, hostname=None): # NOQA: C901 if token != 'key': if hostname: # We already parsed a hostname, so we don't expect another one - raise DatatypeError("Garbled hostname: {0}".format(hostname)) + raise DatatypeError('Garbled hostname: {0}'.format(hostname)) term_parts = term.split(None, 1) if len(term_parts) == 2: @@ -61,10 +61,7 @@ def parse_query(term, hostname=None): # NOQA: C901 # Do not allow functions without preceding key # if they are on top level (e.g. call_depth = 0) if not stack or (call_depth == 0 and stack[-1][0] != 'key'): - raise DatatypeError( - 'Invalid term: top level function requires ' - 'preceding attribute' - ) + raise DatatypeError('Invalid term: top level function requires ' 'preceding attribute') call_depth += 1 stack.append(arg) @@ -84,9 +81,7 @@ def parse_query(term, hostname=None): # NOQA: C901 try: instance = filter_class(*fn_args) except TypeError: - raise DatatypeError( - 'Invalid function args ' + filter_class.__name__ - ) + raise DatatypeError('Invalid function args ' + filter_class.__name__) break else: raise DatatypeError('Invalid function ' + s_value) @@ -95,10 +90,7 @@ def parse_query(term, hostname=None): # NOQA: C901 elif token == 'literal': # Do not allow literals without key or function context if not stack or (call_depth == 0 and stack[-1][0] != 'key'): - raise DatatypeError( - 'Invalid term: Top level literals are not ' - 'allowed when attributes are used' - ) + raise DatatypeError('Invalid term: Top level literals are not ' 'allowed when attributes are used') if call_depth == 0: stack.append(('literal', BaseFilter(value))) else: @@ -106,15 +98,13 @@ def parse_query(term, hostname=None): # NOQA: C901 if stack and stack[0][0] == 'key': if len(stack) != 2: - raise DatatypeError( - 'Invalid term: Attribute requires one argument' - ) + raise DatatypeError('Invalid term: Attribute requires one argument') query_args[stack[0][1]] = stack[1][1] return query_args -def parse_function_string(args, strict=True): # NOQA C901 +def parse_function_string(args, strict=True): # NOQA C901 state = 'start' args_len = len(args) parsed_args = [] @@ -138,9 +128,7 @@ def parse_function_string(args, strict=True): # NOQA C901 if args[i] == '\\': if i == args_len - 1: if strict: - raise DatatypeError( - 'Escape is not allowed at the end' - ) + raise DatatypeError('Escape is not allowed at the end') if args[i + 1] == '\\': string_buf.append('\\') i += 2 @@ -159,9 +147,7 @@ def parse_function_string(args, strict=True): # NOQA C901 i += 1 elif state == 'unquotedstring': if args[i] == ' ': - parsed_args.append( - ('literal', str_to_datatype(args[string_start:i])) - ) + parsed_args.append(('literal', str_to_datatype(args[string_start:i]))) state = 'start' elif args[i] == '(': if string_start != i: @@ -170,17 +156,13 @@ def parse_function_string(args, strict=True): # NOQA C901 state = 'start' elif args[i] == ')' and call_depth != 0: if string_start != i: - parsed_args.append( - ('literal', str_to_datatype(args[string_start:i])) - ) + parsed_args.append(('literal', str_to_datatype(args[string_start:i]))) parsed_args.append(('endfunc', '')) call_depth -= 1 state = 'start' # Do not parse key inside functions or of preceding token # was also a key - elif args[i] == '=' and call_depth == 0 and ( - not parsed_args or parsed_args[-1][0] != 'key' - ): + elif args[i] == '=' and call_depth == 0 and (not parsed_args or parsed_args[-1][0] != 'key'): parsed_args.append(('key', args[string_start:i])) state = 'start' i += 1 diff --git a/adminapi/request.py b/adminapi/request.py index 09dd25d0..4e90ed81 100644 --- a/adminapi/request.py +++ b/adminapi/request.py @@ -2,6 +2,7 @@ Copyright (c) 2019 InnoGames GmbH """ + import gzip import logging import os @@ -27,10 +28,12 @@ try: from paramiko import RSAKey, ECDSAKey, Ed25519Key + key_classes = (RSAKey, ECDSAKey, Ed25519Key) except ImportError: # Ed25519Key requires paramiko >= 2.2 from paramiko import RSAKey, ECDSAKey + key_classes = (RSAKey, ECDSAKey) from adminapi.cmduser import get_auth_token @@ -118,9 +121,7 @@ def calc_signatures(private_keys, timestamp, data=None): def calc_security_token(auth_token, timestamp, data=None): message = calc_message(timestamp, data) - return hmac.new( - auth_token.encode('utf8'), message.encode('utf8'), sha1 - ).hexdigest() + return hmac.new(auth_token.encode('utf8'), message.encode('utf8'), sha1).hexdigest() def calc_app_id(auth_token): @@ -137,7 +138,7 @@ def send_request(endpoint, get_params=None, post_params=None): # In case of an error, sleep before trying again time.sleep(Settings.sleep_interval) else: - assert False # Cannot happen + assert False # Cannot happen content_encoding = response.info().get('Content-Encoding') content = response.read() @@ -146,6 +147,7 @@ def send_request(endpoint, get_params=None, post_params=None): return json.loads(content) + def _build_request(endpoint, get_params, post_params, retry=1): """Wrap request data in an urllib Request instance @@ -169,14 +171,10 @@ def _build_request(endpoint, get_params, post_params, retry=1): if Settings.auth_key: headers['X-PublicKeys'] = Settings.auth_key.get_base64() - headers['X-Signatures'] = calc_signature( - Settings.auth_key, timestamp, post_data - ) + headers['X-Signatures'] = calc_signature(Settings.auth_key, timestamp, post_data) elif Settings.auth_token: headers['X-Application'] = calc_app_id(Settings.auth_token) - headers['X-SecurityToken'] = calc_security_token( - Settings.auth_token, timestamp, post_data - ) + headers['X-SecurityToken'] = calc_security_token(Settings.auth_token, timestamp, post_data) else: try: agent = Agent() @@ -200,13 +198,12 @@ def _build_request(endpoint, get_params, post_params, retry=1): logger.error( f'Signing the requests took {time_spent_signing} seconds! ' 'Serveradmin would reject this request. Maybe your signing ' - f'soft-/hardware is congested ? Retry {retry}/{Settings.tries}.') - return _build_request(endpoint, get_params, post_params, retry+1) + f'soft-/hardware is congested ? Retry {retry}/{Settings.tries}.' + ) + return _build_request(endpoint, get_params, post_params, retry + 1) if not Settings.base_url: - raise ConfigurationError( - 'Environment variable SERVERADMIN_BASE_URL not set' - ) + raise ConfigurationError('Environment variable SERVERADMIN_BASE_URL not set') url = Settings.base_url + endpoint if get_params: diff --git a/adminapi/tests/test_cli.py b/adminapi/tests/test_cli.py index 7e729cd4..5de5a8ea 100644 --- a/adminapi/tests/test_cli.py +++ b/adminapi/tests/test_cli.py @@ -1,6 +1,6 @@ import unittest from argparse import ArgumentParser -from typing import Text, NoReturn +from typing import NoReturn, Text from adminapi.cli import parse_args @@ -13,11 +13,11 @@ def error(self, message: Text) -> NoReturn: class TestCommandlineInterface(unittest.TestCase): def test_no_argument(self, *args): - with self.assertRaises(SystemExit) as e: + with self.assertRaises(SystemExit): parse_args([]) def test_unknown_argument(self, *args): - with self.assertRaises(SystemExit) as e: + with self.assertRaises(SystemExit): parse_args(['project=adminapi', '--attr', 'state', 'spaceship']) def test_one_argument(self, *args): @@ -65,4 +65,4 @@ def test_update_argument(self, *args): self.assertEqual(args.update, [('hostname', 'SomeNewHostname')]) args = parse_args(['project=adminapi', '--update', 'hostname=SomeNewHostname', '-u', 'state=maintenance']) - self.assertEqual(args.update, [('hostname', 'SomeNewHostname'), ('state', 'maintenance')]) \ No newline at end of file + self.assertEqual(args.update, [('hostname', 'SomeNewHostname'), ('state', 'maintenance')]) diff --git a/adminapi/tests/test_dataset.py b/adminapi/tests/test_dataset.py index 132e14ee..5e91b0be 100644 --- a/adminapi/tests/test_dataset.py +++ b/adminapi/tests/test_dataset.py @@ -5,19 +5,19 @@ class TestStrtobool(unittest.TestCase): def test_true_values(self): - true_values = ["y", "yes", "t", "true", "on", "1"] + true_values = ['y', 'yes', 't', 'true', 'on', '1'] for value in true_values: with self.subTest(value=value): self.assertTrue(strtobool(value)) def test_false_values(self): - false_values = ["n", "no", "f", "false", "off", "0"] + false_values = ['n', 'no', 'f', 'false', 'off', '0'] for value in false_values: with self.subTest(value=value): self.assertFalse(strtobool(value)) def test_invalid_values(self): - invalid_values = ["maybe", "2", "none", "", "Yess"] + invalid_values = ['maybe', '2', 'none', '', 'Yess'] for value in invalid_values: with self.subTest(value=value): with self.assertRaises(ValueError): diff --git a/serveradmin/__main__.py b/serveradmin/__main__.py index ebb2eb44..4318548e 100755 --- a/serveradmin/__main__.py +++ b/serveradmin/__main__.py @@ -11,6 +11,7 @@ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'serveradmin.settings') + def main(): execute_from_command_line(sys.argv) diff --git a/serveradmin/access_control/admin.py b/serveradmin/access_control/admin.py index 341f5eb4..f8767a53 100644 --- a/serveradmin/access_control/admin.py +++ b/serveradmin/access_control/admin.py @@ -3,7 +3,7 @@ Copyright (c) 2019 InnoGames GmbH """ -from django.contrib.admin import site, ModelAdmin +from django.contrib.admin import ModelAdmin, site from serveradmin.access_control.models import AccessControlGroup diff --git a/serveradmin/access_control/migrations/0001_initial.py b/serveradmin/access_control/migrations/0001_initial.py index 5a944391..5d40d82e 100644 --- a/serveradmin/access_control/migrations/0001_initial.py +++ b/serveradmin/access_control/migrations/0001_initial.py @@ -5,7 +5,6 @@ class Migration(migrations.Migration): - initial = True dependencies = [ @@ -21,9 +20,28 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=80, unique=True)), ('query', models.CharField(max_length=1000)), - ('applications', models.ManyToManyField(blank=True, limit_choices_to={'disabled': False, 'superuser': False}, related_name='access_control_groups', to='apps.Application')), - ('attributes', models.ManyToManyField(blank=True, related_name='access_control_groups', to='serverdb.Attribute')), - ('members', models.ManyToManyField(blank=True, limit_choices_to={'is_active': True, 'is_superuser': False}, related_name='access_control_groups', to=settings.AUTH_USER_MODEL)), + ( + 'applications', + models.ManyToManyField( + blank=True, + limit_choices_to={'disabled': False, 'superuser': False}, + related_name='access_control_groups', + to='apps.Application', + ), + ), + ( + 'attributes', + models.ManyToManyField(blank=True, related_name='access_control_groups', to='serverdb.Attribute'), + ), + ( + 'members', + models.ManyToManyField( + blank=True, + limit_choices_to={'is_active': True, 'is_superuser': False}, + related_name='access_control_groups', + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ 'db_table': 'access_control_group', diff --git a/serveradmin/access_control/migrations/0002_whitelist_blacklist_toggle.py b/serveradmin/access_control/migrations/0002_whitelist_blacklist_toggle.py index 17ee85e5..23e0d0c6 100644 --- a/serveradmin/access_control/migrations/0002_whitelist_blacklist_toggle.py +++ b/serveradmin/access_control/migrations/0002_whitelist_blacklist_toggle.py @@ -5,7 +5,6 @@ class Migration(migrations.Migration): - dependencies = [ ('access_control', '0001_initial'), ] @@ -14,11 +13,19 @@ class Migration(migrations.Migration): migrations.AddField( model_name='accesscontrolgroup', name='is_whitelist', - field=models.BooleanField(default=True, help_text='If checked, the attribute list is treated as a whitelist, otherwise it is treated as a blacklist.'), + field=models.BooleanField( + default=True, + help_text='If checked, the attribute list is treated as a whitelist, otherwise it is treated as a blacklist.', + ), ), migrations.AlterField( model_name='accesscontrolgroup', name='attributes', - field=models.ManyToManyField(blank=True, help_text="Note that you currently can't select the special attributes like object_id, hostname, servertype or intern_ip here.", related_name='access_control_groups', to='serverdb.Attribute'), + field=models.ManyToManyField( + blank=True, + help_text="Note that you currently can't select the special attributes like object_id, hostname, servertype or intern_ip here.", + related_name='access_control_groups', + to='serverdb.Attribute', + ), ), ] diff --git a/serveradmin/access_control/migrations/0003_accesscontrolgroup_description.py b/serveradmin/access_control/migrations/0003_accesscontrolgroup_description.py index ec6310bb..38d63d3a 100644 --- a/serveradmin/access_control/migrations/0003_accesscontrolgroup_description.py +++ b/serveradmin/access_control/migrations/0003_accesscontrolgroup_description.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ('access_control', '0002_whitelist_blacklist_toggle'), ] diff --git a/serveradmin/access_control/models.py b/serveradmin/access_control/models.py index b29d7eff..91c83cde 100644 --- a/serveradmin/access_control/models.py +++ b/serveradmin/access_control/models.py @@ -3,8 +3,8 @@ Copyright (c) 2019 InnoGames GmbH """ -from django.db import models from django.contrib.auth.models import User +from django.db import models from adminapi.parse import parse_query from serveradmin.apps.models import Application @@ -31,8 +31,7 @@ class AccessControlGroup(models.Model): null=False, default=True, help_text=( - "If checked, the attribute list is treated as a whitelist, " - "otherwise it is treated as a blacklist." + 'If checked, the attribute list is treated as a whitelist, ' 'otherwise it is treated as a blacklist.' ), ) attributes = models.ManyToManyField( @@ -41,7 +40,7 @@ class AccessControlGroup(models.Model): related_name='access_control_groups', help_text=( "Note that you currently can't select the special attributes " - "like object_id, hostname, servertype or intern_ip here." + 'like object_id, hostname, servertype or intern_ip here.' ), ) @@ -69,10 +68,7 @@ def get_permissible_attribute_ids(self): if self.is_whitelist is False: # Set of all attributes, excluding the blacklisted ones - return ( - {a.pk for a in Attribute.objects.all()} | - set(Attribute.specials.keys()) - ).difference( + return ({a.pk for a in Attribute.objects.all()} | set(Attribute.specials.keys())).difference( {a.pk for a in self.attributes.all()} ) diff --git a/serveradmin/access_control/tests/test_acl.py b/serveradmin/access_control/tests/test_acl.py index 3454557d..08fe07d1 100644 --- a/serveradmin/access_control/tests/test_acl.py +++ b/serveradmin/access_control/tests/test_acl.py @@ -10,42 +10,42 @@ class TestAttributeRelatedViaPermissions(TransactionTestCase): # See https://github.com/innogames/serveradmin/pull/351 def test_can_commit_related_via_attribute(self): - hv_1 = Query().new_object("hv") - hv_1["hostname"] = "hv-1" - hv_1["nic"] = "nic-1" + hv_1 = Query().new_object('hv') + hv_1['hostname'] = 'hv-1' + hv_1['nic'] = 'nic-1' hv_1.commit(app=Application.objects.filter(superuser=True).first()) - hv_2 = Query().new_object("hv") - hv_2["hostname"] = "hv-2" - hv_2["nic"] = "nic-2" + hv_2 = Query().new_object('hv') + hv_2['hostname'] = 'hv-2' + hv_2['nic'] = 'nic-2' hv_2.commit(app=Application.objects.filter(superuser=True).first()) - vm = Query().new_object("vm") - vm["hostname"] = "vm-1" - vm["hv"] = "hv-1" + vm = Query().new_object('vm') + vm['hostname'] = 'vm-1' + vm['hv'] = 'hv-1' vm.commit(app=Application.objects.filter(superuser=True).first()) - vm = Query({"hostname": "vm-1"}, ["hostname", "hv"]) - vm.update(hv="hv-2") - self.assertIsNone(vm.commit(app=Application.objects.get(name="test"))) + vm = Query({'hostname': 'vm-1'}, ['hostname', 'hv']) + vm.update(hv='hv-2') + self.assertIsNone(vm.commit(app=Application.objects.get(name='test'))) # See https://github.com/innogames/serveradmin/pull/351 def test_cannot_commit_related_via_attribute_target(self): - hv_1 = Query().new_object("hv") - hv_1["hostname"] = "hv-1" - hv_1["nic"] = "nic-1" + hv_1 = Query().new_object('hv') + hv_1['hostname'] = 'hv-1' + hv_1['nic'] = 'nic-1' hv_1.commit(app=Application.objects.filter(superuser=True).first()) - hv_2 = Query().new_object("hv") - hv_2["hostname"] = "hv-2" - hv_2["nic"] = "nic-2" + hv_2 = Query().new_object('hv') + hv_2['hostname'] = 'hv-2' + hv_2['nic'] = 'nic-2' hv_2.commit(app=Application.objects.filter(superuser=True).first()) - vm = Query().new_object("vm") - vm["hostname"] = "vm-1" - vm["hv"] = "hv-1" + vm = Query().new_object('vm') + vm['hostname'] = 'vm-1' + vm['hv'] = 'hv-1' vm.commit(app=Application.objects.filter(superuser=True).first()) - vm = Query({"hostname": "hv-1"}, ["hostname", "nic"]) - vm.update(nic="hv-2") - self.assertRaises(PermissionDenied, vm.commit, app=Application.objects.get(name="test")) + vm = Query({'hostname': 'hv-1'}, ['hostname', 'nic']) + vm.update(nic='hv-2') + self.assertRaises(PermissionDenied, vm.commit, app=Application.objects.get(name='test')) diff --git a/serveradmin/api/__init__.py b/serveradmin/api/__init__.py index 9904143c..d04eabcb 100644 --- a/serveradmin/api/__init__.py +++ b/serveradmin/api/__init__.py @@ -3,6 +3,6 @@ Copyright (c) 2019 InnoGames GmbH """ -from adminapi.api import ApiError # NOQA: F401 +from adminapi.api import ApiError # NOQA: F401 AVAILABLE_API_FUNCTIONS = {} diff --git a/serveradmin/api/api.py b/serveradmin/api/api.py index 069ba5b1..d70c0533 100644 --- a/serveradmin/api/api.py +++ b/serveradmin/api/api.py @@ -24,9 +24,9 @@ def lock(identifier, seconds=60): # Use hash sum because this has a constant length hash_sum = Lock.get_hash_sum(identifier) - obj, created = Lock.objects.get_or_create(hash_sum=hash_sum, defaults={ - 'duration': seconds, - 'until': timezone.now() + timedelta(seconds=seconds)}) + obj, created = Lock.objects.get_or_create( + hash_sum=hash_sum, defaults={'duration': seconds, 'until': timezone.now() + timedelta(seconds=seconds)} + ) if created: return True diff --git a/serveradmin/api/apps.py b/serveradmin/api/apps.py index acd98108..ee55d82b 100644 --- a/serveradmin/api/apps.py +++ b/serveradmin/api/apps.py @@ -3,7 +3,7 @@ class ApiConfig(AppConfig): name = 'serveradmin.api' - verbose_name = "Api" + verbose_name = 'Api' def ready(self): - import serveradmin.api.api # noqa + import serveradmin.api.api # noqa diff --git a/serveradmin/api/decorators.py b/serveradmin/api/decorators.py index 4f716569..7c6e4808 100644 --- a/serveradmin/api/decorators.py +++ b/serveradmin/api/decorators.py @@ -3,11 +3,11 @@ Copyright (c) 2019 InnoGames GmbH """ +import json +from base64 import b64decode from datetime import datetime, timedelta from functools import update_wrapper from logging import getLogger -from base64 import b64decode -import json from django.core.exceptions import ( ObjectDoesNotExist, @@ -16,20 +16,19 @@ ValidationError, ) from django.http import HttpResponse -from django.views.decorators.csrf import csrf_exempt +from django.utils import dateformat, timezone from django.utils.crypto import constant_time_compare -from django.utils import timezone, dateformat - +from django.views.decorators.csrf import csrf_exempt from paramiko.message import Message +from adminapi.filters import FilterValueError from adminapi.request import ( calc_message, calc_security_token, json_encode_extra, ) -from adminapi.filters import FilterValueError -from serveradmin.apps.models import Application, PublicKey from serveradmin.api import AVAILABLE_API_FUNCTIONS +from serveradmin.apps.models import Application, PublicKey logger = getLogger('serveradmin') @@ -42,9 +41,7 @@ def api_view(view): @csrf_exempt def _wrapper(request): - logger.debug('api: Start processing request: {} {}'.format( - request.scheme, request.path - )) + logger.debug('api: Start processing request: {} {}'.format(request.scheme, request.path)) now = timezone.now() body = request.body.decode('utf8') if request.body else None @@ -52,25 +49,26 @@ def _wrapper(request): signatures = request.META.get('HTTP_X_SIGNATURES') app_id = request.META.get('HTTP_X_APPLICATION') token = request.META.get('HTTP_X_SECURITYTOKEN') - then = datetime.utcfromtimestamp( - int(request.META['HTTP_X_TIMESTAMP']) - ).replace(tzinfo=timezone.utc) + then = datetime.utcfromtimestamp(int(request.META['HTTP_X_TIMESTAMP'])).replace(tzinfo=timezone.utc) body_json = json.loads(body) if body else None status_code = 200 try: - app = authenticate_app( - public_keys, signatures, app_id, token, then, now, body - ) + app = authenticate_app(public_keys, signatures, app_id, token, then, now, body) return_value = view(request, app, body_json) - logger.info('api: Call: ' + (', '.join([ - 'Method: {}'.format(view.__name__), - 'Application: {}'.format(app), - 'Time elapsed: {:.3f}s'.format( - (timezone.now() - now).total_seconds() - ), - ]))) + logger.info( + 'api: Call: ' + + ( + ', '.join( + [ + 'Method: {}'.format(view.__name__), + 'Application: {}'.format(app), + 'Time elapsed: {:.3f}s'.format((timezone.now() - now).total_seconds()), + ] + ) + ) + ) except ( FilterValueError, ValidationError, @@ -80,10 +78,7 @@ def _wrapper(request): ) as error: reason = '' - if isinstance( - error, - (FilterValueError, ValidationError, SuspiciousOperation) - ): + if isinstance(error, (FilterValueError, ValidationError, SuspiciousOperation)): status_code = 400 reason = 'Bad Request' if isinstance(error, PermissionDenied): @@ -110,9 +105,7 @@ def _wrapper(request): return update_wrapper(_wrapper, view) -def authenticate_app( - public_keys, signatures, app_id, token, then, now, body -): +def authenticate_app(public_keys, signatures, app_id, token, then, now, body): """Authenticate requests Ensure this request isn't beeing replayed by making sure the timestamp @@ -127,16 +120,12 @@ def authenticate_app( Return the app the user authenticated to """ - if ( - then + TIMESTAMP_GRACE_PERIOD < now or - then - TIMESTAMP_GRACE_PERIOD > now - ): + if then + TIMESTAMP_GRACE_PERIOD < now or then - TIMESTAMP_GRACE_PERIOD > now: raise PermissionDenied( - 'Request expired, header timestamp off by {:0.0f} seconds' - .format((now - then).total_seconds()) + 'Request expired, header timestamp off by {:0.0f} seconds'.format((now - then).total_seconds()) ) - timestamp = dateformat.format(then, u'U') + timestamp = dateformat.format(then, 'U') if public_keys and signatures: app = authenticate_app_ssh(public_keys, signatures, timestamp, body) elif app_id and token: @@ -211,10 +200,7 @@ def verify_signature(public_key, signature): Return the public key on success """ expected_message = calc_message(timestamp, body) - if not public_key.load().verify_ssh_sig( - data=expected_message.encode(), - msg=Message(b64decode(signature)) - ): + if not public_key.load().verify_ssh_sig(data=expected_message.encode(), msg=Message(b64decode(signature))): raise PermissionDenied('Invalid signature') return public_key @@ -225,9 +211,7 @@ def verify_signature(public_key, signature): verified_keys = { verify_signature(public_key, key_signatures[public_key.key_base64]) - for public_key in PublicKey.objects.filter( - key_base64__in=key_signatures.keys() - ) + for public_key in PublicKey.objects.filter(key_base64__in=key_signatures.keys()) } if not verified_keys: @@ -236,9 +220,9 @@ def verify_signature(public_key, signature): applications = {key.application for key in verified_keys} if len(applications) > 1: raise PermissionDenied( - 'Valid signatures for more than one application received: ' + - ', '.join([str(key) for key in verified_keys]) + - '. It is unclear which ACLs to enforce, giving up.' + 'Valid signatures for more than one application received: ' + + ', '.join([str(key) for key in verified_keys]) + + '. It is unclear which ACLs to enforce, giving up.' ) application = applications.pop() diff --git a/serveradmin/api/migrations/0001_api_lock.py b/serveradmin/api/migrations/0001_api_lock.py index 345eabbb..8f6204f3 100644 --- a/serveradmin/api/migrations/0001_api_lock.py +++ b/serveradmin/api/migrations/0001_api_lock.py @@ -4,11 +4,9 @@ class Migration(migrations.Migration): - initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( diff --git a/serveradmin/api/urls.py b/serveradmin/api/urls.py index 7557a88d..a3d7aadb 100644 --- a/serveradmin/api/urls.py +++ b/serveradmin/api/urls.py @@ -6,11 +6,11 @@ from django.urls import path from serveradmin.api.views import ( - health_check, - dataset_query, + api_call, dataset_commit, dataset_new_object, - api_call, + dataset_query, + health_check, ) urlpatterns = [ diff --git a/serveradmin/api/utils.py b/serveradmin/api/utils.py index 29930ca8..322a1445 100644 --- a/serveradmin/api/utils.py +++ b/serveradmin/api/utils.py @@ -16,7 +16,7 @@ def build_function_description(fn): else: extra_args = 0 - arguments = list(code.co_varnames[:code.co_argcount + extra_args]) + arguments = list(code.co_varnames[: code.co_argcount + extra_args]) if is_kwargs: arguments[-1] = '**' + arguments[-1] diff --git a/serveradmin/api/views.py b/serveradmin/api/views.py index 5c2d4565..f338a56d 100644 --- a/serveradmin/api/views.py +++ b/serveradmin/api/views.py @@ -4,20 +4,18 @@ """ from django.core.exceptions import ( - SuspiciousOperation, PermissionDenied, + SuspiciousOperation, ValidationError, ) from django.template.response import HttpResponse from adminapi.filters import BaseFilter, FilterValueError -from serveradmin.api import ApiError, AVAILABLE_API_FUNCTIONS +from serveradmin.api import AVAILABLE_API_FUNCTIONS, ApiError from serveradmin.api.decorators import api_view from serveradmin.serverdb.query_committer import commit_query from serveradmin.serverdb.query_executer import execute_query -from serveradmin.serverdb.query_materializer import ( - get_default_attribute_values -) +from serveradmin.serverdb.query_materializer import get_default_attribute_values class StringEncoder(object): @@ -134,10 +132,7 @@ def _validate_commit_changed(changes): continue if not isinstance(change, dict) or 'action' not in change: - raise SuspiciousOperation( - 'Invalid commit changed for attribute "{}"' - .format(attribute_id) - ) + raise SuspiciousOperation('Invalid commit changed for attribute "{}"'.format(attribute_id)) func = globals()['_validate_commit_changed_' + change['action']] func(change) @@ -168,9 +163,7 @@ def _validate_commit_changed_multi(change): def _validate_commit_deleted(deleted): if not isinstance(deleted, int): - raise SuspiciousOperation( - 'Invalid commit deleted "{}"'.format(deleted) - ) + raise SuspiciousOperation('Invalid commit deleted "{}"'.format(deleted)) @api_view @@ -182,9 +175,7 @@ def api_call(request, app, data): allowed_methods = app.allowed_methods.splitlines() method_name = '{0}.{1}'.format(data['group'], data['name']) if not app.superuser and method_name not in allowed_methods: - raise PermissionDenied( - 'Method {0} not allowed'.format(method_name) - ) + raise PermissionDenied('Method {0} not allowed'.format(method_name)) try: fn = AVAILABLE_API_FUNCTIONS[data['group']][data['name']] diff --git a/serveradmin/apps/admin.py b/serveradmin/apps/admin.py index c199b369..51990cd1 100644 --- a/serveradmin/apps/admin.py +++ b/serveradmin/apps/admin.py @@ -11,11 +11,11 @@ class PublicKeyInline(admin.TabularInline): inside the PublicKey form. This allows us to edit PublicKeys inside the Applications admin form. """ + model = PublicKey class ApplicationAdmin(admin.ModelAdmin): - list_display = [ 'name', 'owner', @@ -25,18 +25,24 @@ class ApplicationAdmin(admin.ModelAdmin): 'disabled', 'last_login', ] - search_fields = ['name', 'owner__username', ] - list_filter = ['superuser', 'disabled', ] - list_select_related = ['owner', ] + search_fields = [ + 'name', + 'owner__username', + ] + list_filter = [ + 'superuser', + 'disabled', + ] + list_select_related = [ + 'owner', + ] readonly_fields = [ 'auth_token', 'last_login', ] autocomplete_fields = ['owner'] - inlines = [ - PublicKeyInline - ] + inlines = [PublicKeyInline] @admin.display(description='Public Keys') def get_public_keys(self, obj): diff --git a/serveradmin/apps/management/commands/createapp.py b/serveradmin/apps/management/commands/createapp.py index 2a006044..06fcb4f7 100644 --- a/serveradmin/apps/management/commands/createapp.py +++ b/serveradmin/apps/management/commands/createapp.py @@ -4,6 +4,7 @@ Copyright (c) 2021 InnoGames GmbH """ + from os import environ from django.contrib.auth.models import User @@ -17,21 +18,23 @@ class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument('--owner', help='Username of application owner') - parser.add_argument('--superuser', action='store_true', - help='Create superuser token') - parser.add_argument('--non-interactive', action='store_true', help=( - 'Gather values from SERVERADMIN_TOKEN_OWNER, SERVERADMIN_TOKEN ' - 'and SERVERADMIN_TOKEN_SUPERUSER env variables. ' - 'Any value for SERVERADMIN_TOKEN_SUPERUSER means yes. ' - 'Empty string or absence means no.' - )) + parser.add_argument('--superuser', action='store_true', help='Create superuser token') + parser.add_argument( + '--non-interactive', + action='store_true', + help=( + 'Gather values from SERVERADMIN_TOKEN_OWNER, SERVERADMIN_TOKEN ' + 'and SERVERADMIN_TOKEN_SUPERUSER env variables. ' + 'Any value for SERVERADMIN_TOKEN_SUPERUSER means yes. ' + 'Empty string or absence means no.' + ), + ) def handle(self, *args, **options): if options['non_interactive']: owner = environ.get('SERVERADMIN_TOKEN_OWNER') token = environ.get('SERVERADMIN_TOKEN', default='').strip() - superuser = bool( - environ.get('SERVERADMIN_TOKEN_SUPERUSER', default=False)) + superuser = bool(environ.get('SERVERADMIN_TOKEN_SUPERUSER', default=False)) else: if options['owner']: owner = options['owner'] @@ -45,11 +48,9 @@ def handle(self, *args, **options): if not user.exists(): raise CommandError(f'No such user {owner} found!') - app = Application.objects.filter( - owner=user.get(), name=f'default app for {owner}') + app = Application.objects.filter(owner=user.get(), name=f'default app for {owner}') if app.exists(): - self.stdout.write(self.style.WARNING( - f'Default app for {owner} already exists - skipping.')) + self.stdout.write(self.style.WARNING(f'Default app for {owner} already exists - skipping.')) return app = Application() diff --git a/serveradmin/apps/migrations/0001_initial.py b/serveradmin/apps/migrations/0001_initial.py index 932b8a39..b1d88e7d 100644 --- a/serveradmin/apps/migrations/0001_initial.py +++ b/serveradmin/apps/migrations/0001_initial.py @@ -1,12 +1,11 @@ # Generated by Django 2.1.1 on 2018-09-02 22:28 +import django.db.models.deletion from django.conf import settings from django.db import migrations, models -import django.db.models.deletion class Migration(migrations.Migration): - initial = True dependencies = [ diff --git a/serveradmin/apps/migrations/0002_public_key_support.py b/serveradmin/apps/migrations/0002_public_key_support.py index a8a786d5..64b8cace 100644 --- a/serveradmin/apps/migrations/0002_public_key_support.py +++ b/serveradmin/apps/migrations/0002_public_key_support.py @@ -1,12 +1,11 @@ # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-04-12 14:15 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('apps', '0001_initial'), ] @@ -18,7 +17,12 @@ class Migration(migrations.Migration): ('key_algorithm', models.CharField(max_length=80)), ('key_base64', models.CharField(max_length=1024, primary_key=True, serialize=False)), ('key_comment', models.CharField(max_length=80, blank=True)), - ('application', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='public_keys', to='apps.Application')), + ( + 'application', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='public_keys', to='apps.Application' + ), + ), ], ), ] diff --git a/serveradmin/apps/migrations/0003_public_key_length.py b/serveradmin/apps/migrations/0003_public_key_length.py index cc1db7b0..89fcdaa6 100644 --- a/serveradmin/apps/migrations/0003_public_key_length.py +++ b/serveradmin/apps/migrations/0003_public_key_length.py @@ -5,7 +5,6 @@ class Migration(migrations.Migration): - dependencies = [ ('apps', '0002_public_key_support'), ] diff --git a/serveradmin/apps/migrations/0004_application_last_login.py b/serveradmin/apps/migrations/0004_application_last_login.py index 64ab77ca..513e6215 100644 --- a/serveradmin/apps/migrations/0004_application_last_login.py +++ b/serveradmin/apps/migrations/0004_application_last_login.py @@ -5,7 +5,6 @@ class Migration(migrations.Migration): - dependencies = [ ('apps', '0003_public_key_length'), ] diff --git a/serveradmin/apps/models.py b/serveradmin/apps/models.py index fc36d3b6..3b310df9 100644 --- a/serveradmin/apps/models.py +++ b/serveradmin/apps/models.py @@ -1,14 +1,14 @@ -from base64 import b64encode, b64decode +from base64 import b64decode, b64encode from hashlib import sha256 -from django.db import models -from django.db.models.signals import pre_save, post_save -from django.dispatch import receiver from django.contrib.auth.models import User from django.core.exceptions import ValidationError - +from django.db import models +from django.db.models.signals import post_save, pre_save +from django.dispatch import receiver +from paramiko import ECDSAKey, RSAKey from paramiko.ssh_exception import SSHException -from paramiko import RSAKey, ECDSAKey + try: from paramiko import Ed25519Key except ImportError: @@ -66,9 +66,7 @@ def set_disabled(sender, instance, **kwargs): class PublicKey(models.Model): - application = models.ForeignKey( - Application, related_name="public_keys", on_delete=models.CASCADE - ) + application = models.ForeignKey(Application, related_name='public_keys', on_delete=models.CASCADE) key_algorithm = models.CharField(max_length=80) key_base64 = models.CharField(primary_key=True, max_length=2048) key_comment = models.CharField(max_length=80, blank=True) @@ -135,9 +133,7 @@ def create(cls, application, public_key): application=application, key_algorithm=public_key_parts[0], key_base64=public_key_parts[1], - key_comment=( - public_key_parts[2] if len(public_key_parts) == 3 else '' - ), + key_comment=(public_key_parts[2] if len(public_key_parts) == 3 else ''), ) return instance diff --git a/serveradmin/common/management/commands/createdefaultuser.py b/serveradmin/common/management/commands/createdefaultuser.py index d0f4c8b3..1295b3fc 100644 --- a/serveradmin/common/management/commands/createdefaultuser.py +++ b/serveradmin/common/management/commands/createdefaultuser.py @@ -6,6 +6,7 @@ Copyright (c) 2021 InnoGames GmbH """ + from os import environ from django.contrib.auth.models import User diff --git a/serveradmin/common/templatetags/__init__.py b/serveradmin/common/templatetags/__init__.py index 95eda910..4277f602 100644 --- a/serveradmin/common/templatetags/__init__.py +++ b/serveradmin/common/templatetags/__init__.py @@ -2,4 +2,3 @@ Copyright (c) 2019 InnoGames GmbH """ - diff --git a/serveradmin/common/templatetags/common.py b/serveradmin/common/templatetags/common.py index ead91e01..b8f0f15e 100644 --- a/serveradmin/common/templatetags/common.py +++ b/serveradmin/common/templatetags/common.py @@ -55,7 +55,7 @@ def group(items, number_of_groups): step = 1 for counter in range(0, len(items), step): - groups.extend([items[counter:counter + step]]) + groups.extend([items[counter : counter + step]]) return groups diff --git a/serveradmin/common/utils.py b/serveradmin/common/utils.py index 49effab1..2e7c86e1 100644 --- a/serveradmin/common/utils.py +++ b/serveradmin/common/utils.py @@ -2,12 +2,12 @@ Copyright (c) 2020 InnoGames GmbH """ + import functools +import logging import os import re import time -import logging - from base64 import b64encode _hostname_re = re.compile( @@ -45,4 +45,5 @@ def wrapper_profile(*args, **kwargs): logging.getLogger('profile').info(msg) return value + return wrapper_profile diff --git a/serveradmin/dataset.py b/serveradmin/dataset.py index 6fb35fad..c2c81ab5 100644 --- a/serveradmin/dataset.py +++ b/serveradmin/dataset.py @@ -3,16 +3,14 @@ Copyright (c) 2019 InnoGames GmbH """ -from adminapi.dataset import BaseQuery, DatasetObject as ApiDatasetObject +from adminapi.dataset import BaseQuery +from adminapi.dataset import DatasetObject as ApiDatasetObject from serveradmin.serverdb.query_committer import commit_query from serveradmin.serverdb.query_executer import execute_query -from serveradmin.serverdb.query_materializer import ( - get_default_attribute_values -) +from serveradmin.serverdb.query_materializer import get_default_attribute_values class Query(BaseQuery): - def _fetch_new_object(self, servertype): return DatasetObject(get_default_attribute_values(servertype)) diff --git a/serveradmin/graphite/management/commands/cache_graphite.py b/serveradmin/graphite/management/commands/cache_graphite.py index 9dc65659..45f0ce1a 100644 --- a/serveradmin/graphite/management/commands/cache_graphite.py +++ b/serveradmin/graphite/management/commands/cache_graphite.py @@ -41,59 +41,59 @@ class Command(BaseCommand): def add_arguments(self, parser: CommandParser) -> None: parser.add_argument( - "--collections", - nargs="*", + '--collections', + nargs='*', type=str, - help="Generate/update only these collections.", + help='Generate/update only these collections.', ) parser.add_argument( - "--query", + '--query', type=str, - help="Generate/update only objects matching this Serveradmin query.", + help='Generate/update only objects matching this Serveradmin query.', ) parser.add_argument( - "--threads", + '--threads', type=int, default=5, - help="Generate n sprites/numerics concurrently.", + help='Generate n sprites/numerics concurrently.', ) def handle(self, *args, **options): """The entry point of the command""" - if options["threads"] < 1: - self.stderr.write(self.style.ERROR(f"--threads must be greater 0!")) + if options['threads'] < 1: + self.stderr.write(self.style.ERROR('--threads must be greater 0!')) exit(1) start = time.time() sprite_params = settings.GRAPHITE_SPRITE_PARAMS - sprite_dir = settings.MEDIA_ROOT + "/graph_sprite" + sprite_dir = settings.MEDIA_ROOT + '/graph_sprite' if not isdir(sprite_dir): mkdir(sprite_dir) collections = Collection.objects.filter(overview=True) - if options["collections"]: - collections = collections.filter(name__in=options["collections"]) + if options['collections']: + collections = collections.filter(name__in=options['collections']) for collection in collections: - self.stdout.write(f"[{now()}] Starting collection {collection}") + self.stdout.write(f'[{now()}] Starting collection {collection}') - collection_dir = sprite_dir + "/" + collection.name + collection_dir = sprite_dir + '/' + collection.name if not isdir(collection_dir): mkdir(collection_dir) query_filter = { GRAPHITE_ATTRIBUTE_ID: collection.name, - "state": filters.Not("retired"), + 'state': filters.Not('retired'), } - if options["query"]: - query_filter.update(**parse_query(options["query"])) + if options['query']: + query_filter.update(**parse_query(options['query'])) futures = [] - with ThreadPoolExecutor(options["threads"]) as executor: - for server in Query(query_filter, ["hostname"]): + with ThreadPoolExecutor(options['threads']) as executor: + for server in Query(query_filter, ['hostname']): futures.append( executor.submit( self.generate_sprite, @@ -103,16 +103,12 @@ def handle(self, *args, **options): sprite_params, ) ) - futures.append( - executor.submit(self.cache_numerics, collection, server) - ) + futures.append(executor.submit(self.cache_numerics, collection, server)) - self.stdout.write(f"[{now()}] Finished collection {collection}") + self.stdout.write(f'[{now()}] Finished collection {collection}') end = time.time() - self.stdout.write( - self.style.SUCCESS(f"[{now()}] Total time: {end - start:.2f} seconds.") - ) + self.stdout.write(self.style.SUCCESS(f'[{now()}] Total time: {end - start:.2f} seconds.')) def generate_sprite(self, collection_dir, server, collection, sprite_params): """Generate sprites for the given server using the given collection""" @@ -125,7 +121,7 @@ def generate_sprite(self, collection_dir, server, collection, sprite_params): sprite_width = settings.GRAPHITE_SPRITE_WIDTH sprite_height = settings.GRAPHITE_SPRITE_HEIGHT total_width = len(graphs) * sprite_width - sprite_img = Image.new("RGB", (total_width, sprite_height), (255,) * 3) + sprite_img = Image.new('RGB', (total_width, sprite_height), (255,) * 3) for graph, offset in zip(graphs, range(0, total_width, sprite_width)): response = self.get_from_graphite(graph) @@ -133,7 +129,7 @@ def generate_sprite(self, collection_dir, server, collection, sprite_params): box = (offset, 0, offset + sprite_width, sprite_height) sprite_img.paste(Image.open(BytesIO(response)), box) - sprite_img.save(collection_dir + "/" + server["hostname"] + ".png") + sprite_img.save(collection_dir + '/' + server['hostname'] + '.png') self.stdout.write(f"[{now()}] Generated sprite for {server['hostname']}") @@ -146,22 +142,18 @@ def cache_numerics(self, collection, server): if not response: continue - response_json = json.loads(response.decode("utf8")) + response_json = json.loads(response.decode('utf8')) try: - value = response_json[0]["datapoints"][0][0] + value = response_json[0]['datapoints'][0][0] except IndexError: self.stdout.write( - self.style.NOTICE( - f"[{now()}] {server['hostname']}: Can't parse response {response} for {params}." - ) + self.style.NOTICE(f"[{now()}] {server['hostname']}: Can't parse response {response} for {params}.") ) continue if value is None: self.stdout.write( - self.style.NOTICE( - f"[{now()}] {server['hostname']}: None value for {params} received." - ) + self.style.NOTICE(f"[{now()}] {server['hostname']}: None value for {params} received.") ) continue @@ -173,21 +165,15 @@ def cache_numerics(self, collection, server): try: # Lock server for changes to avoid non-repeatable reads in the # query_committer. - locked_server = Server.objects.select_for_update().get( - server_id=server.object_id - ) + locked_server = Server.objects.select_for_update().get(server_id=server.object_id) except Server.DoesNotExist: - self.stdout.write( - self.style.NOTICE( - f"[{now()}] {server['hostname']} has been deleted." - ) - ) + self.stdout.write(self.style.NOTICE(f"[{now()}] {server['hostname']} has been deleted.")) continue locked_server.servernumberattribute_set.update_or_create( server_id=locked_server.server_id, attribute=numeric.attribute, - defaults={"value": Decimal(value)}, + defaults={'value': Decimal(value)}, ) self.stdout.write(f"[{now()}] Updated numerics for {server['hostname']}") @@ -202,21 +188,15 @@ def get_from_graphite(self, params): settings.GRAPHITE_PASSWORD, ) auth_handler = HTTPBasicAuthHandler(password_mgr) - url = "{0}/render?{1}".format(settings.GRAPHITE_URL, params) + url = '{0}/render?{1}'.format(settings.GRAPHITE_URL, params) start = time.time() try: with build_opener(auth_handler).open(url) as response: return response.read() except HTTPError as error: - self.stdout.write( - self.style.NOTICE(f"[{now()}] Graphite returned {error} for {url}") - ) + self.stdout.write(self.style.NOTICE(f'[{now()}] Graphite returned {error} for {url}')) finally: end = time.time() if end - start > 10: - self.stdout.write( - self.style.WARNING( - f"[{now()}] Graphite request {url} took {end - start} seconds" - ) - ) + self.stdout.write(self.style.WARNING(f'[{now()}] Graphite request {url} took {end - start} seconds')) diff --git a/serveradmin/graphite/migrations/0001_initial.py b/serveradmin/graphite/migrations/0001_initial.py index 7a0cab80..0ba569c7 100644 --- a/serveradmin/graphite/migrations/0001_initial.py +++ b/serveradmin/graphite/migrations/0001_initial.py @@ -1,12 +1,11 @@ # Generated by Django 2.1.1 on 2018-09-02 22:27 import django.core.validators -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): - initial = True dependencies = [ @@ -18,10 +17,28 @@ class Migration(migrations.Migration): name='Collection', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255, validators=[django.core.validators.RegexValidator('\\A[a-z][a-z0-9_]+\\Z', 'Invalid id')])), - ('params', models.TextField(blank=True, help_text='\n Part of the URL after "?" to GET the graph or the value from\n the Graphite. It will be concatenated with the params for\n the template and the variation. Make sure it doesn\'t include\n any character that doesn\'t allowed on URL\'s. Also do not include "?"\n and do not put "&" at the end.\n\n The params can include variables inside curly brackets like\n "{hostname}".\n Variables can be any string attribute except multiple ones related to\n the servers. See Python String Formatting documentation [1] for other\n formatting options. The dots inside the values are replaced with\n underscores in advance. If you need to include a brace character in\n the parameters, it can be escaped by doubling: \'{{ and }}\'.\n\n Example params:\n\n width=500&height=500\n\n [1] https://docs.python.org/2/library/string.html#formatstrings\n ')), + ( + 'name', + models.CharField( + max_length=255, + validators=[django.core.validators.RegexValidator('\\A[a-z][a-z0-9_]+\\Z', 'Invalid id')], + ), + ), + ( + 'params', + models.TextField( + blank=True, + help_text='\n Part of the URL after "?" to GET the graph or the value from\n the Graphite. It will be concatenated with the params for\n the template and the variation. Make sure it doesn\'t include\n any character that doesn\'t allowed on URL\'s. Also do not include "?"\n and do not put "&" at the end.\n\n The params can include variables inside curly brackets like\n "{hostname}".\n Variables can be any string attribute except multiple ones related to\n the servers. See Python String Formatting documentation [1] for other\n formatting options. The dots inside the values are replaced with\n underscores in advance. If you need to include a brace character in\n the parameters, it can be escaped by doubling: \'{{ and }}\'.\n\n Example params:\n\n width=500&height=500\n\n [1] https://docs.python.org/2/library/string.html#formatstrings\n ', + ), + ), ('sort_order', models.FloatField(default=0)), - ('overview', models.BooleanField(default=False, help_text="\n Marks the collection to be shown on the overview page. For\n the overview page, sprites will be generated and cached on\n the server in advance to improve the loading time. A suffix\n will be appended to the generated URLs to get the overview\n images, as defined by the GRAPHITE_SPRITE_PARAMS setting.\n ")), + ( + 'overview', + models.BooleanField( + default=False, + help_text='\n Marks the collection to be shown on the overview page. For\n the overview page, sprites will be generated and cached on\n the server in advance to improve the loading time. A suffix\n will be appended to the generated URLs to get the overview\n images, as defined by the GRAPHITE_SPRITE_PARAMS setting.\n ', + ), + ), ('created_at', models.DateTimeField(auto_now_add=True)), ], options={ @@ -35,8 +52,22 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('params', models.TextField(blank=True, help_text='Same as the params of the collections')), ('sort_order', models.FloatField(default=0)), - ('attribute', models.ForeignKey(limit_choices_to={'multi': False, 'readonly': True, 'type': 'number'}, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Attribute')), - ('collection', models.ForeignKey(limit_choices_to={'overview': True}, on_delete=django.db.models.deletion.CASCADE, to='graphite.Collection')), + ( + 'attribute', + models.ForeignKey( + limit_choices_to={'multi': False, 'readonly': True, 'type': 'number'}, + on_delete=django.db.models.deletion.CASCADE, + to='serverdb.Attribute', + ), + ), + ( + 'collection', + models.ForeignKey( + limit_choices_to={'overview': True}, + on_delete=django.db.models.deletion.CASCADE, + to='graphite.Collection', + ), + ), ], options={ 'db_table': 'graphite_numeric', @@ -48,8 +79,22 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('sort_order', models.FloatField(default=0)), - ('attribute', models.ForeignKey(limit_choices_to=models.Q(type__in=['relation', 'reverse', 'supernet', 'domain']), on_delete=django.db.models.deletion.CASCADE, to='serverdb.Attribute')), - ('collection', models.ForeignKey(limit_choices_to={'overview': True}, on_delete=django.db.models.deletion.CASCADE, to='graphite.Collection')), + ( + 'attribute', + models.ForeignKey( + limit_choices_to=models.Q(type__in=['relation', 'reverse', 'supernet', 'domain']), + on_delete=django.db.models.deletion.CASCADE, + to='serverdb.Attribute', + ), + ), + ( + 'collection', + models.ForeignKey( + limit_choices_to={'overview': True}, + on_delete=django.db.models.deletion.CASCADE, + to='graphite.Collection', + ), + ), ], options={ 'db_table': 'graphite_relation', @@ -60,12 +105,33 @@ class Migration(migrations.Migration): name='Template', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255, validators=[django.core.validators.RegexValidator('\\A[a-z][a-z0-9_]+\\Z', 'Invalid id')])), - ('params', models.TextField(blank=True, help_text='\n Same as the params of the collections.\n ')), + ( + 'name', + models.CharField( + max_length=255, + validators=[django.core.validators.RegexValidator('\\A[a-z][a-z0-9_]+\\Z', 'Invalid id')], + ), + ), + ( + 'params', + models.TextField( + blank=True, help_text='\n Same as the params of the collections.\n ' + ), + ), ('sort_order', models.FloatField(default=0)), ('description', models.TextField(blank=True)), - ('foreach_path', models.CharField(blank=True, help_text='\n Generates multiple graphs from the same template. Variables can be\n used like "params". It will be a variable for the "params" that can\n be used as {foreach_id}. Example value:\n\n servers.{hostname}.system.cpu.*\n ', max_length=256)), - ('collection', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='graphite.Collection')), + ( + 'foreach_path', + models.CharField( + blank=True, + help_text='\n Generates multiple graphs from the same template. Variables can be\n used like "params". It will be a variable for the "params" that can\n be used as {foreach_id}. Example value:\n\n servers.{hostname}.system.cpu.*\n ', + max_length=256, + ), + ), + ( + 'collection', + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='graphite.Collection'), + ), ], options={ 'db_table': 'graphite_template', @@ -76,11 +142,31 @@ class Migration(migrations.Migration): name='Variation', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255, validators=[django.core.validators.RegexValidator('\\A[a-z][a-z0-9_]+\\Z', 'Invalid id')])), - ('params', models.TextField(blank=True, help_text='\n Same as the params of the collections.\n ')), + ( + 'name', + models.CharField( + max_length=255, + validators=[django.core.validators.RegexValidator('\\A[a-z][a-z0-9_]+\\Z', 'Invalid id')], + ), + ), + ( + 'params', + models.TextField( + blank=True, help_text='\n Same as the params of the collections.\n ' + ), + ), ('sort_order', models.FloatField(default=0)), - ('summarize_interval', models.CharField(help_text='\n Interval string that makes sense to use on the summarize() function on\n the Graphite for this variation. It can be used in the params as\n {summarize_interval}.\n ', max_length=255)), - ('collection', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='graphite.Collection')), + ( + 'summarize_interval', + models.CharField( + help_text='\n Interval string that makes sense to use on the summarize() function on\n the Graphite for this variation. It can be used in the params as\n {summarize_interval}.\n ', + max_length=255, + ), + ), + ( + 'collection', + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='graphite.Collection'), + ), ], options={ 'db_table': 'graphite_variation', diff --git a/serveradmin/graphite/migrations/0002_template_and_variation_name_validation.py b/serveradmin/graphite/migrations/0002_template_and_variation_name_validation.py index 78d03560..b9e4f31c 100644 --- a/serveradmin/graphite/migrations/0002_template_and_variation_name_validation.py +++ b/serveradmin/graphite/migrations/0002_template_and_variation_name_validation.py @@ -5,7 +5,6 @@ class Migration(migrations.Migration): - dependencies = [ ('graphite', '0001_initial'), ] diff --git a/serveradmin/graphite/models.py b/serveradmin/graphite/models.py index ff67667c..7ed93023 100644 --- a/serveradmin/graphite/models.py +++ b/serveradmin/graphite/models.py @@ -5,18 +5,13 @@ import json from string import Formatter -from urllib.request import ( - HTTPBasicAuthHandler, - HTTPPasswordMgrWithDefaultRealm, - build_opener -) +from urllib.request import HTTPBasicAuthHandler, HTTPPasswordMgrWithDefaultRealm, build_opener -from django.db import models from django.conf import settings +from django.db import models from adminapi.dataset import MultiAttr from serveradmin.graphite.validators import validate_unique_uri_parameters - from serveradmin.serverdb.models import LOOKUP_ID_VALIDATORS, Attribute GRAPHITE_ATTRIBUTE_ID = 'graphite_graphs' @@ -24,8 +19,11 @@ class Collection(models.Model): """Collection of graphs and values to be shown for the servers""" + name = models.CharField(max_length=255, validators=LOOKUP_ID_VALIDATORS) - params = models.TextField(blank=True, help_text=""" + params = models.TextField( + blank=True, + help_text=""" Part of the URL after "?" to GET the graph or the value from the Graphite. It will be concatenated with the params for the template and the variation. Make sure it doesn't include @@ -45,15 +43,20 @@ class Collection(models.Model): width=500&height=500 [1] https://docs.python.org/2/library/string.html#formatstrings - """, validators=[validate_unique_uri_parameters]) + """, + validators=[validate_unique_uri_parameters], + ) sort_order = models.FloatField(default=0) - overview = models.BooleanField(default=False, help_text=""" + overview = models.BooleanField( + default=False, + help_text=""" Marks the collection to be shown on the overview page. For the overview page, sprites will be generated and cached on the server in advance to improve the loading time. A suffix will be appended to the generated URLs to get the overview images, as defined by the GRAPHITE_SPRITE_PARAMS setting. - """) + """, + ) created_at = models.DateTimeField(auto_now_add=True) class Meta: @@ -63,8 +66,8 @@ class Meta: def __init__(self, *args, **kwargs): models.Model.__init__(self, *args, **kwargs) - self._templates = None # To cache graph templates - self._variations = None # To cache graph variations + self._templates = None # To cache graph templates + self._variations = None # To cache graph variations def __str__(self): name = self.name @@ -87,9 +90,11 @@ def graph_column(self, server, custom_params=''): column = [] for template in self.template_set.all(): for foreach_metric in template.foreach(server): - formatter = AttributeFormatter({ - 'foreach_id': foreach_metric['id'], - }) + formatter = AttributeFormatter( + { + 'foreach_id': foreach_metric['id'], + } + ) params = self.merged_params((template.params, custom_params)) name = template.name @@ -125,15 +130,14 @@ def graph_table(self, server, custom_params=''): for foreach_metric in template.foreach(server): column = [] for variation in self.variation_set.all(): - formatter = AttributeFormatter({ - 'foreach_id': foreach_metric['id'], - 'summarize_interval': variation.summarize_interval, - }) - params = self.merged_params((variation.params, - template.params, - custom_params)) - column.append((variation.name, - formatter.vformat(params, (), server))) + formatter = AttributeFormatter( + { + 'foreach_id': foreach_metric['id'], + 'summarize_interval': variation.summarize_interval, + } + ) + params = self.merged_params((variation.params, template.params, custom_params)) + column.append((variation.name, formatter.vformat(params, (), server))) name = template.name if foreach_metric['text']: @@ -158,22 +162,24 @@ def merged_params(self, other_params): class Numeric(models.Model): """Templates in the collections""" + collection = models.ForeignKey( - Collection, on_delete=models.CASCADE, + Collection, + on_delete=models.CASCADE, limit_choices_to={'overview': True}, ) params = models.TextField( - blank=True, help_text="Same as the params of the collections", - validators=[validate_unique_uri_parameters] + blank=True, help_text='Same as the params of the collections', validators=[validate_unique_uri_parameters] ) sort_order = models.FloatField(default=0) attribute = models.ForeignKey( - Attribute, on_delete=models.CASCADE, + Attribute, + on_delete=models.CASCADE, limit_choices_to={ 'multi': False, 'type': 'number', 'readonly': True, - } + }, ) class Meta: @@ -187,16 +193,13 @@ def __str__(self): class Relation(models.Model): """Templates in the collections""" - collection = models.ForeignKey( - Collection, on_delete=models.CASCADE, - limit_choices_to={'overview': True} - ) + + collection = models.ForeignKey(Collection, on_delete=models.CASCADE, limit_choices_to={'overview': True}) sort_order = models.FloatField(default=0) attribute = models.ForeignKey( - Attribute, on_delete=models.CASCADE, - limit_choices_to=models.Q( - type__in=['relation', 'reverse', 'supernet', 'domain'] - ) + Attribute, + on_delete=models.CASCADE, + limit_choices_to=models.Q(type__in=['relation', 'reverse', 'supernet', 'domain']), ) class Meta: @@ -210,20 +213,29 @@ def __str__(self): class Template(models.Model): """Templates in the collections""" + collection = models.ForeignKey(Collection, on_delete=models.CASCADE) name = models.CharField(max_length=255) - params = models.TextField(blank=True, help_text=""" + params = models.TextField( + blank=True, + help_text=""" Same as the params of the collections. - """, validators=[validate_unique_uri_parameters]) + """, + validators=[validate_unique_uri_parameters], + ) sort_order = models.FloatField(default=0) description = models.TextField(blank=True) - foreach_path = models.CharField(max_length=256, blank=True, help_text=""" + foreach_path = models.CharField( + max_length=256, + blank=True, + help_text=""" Generates multiple graphs from the same template. Variables can be used like "params". It will be a variable for the "params" that can be used as {foreach_id}. Example value: servers.{hostname}.system.cpu.* - """) + """, + ) class Meta: db_table = 'graphite_template' @@ -242,9 +254,7 @@ def foreach(self, server): if self.foreach_path: formatter = AttributeFormatter() - params = formatter.vformat( - 'query=' + self.foreach_path, (), server - ) + params = formatter.vformat('query=' + self.foreach_path, (), server) password_mgr = HTTPPasswordMgrWithDefaultRealm() password_mgr.add_password( @@ -254,37 +264,43 @@ def foreach(self, server): settings.GRAPHITE_PASSWORD, ) auth_handler = HTTPBasicAuthHandler(password_mgr) - url = '{0}/metrics/find?{1}'.format( - settings.GRAPHITE_URL, params - ) + url = '{0}/metrics/find?{1}'.format(settings.GRAPHITE_URL, params) with build_opener(auth_handler).open(url) as response: return json.loads(response.read().decode()) - return [{ - 'id': '', - 'leaf': 0, - 'context': {}, - 'text': '', - 'expandable': 0, - 'allowChildren': 0, - }] + return [ + { + 'id': '', + 'leaf': 0, + 'context': {}, + 'text': '', + 'expandable': 0, + 'allowChildren': 0, + } + ] class Variation(models.Model): - """Variation to render the templates - """ + """Variation to render the templates""" collection = models.ForeignKey(Collection, on_delete=models.CASCADE) name = models.CharField(max_length=255) - params = models.TextField(blank=True, help_text=""" + params = models.TextField( + blank=True, + help_text=""" Same as the params of the collections. - """, validators=[validate_unique_uri_parameters]) + """, + validators=[validate_unique_uri_parameters], + ) sort_order = models.FloatField(default=0) - summarize_interval = models.CharField(max_length=255, help_text=""" + summarize_interval = models.CharField( + max_length=255, + help_text=""" Interval string that makes sense to use on the summarize() function on the Graphite for this variation. It can be used in the params as {summarize_interval}. - """) + """, + ) class Meta: db_table = 'graphite_variation' @@ -349,5 +365,5 @@ def format_attribute_value(value): # XXX This function is a terrible temporary hack that needs to go away for suffix in ['.ig.local', '.innogames.net']: if value.endswith(suffix): - value = value[:-len(suffix)] + value = value[: -len(suffix)] return value.replace('.', '_') diff --git a/serveradmin/graphite/validators.py b/serveradmin/graphite/validators.py index f196e2bb..ace8d66c 100644 --- a/serveradmin/graphite/validators.py +++ b/serveradmin/graphite/validators.py @@ -17,9 +17,7 @@ def validate_unique_uri_parameters(query_string: str): for key, occurences in counter.most_common(): if occurences > 1: - errors.append(ValidationError( - _('Parameter "%(key)s" must only appear once!'), - params={'key': key})) + errors.append(ValidationError(_('Parameter "%(key)s" must only appear once!'), params={'key': key})) if errors: raise ValidationError(*errors) diff --git a/serveradmin/graphite/views.py b/serveradmin/graphite/views.py index 385d6d68..fb6f9951 100644 --- a/serveradmin/graphite/views.py +++ b/serveradmin/graphite/views.py @@ -2,6 +2,7 @@ Copyright (c) 2019 InnoGames GmbH """ + from urllib.parse import urlencode from urllib.request import ( HTTPBasicAuthHandler, @@ -35,30 +36,29 @@ def graph_table(request): :return: """ - hostnames = [h.strip() for h in request.GET.getlist("hostname", []) if h] - object_ids = [o.strip() for o in request.GET.getlist("object_id", []) if o] + hostnames = [h.strip() for h in request.GET.getlist('hostname', []) if h] + object_ids = [o.strip() for o in request.GET.getlist('object_id', []) if o] if len(hostnames) == 0 and len(object_ids) == 0: - return HttpResponseBadRequest("No hostname or object_id provided") + return HttpResponseBadRequest('No hostname or object_id provided') # For convenience, we will cache the servers in a dictionary. - servers = {s["hostname"]: s for s in Query({"hostname": Any(*hostnames)}, None)} - servers.update( - {s["hostname"]: s for s in Query({"object_id": Any(*object_ids)}, None)} - ) + servers = {s['hostname']: s for s in Query({'hostname': Any(*hostnames)}, None)} + servers.update({s['hostname']: s for s in Query({'object_id': Any(*object_ids)}, None)}) if len(servers) != len(hostnames) + len(object_ids): messages.error( request, - "One or more objects with hostname: {} or object_ids: {} does not " - "exist".format(",".join(hostnames), ",".join(object_ids)), + 'One or more objects with hostname: {} or object_ids: {} does not ' 'exist'.format( + ','.join(hostnames), ','.join(object_ids) + ), ) # Find the collections which are related with all the hostnames. # If there are two collections with same match, use only the one which # is not an overview. collections = [] - for collection in Collection.objects.order_by("overview", "sort_order"): + for collection in Collection.objects.order_by('overview', 'sort_order'): if any(collection.name == c.name for c in collections): continue for hostname in servers.keys(): @@ -75,22 +75,18 @@ def graph_table(request): descriptions = [] for collection in collections: for template in collection.template_set.all(): - descriptions += [(template.name, template.description)] * len( - servers.keys() - ) + descriptions += [(template.name, template.description)] * len(servers.keys()) # Prepare the graph tables for all hosts graph_tables = [] for hostname in servers.keys(): host_graph_table = [] - if request.GET.get("action") == "Submit" and ( - request.GET.get("from") or request.GET.get("until") - ): + if request.GET.get('action') == 'Submit' and (request.GET.get('from') or request.GET.get('until')): custom_params = request.GET.urlencode() for collection in collections: column = collection.graph_column(servers[hostname], custom_params) - host_graph_table += [(k, [("Custom", v)]) for k, v in column] + host_graph_table += [(k, [('Custom', v)]) for k, v in column] else: for collection in collections: host_graph_table += collection.graph_table(servers[hostname]) @@ -100,9 +96,7 @@ def graph_table(request): if len(servers) > 1: # Add hostname to the titles for order, hostname in enumerate(servers.keys()): - graph_tables[order] = [ - (k + " on " + hostname, v) for k, v in graph_tables[order] - ] + graph_tables[order] = [(k + ' on ' + hostname, v) for k, v in graph_tables[order]] # Combine them all_graph_tables = [] @@ -113,29 +107,25 @@ def graph_table(request): # called SERVER that receives a coded hostname as alternative to the # builtin graphs. grafana_links = [] - if hasattr(settings, "GRAFANA_DASHBOARD"): + if hasattr(settings, 'GRAFANA_DASHBOARD'): def _get_grafana_link(hostname): - return ( - settings.GRAFANA_DASHBOARD - + "?" - + urlencode({"var-SERVER": format_attribute_value(hostname)}) - ) + return settings.GRAFANA_DASHBOARD + '?' + urlencode({'var-SERVER': format_attribute_value(hostname)}) for hostname in servers.keys(): grafana_links.append((hostname, _get_grafana_link(hostname))) return TemplateResponse( request, - "graphite/graph_table.html", + 'graphite/graph_table.html', { - "hostnames": servers.keys(), - "descriptions": descriptions, - "graph_table": all_graph_tables, - "grafana_links": grafana_links, - "link": request.get_full_path(), - "from": request.GET.get("from", ""), - "until": request.GET.get("until", ""), + 'hostnames': servers.keys(), + 'descriptions': descriptions, + 'graph_table': all_graph_tables, + 'grafana_links': grafana_links, + 'link': request.get_full_path(), + 'from': request.GET.get('from', ''), + 'until': request.GET.get('until', ''), }, ) @@ -157,7 +147,7 @@ def graph(request): settings.GRAPHITE_PASSWORD, ) auth_handler = HTTPBasicAuthHandler(password_mgr) - url = "{0}/render?{1}".format(settings.GRAPHITE_URL, request.GET.urlencode()) + url = '{0}/render?{1}'.format(settings.GRAPHITE_URL, request.GET.urlencode()) # If the Graphite server fails, we would return proper server error # to the user instead of failing. This is not really a matter for @@ -167,6 +157,6 @@ def graph(request): # empty result with 200 instead of proper error codes. try: with build_opener(auth_handler).open(url) as response: - return HttpResponse(response.read(), content_type="image/png") + return HttpResponse(response.read(), content_type='image/png') except IOError as error: return HttpResponseServerError(str(error)) diff --git a/serveradmin/resources/__init__.py b/serveradmin/resources/__init__.py index 305f4fac..6a38df6d 100644 --- a/serveradmin/resources/__init__.py +++ b/serveradmin/resources/__init__.py @@ -2,4 +2,3 @@ Copyright (c) 2019 InnoGames GmbH """ - diff --git a/serveradmin/resources/management/commands/clear_migration_log.py b/serveradmin/resources/management/commands/clear_migration_log.py index 76dd1612..9b80d705 100644 --- a/serveradmin/resources/management/commands/clear_migration_log.py +++ b/serveradmin/resources/management/commands/clear_migration_log.py @@ -7,11 +7,13 @@ Copyright (c) 2020 InnoGames GmbH """ -from datetime import datetime, timedelta, timezone + +from datetime import datetime, timezone + from django.core.management.base import BaseCommand from adminapi.dataset import Query -from adminapi.filters import Not, Empty +from adminapi.filters import Empty, Not class Command(BaseCommand): @@ -24,26 +26,21 @@ def handle(self, *args, **options): and delete all entries which are from the previous day. """ - all_hypervisors = Query({'igvm_migration_log': Not(Empty()), - 'servertype': 'hypervisor'}, - ['igvm_migration_log', 'hostname']) + all_hypervisors = Query( + {'igvm_migration_log': Not(Empty()), 'servertype': 'hypervisor'}, ['igvm_migration_log', 'hostname'] + ) now = datetime.now(tz=timezone.utc) for hypervisor in all_hypervisors: - for entry in hypervisor['igvm_migration_log']: timestamp = entry.split()[0] - dt_object_sa = datetime.fromtimestamp( - int(timestamp), - tz=timezone.utc) + dt_object_sa = datetime.fromtimestamp(int(timestamp), tz=timezone.utc) if dt_object_sa.date() == now.date(): continue hypervisor['igvm_migration_log'].discard(entry) hypervisor.commit() - self.stdout.write(self.style.SUCCESS( - 'Delete old entries from {} '.format( - hypervisor['hostname']))) + self.stdout.write(self.style.SUCCESS('Delete old entries from {} '.format(hypervisor['hostname']))) diff --git a/serveradmin/resources/urls.py b/serveradmin/resources/urls.py index 1ef1bc61..9c255df1 100644 --- a/serveradmin/resources/urls.py +++ b/serveradmin/resources/urls.py @@ -5,7 +5,7 @@ from django.urls import path -from serveradmin.resources.views import index, graph_popup +from serveradmin.resources.views import graph_popup, index urlpatterns = [ path('', index, name='resources_index'), diff --git a/serveradmin/resources/views.py b/serveradmin/resources/views.py index 47bd2be7..53793291 100644 --- a/serveradmin/resources/views.py +++ b/serveradmin/resources/views.py @@ -8,7 +8,7 @@ from django.conf import settings from django.contrib.auth.decorators import login_required from django.core.exceptions import SuspiciousOperation -from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.http import HttpResponseBadRequest from django.template.response import TemplateResponse from django.urls import reverse @@ -22,7 +22,7 @@ from serveradmin.graphite.views import graph -@login_required # NOQA: C901 +@login_required # NOQA: C901 @ensure_csrf_cookie def index(request): """The hardware resources page""" @@ -40,7 +40,7 @@ def index(request): current_collection = collection break else: - return HttpResponseBadRequest(f"Collection {current_collection_id} does not exist!") + return HttpResponseBadRequest(f'Collection {current_collection_id} does not exist!') # Save latest choice for collection request.session['current_collection'] = current_collection.id @@ -75,8 +75,7 @@ def index(request): variations = list(current_collection.variation_set.all()) columns = [] - columns_selected = request.GET.getlist( - 'columns', request.session.get('resources_columns', [])) + columns_selected = request.GET.getlist('columns', request.session.get('resources_columns', [])) request.session['resources_columns'] = columns_selected attribute_ids = ['hostname', 'servertype'] graph_index = 0 @@ -84,27 +83,33 @@ def index(request): for template in current_collection.template_set.all(): for variation in variations: name = str(template) + ' ' + str(variation) - columns.append({ - 'name': name, - 'type': 'graph', - 'graph_index': graph_index, - 'sprite_offset': graph_index * sprite_width, - 'visible': slugify(name) in columns_selected, - }) + columns.append( + { + 'name': name, + 'type': 'graph', + 'graph_index': graph_index, + 'sprite_offset': graph_index * sprite_width, + 'visible': slugify(name) in columns_selected, + } + ) graph_index += 1 for numeric in current_collection.numeric_set.all(): - columns.append({ - 'name': str(numeric), - 'type': 'numeric', - 'visible': slugify(numeric) in columns_selected, - }) + columns.append( + { + 'name': str(numeric), + 'type': 'numeric', + 'visible': slugify(numeric) in columns_selected, + } + ) attribute_ids.append(numeric.attribute_id) for relation in current_collection.relation_set.all(): - columns.append({ - 'name': str(relation), - 'type': 'relation', - 'visible': slugify(relation) in columns_selected, - }) + columns.append( + { + 'name': str(relation), + 'type': 'relation', + 'visible': slugify(relation) in columns_selected, + } + ) attribute_ids.append(relation.attribute_id) hosts = OrderedDict() @@ -115,8 +120,7 @@ def index(request): hosts[server['hostname']] = dict(server) page = abs(int(request.GET.get('page', 1))) - per_page = int(request.GET.get( - 'per_page', request.session.get('resources_per_page', 8))) + per_page = int(request.GET.get('per_page', request.session.get('resources_per_page', 8))) # Save settings in session request.session['resources_per_page'] = per_page @@ -133,16 +137,18 @@ def index(request): raise SuspiciousOperation('{} is not a valid!'.format(page)) sprite_url = settings.MEDIA_URL + 'graph_sprite/' + current_collection.name - template_info.update({ - 'columns': columns, - 'hosts': hosts_page, - 'page': page, - 'per_page': per_page, - 'matched_hostnames': matched_hostnames, - 'understood': understood, - 'error': None, - 'sprite_url': sprite_url, - }) + template_info.update( + { + 'columns': columns, + 'hosts': hosts_page, + 'page': page, + 'per_page': per_page, + 'matched_hostnames': matched_hostnames, + 'understood': understood, + 'error': None, + 'sprite_url': sprite_url, + } + ) return TemplateResponse(request, 'resources/index.html', template_info) @@ -159,17 +165,19 @@ def graph_popup(request): # but we don't bother because they are unlikely to be more than a few # marked as overview. for collection in Collection.objects.filter(overview=True): - servers = list(Query({ - GRAPHITE_ATTRIBUTE_ID: collection.name, - 'hostname': hostname, - })) + servers = list( + Query( + { + GRAPHITE_ATTRIBUTE_ID: collection.name, + 'hostname': hostname, + } + ) + ) if servers: table = collection.graph_table(servers[0]) params = [v2 for k1, v1 in table for k2, v2 in v1][int(graph_id)] url = reverse(graph) + '?' + params - return TemplateResponse(request, 'resources/graph_popup.html', { - 'image': url - }) + return TemplateResponse(request, 'resources/graph_popup.html', {'image': url}) return HttpResponseBadRequest('No graph found') diff --git a/serveradmin/serverdb/admin.py b/serveradmin/serverdb/admin.py index 57942e8e..beb36d90 100644 --- a/serveradmin/serverdb/admin.py +++ b/serveradmin/serverdb/admin.py @@ -7,16 +7,16 @@ from django.utils.html import format_html from serveradmin.serverdb.forms import ( - ServertypeAttributeAdminForm, ServertypeAdminForm, + ServertypeAttributeAdminForm, ) from serveradmin.serverdb.models import ( - Servertype, Attribute, - ServertypeAttribute, Server, ServerRelationAttribute, ServerStringAttribute, + Servertype, + ServertypeAttribute, ) @@ -27,12 +27,16 @@ class ServertypeAttributeInline(admin.TabularInline): class ServertypeAdmin(admin.ModelAdmin): form = ServertypeAdminForm - inlines = ( - ServertypeAttributeInline, - ) + inlines = (ServertypeAttributeInline,) - list_display = ['servertype_id', 'description', ] - search_fields = ['servertype_id', 'description', ] + list_display = [ + 'servertype_id', + 'description', + ] + search_fields = [ + 'servertype_id', + 'description', + ] def get_readonly_fields(self, request, obj=None): fields = super().get_readonly_fields(request, obj) @@ -61,10 +65,21 @@ class ServerAdmin(admin.ModelAdmin): ServerStringAttributeInline, ) - list_display = ['server_id', 'hostname', 'servertype', ] - list_display_links = ['hostname', ] - search_fields = ['server_id', 'hostname', ] - list_filter = ['servertype__servertype_id', ] + list_display = [ + 'server_id', + 'hostname', + 'servertype', + ] + list_display_links = [ + 'hostname', + ] + search_fields = [ + 'server_id', + 'hostname', + ] + list_filter = [ + 'servertype__servertype_id', + ] class AttributeAdmin(admin.ModelAdmin): @@ -78,8 +93,17 @@ class AttributeAdmin(admin.ModelAdmin): 'clone', 'history', ] - search_fields = ['attribute_id', ] - list_filter = ['type', 'group', 'multi', 'readonly', 'clone', 'history', ] + search_fields = [ + 'attribute_id', + ] + list_filter = [ + 'type', + 'group', + 'multi', + 'readonly', + 'clone', + 'history', + ] def get_readonly_fields(self, request, obj=None): fields = super().get_readonly_fields(request, obj) @@ -88,10 +112,7 @@ def get_readonly_fields(self, request, obj=None): # objects and the little use-cases we have right now we don't # support it. if obj: - fields += ( - 'type', 'attribute_id', 'target_servertype', - 'reversed_attribute' - ) + fields += ('type', 'attribute_id', 'target_servertype', 'reversed_attribute') return fields diff --git a/serveradmin/serverdb/forms.py b/serveradmin/serverdb/forms.py index b450e395..131f5977 100644 --- a/serveradmin/serverdb/forms.py +++ b/serveradmin/serverdb/forms.py @@ -24,12 +24,12 @@ def clean(self): # It makes no sense to add inet or supernet attributes to hosts of # ip_addr_type null because they would have to be empty anyways. inet_attribute = ( - self.cleaned_data['attribute'].type in ('inet', 'supernet') and - self.instance.servertype.ip_addr_type == 'null' + self.cleaned_data['attribute'].type in ('inet', 'supernet') + and self.instance.servertype.ip_addr_type == 'null' ) if inet_attribute: raise ValidationError( - 'Adding an attribute of type inet or supernet when ' - 'ip_addr_type is null is not possible!') + 'Adding an attribute of type inet or supernet when ' 'ip_addr_type is null is not possible!' + ) super().clean() diff --git a/serveradmin/serverdb/migrations/0001_initial.py b/serveradmin/serverdb/migrations/0001_initial.py index 6ea1177c..96660bdd 100644 --- a/serveradmin/serverdb/migrations/0001_initial.py +++ b/serveradmin/serverdb/migrations/0001_initial.py @@ -1,15 +1,14 @@ # Generated by Django 2.1.1 on 2018-09-02 22:26 -from django.conf import settings import django.core.validators -from django.db import migrations, models import django.db.models.deletion import django.utils.timezone import netfields.fields +from django.conf import settings +from django.db import migrations, models class Migration(migrations.Migration): - initial = True dependencies = [ @@ -21,16 +20,63 @@ class Migration(migrations.Migration): migrations.CreateModel( name='Attribute', fields=[ - ('attribute_id', models.CharField(max_length=32, primary_key=True, serialize=False, validators=[django.core.validators.RegexValidator('\\A[a-z][a-z0-9_]+\\Z', 'Invalid id')])), - ('type', models.CharField(choices=[('string', 'string'), ('boolean', 'boolean'), ('relation', 'relation'), ('reverse', 'reverse'), ('number', 'number'), ('inet', 'inet'), ('macaddr', 'macaddr'), ('date', 'date'), ('supernet', 'supernet'), ('domain', 'domain')], max_length=32)), + ( + 'attribute_id', + models.CharField( + max_length=32, + primary_key=True, + serialize=False, + validators=[django.core.validators.RegexValidator('\\A[a-z][a-z0-9_]+\\Z', 'Invalid id')], + ), + ), + ( + 'type', + models.CharField( + choices=[ + ('string', 'string'), + ('boolean', 'boolean'), + ('relation', 'relation'), + ('reverse', 'reverse'), + ('number', 'number'), + ('inet', 'inet'), + ('macaddr', 'macaddr'), + ('date', 'date'), + ('supernet', 'supernet'), + ('domain', 'domain'), + ], + max_length=32, + ), + ), ('multi', models.BooleanField(default=False)), ('hovertext', models.TextField(blank=True, default='')), ('group', models.CharField(default='other', max_length=32)), ('help_link', models.CharField(blank=True, max_length=255, null=True)), ('readonly', models.BooleanField(default=False)), ('clone', models.BooleanField(default=False)), - ('regexp', models.CharField(max_length=1024, validators=[django.core.validators.RegexValidator('\\A\\\\A.*\\\\Z\\Z', 'You must wrap your pattern in "\\A" and "\\Z" to force line matching')])), - ('reversed_attribute', models.ForeignKey(blank=True, db_index=False, limit_choices_to={'type': 'relation'}, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reversed_attribute_set', to='serverdb.Attribute')), + ( + 'regexp', + models.CharField( + max_length=1024, + validators=[ + django.core.validators.RegexValidator( + '\\A\\\\A.*\\\\Z\\Z', + 'You must wrap your pattern in "\\A" and "\\Z" to force line matching', + ) + ], + ), + ), + ( + 'reversed_attribute', + models.ForeignKey( + blank=True, + db_index=False, + limit_choices_to={'type': 'relation'}, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='reversed_attribute_set', + to='serverdb.Attribute', + ), + ), ], options={ 'db_table': 'attribute', @@ -43,8 +89,16 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('change_on', models.DateTimeField(db_index=True, default=django.utils.timezone.now)), ('changes_json', models.TextField()), - ('app', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='apps.Application')), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ( + 'app', + models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='apps.Application'), + ), + ( + 'user', + models.ForeignKey( + null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL + ), + ), ], ), migrations.CreateModel( @@ -60,8 +114,16 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('change_on', models.DateTimeField(db_index=True, default=django.utils.timezone.now)), - ('app', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='apps.Application')), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ( + 'app', + models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='apps.Application'), + ), + ( + 'user', + models.ForeignKey( + null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL + ), + ), ], ), migrations.CreateModel( @@ -86,7 +148,18 @@ class Migration(migrations.Migration): name='Server', fields=[ ('server_id', models.AutoField(primary_key=True, serialize=False)), - ('hostname', models.CharField(max_length=64, unique=True, validators=[django.core.validators.RegexValidator('\\A(\\*\\.)?([a-z0-9]+[\\.\\-])*[a-z0-9]+\\Z', 'Invalid hostname')])), + ( + 'hostname', + models.CharField( + max_length=64, + unique=True, + validators=[ + django.core.validators.RegexValidator( + '\\A(\\*\\.)?([a-z0-9]+[\\.\\-])*[a-z0-9]+\\Z', 'Invalid hostname' + ) + ], + ), + ), ('intern_ip', netfields.fields.InetAddressField(blank=True, max_length=39, null=True)), ], options={ @@ -97,8 +170,20 @@ class Migration(migrations.Migration): name='ServerBooleanAttribute', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('attribute', models.ForeignKey(limit_choices_to={'type': 'boolean'}, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Attribute')), - ('server', models.ForeignKey(db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server')), + ( + 'attribute', + models.ForeignKey( + limit_choices_to={'type': 'boolean'}, + on_delete=django.db.models.deletion.CASCADE, + to='serverdb.Attribute', + ), + ), + ( + 'server', + models.ForeignKey( + db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server' + ), + ), ], options={ 'db_table': 'server_boolean_attribute', @@ -109,8 +194,21 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('value', models.DateField()), - ('attribute', models.ForeignKey(db_index=False, limit_choices_to={'type': 'date'}, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Attribute')), - ('server', models.ForeignKey(db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server')), + ( + 'attribute', + models.ForeignKey( + db_index=False, + limit_choices_to={'type': 'date'}, + on_delete=django.db.models.deletion.CASCADE, + to='serverdb.Attribute', + ), + ), + ( + 'server', + models.ForeignKey( + db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server' + ), + ), ], options={ 'db_table': 'server_date_attribute', @@ -121,8 +219,21 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('value', netfields.fields.InetAddressField(max_length=39)), - ('attribute', models.ForeignKey(db_index=False, limit_choices_to={'type': 'inet'}, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Attribute')), - ('server', models.ForeignKey(db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server')), + ( + 'attribute', + models.ForeignKey( + db_index=False, + limit_choices_to={'type': 'inet'}, + on_delete=django.db.models.deletion.CASCADE, + to='serverdb.Attribute', + ), + ), + ( + 'server', + models.ForeignKey( + db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server' + ), + ), ], options={ 'db_table': 'server_inet_attribute', @@ -133,8 +244,21 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('value', netfields.fields.MACAddressField()), - ('attribute', models.ForeignKey(db_index=False, limit_choices_to={'type': 'macaddr'}, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Attribute')), - ('server', models.ForeignKey(db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server')), + ( + 'attribute', + models.ForeignKey( + db_index=False, + limit_choices_to={'type': 'macaddr'}, + on_delete=django.db.models.deletion.CASCADE, + to='serverdb.Attribute', + ), + ), + ( + 'server', + models.ForeignKey( + db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server' + ), + ), ], options={ 'db_table': 'server_macaddr_attribute', @@ -145,8 +269,21 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('value', models.DecimalField(decimal_places=0, max_digits=65)), - ('attribute', models.ForeignKey(db_index=False, limit_choices_to={'type': 'number'}, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Attribute')), - ('server', models.ForeignKey(db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server')), + ( + 'attribute', + models.ForeignKey( + db_index=False, + limit_choices_to={'type': 'number'}, + on_delete=django.db.models.deletion.CASCADE, + to='serverdb.Attribute', + ), + ), + ( + 'server', + models.ForeignKey( + db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server' + ), + ), ], options={ 'db_table': 'server_number_attribute', @@ -156,9 +293,32 @@ class Migration(migrations.Migration): name='ServerRelationAttribute', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('attribute', models.ForeignKey(db_index=False, limit_choices_to={'type': 'relation'}, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Attribute')), - ('server', models.ForeignKey(db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server')), - ('value', models.ForeignKey(db_column='value', db_index=False, on_delete=django.db.models.deletion.PROTECT, related_name='relation_attribute_servers', related_query_name='relation_attribute_server', to='serverdb.Server')), + ( + 'attribute', + models.ForeignKey( + db_index=False, + limit_choices_to={'type': 'relation'}, + on_delete=django.db.models.deletion.CASCADE, + to='serverdb.Attribute', + ), + ), + ( + 'server', + models.ForeignKey( + db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server' + ), + ), + ( + 'value', + models.ForeignKey( + db_column='value', + db_index=False, + on_delete=django.db.models.deletion.PROTECT, + related_name='relation_attribute_servers', + related_query_name='relation_attribute_server', + to='serverdb.Server', + ), + ), ], options={ 'db_table': 'server_relation_attribute', @@ -169,8 +329,21 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('value', models.CharField(max_length=1024)), - ('attribute', models.ForeignKey(db_index=False, limit_choices_to={'type': 'string'}, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Attribute')), - ('server', models.ForeignKey(db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server')), + ( + 'attribute', + models.ForeignKey( + db_index=False, + limit_choices_to={'type': 'string'}, + on_delete=django.db.models.deletion.CASCADE, + to='serverdb.Attribute', + ), + ), + ( + 'server', + models.ForeignKey( + db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Server' + ), + ), ], options={ 'db_table': 'server_string_attribute', @@ -179,9 +352,28 @@ class Migration(migrations.Migration): migrations.CreateModel( name='Servertype', fields=[ - ('servertype_id', models.CharField(max_length=32, primary_key=True, serialize=False, validators=[django.core.validators.RegexValidator('\\A[a-z][a-z0-9_]+\\Z', 'Invalid id')])), + ( + 'servertype_id', + models.CharField( + max_length=32, + primary_key=True, + serialize=False, + validators=[django.core.validators.RegexValidator('\\A[a-z][a-z0-9_]+\\Z', 'Invalid id')], + ), + ), ('description', models.CharField(max_length=1024)), - ('ip_addr_type', models.CharField(choices=[('null', 'null'), ('host', 'host'), ('loadbalancer', 'loadbalancer'), ('network', 'network')], max_length=32)), + ( + 'ip_addr_type', + models.CharField( + choices=[ + ('null', 'null'), + ('host', 'host'), + ('loadbalancer', 'loadbalancer'), + ('network', 'network'), + ], + max_length=32, + ), + ), ], options={ 'db_table': 'servertype', @@ -195,10 +387,48 @@ class Migration(migrations.Migration): ('required', models.BooleanField(default=False)), ('default_value', models.CharField(blank=True, max_length=255, null=True)), ('default_visible', models.BooleanField(default=False)), - ('attribute', models.ForeignKey(db_index=False, on_delete=django.db.models.deletion.CASCADE, related_name='servertype_attributes', to='serverdb.Attribute')), - ('consistent_via_attribute', models.ForeignKey(blank=True, db_column='consistent_via_attribute_id', db_index=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='consistent_via_servertype_attributes', to='serverdb.Attribute')), - ('related_via_attribute', models.ForeignKey(blank=True, db_index=False, limit_choices_to=models.Q(type__in=['relation', 'reverse', 'supernet', 'domain']), null=True, on_delete=django.db.models.deletion.CASCADE, related_name='related_via_servertype_attributes', to='serverdb.Attribute')), - ('servertype', models.ForeignKey(db_index=False, on_delete=django.db.models.deletion.CASCADE, related_name='attributes', to='serverdb.Servertype')), + ( + 'attribute', + models.ForeignKey( + db_index=False, + on_delete=django.db.models.deletion.CASCADE, + related_name='servertype_attributes', + to='serverdb.Attribute', + ), + ), + ( + 'consistent_via_attribute', + models.ForeignKey( + blank=True, + db_column='consistent_via_attribute_id', + db_index=False, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='consistent_via_servertype_attributes', + to='serverdb.Attribute', + ), + ), + ( + 'related_via_attribute', + models.ForeignKey( + blank=True, + db_index=False, + limit_choices_to=models.Q(type__in=['relation', 'reverse', 'supernet', 'domain']), + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='related_via_servertype_attributes', + to='serverdb.Attribute', + ), + ), + ( + 'servertype', + models.ForeignKey( + db_index=False, + on_delete=django.db.models.deletion.CASCADE, + related_name='attributes', + to='serverdb.Servertype', + ), + ), ], options={ 'db_table': 'servertype_attribute', @@ -218,7 +448,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='attribute', name='target_servertype', - field=models.ForeignKey(blank=True, db_index=False, null=True, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Servertype'), + field=models.ForeignKey( + blank=True, + db_index=False, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to='serverdb.Servertype', + ), ), migrations.AlterUniqueTogether( name='servertypeattribute', diff --git a/serveradmin/serverdb/migrations/0003_server_indexing.py b/serveradmin/serverdb/migrations/0003_server_indexing.py index 3ae66b67..496750e9 100644 --- a/serveradmin/serverdb/migrations/0003_server_indexing.py +++ b/serveradmin/serverdb/migrations/0003_server_indexing.py @@ -8,10 +8,7 @@ class Migration(migrations.Migration): operations = [ # Add a pg_trgm based trigram index on the server hostname. migrations.RunSQL('CREATE EXTENSION IF NOT EXISTS pg_trgm'), - migrations.RunSQL( - 'CREATE INDEX server_hostname_trgm ' - 'ON server USING gin (hostname gin_trgm_ops)' - ), + migrations.RunSQL('CREATE INDEX server_hostname_trgm ' 'ON server USING gin (hostname gin_trgm_ops)'), # Ensure objects within the same servertype have a unique intern_ip. migrations.RunSQL('CREATE EXTENSION IF NOT EXISTS btree_gist'), migrations.RunSQL( diff --git a/serveradmin/serverdb/migrations/0005_attribute_clone.py b/serveradmin/serverdb/migrations/0005_attribute_clone.py index 57d5cc7d..69cb5c5f 100644 --- a/serveradmin/serverdb/migrations/0005_attribute_clone.py +++ b/serveradmin/serverdb/migrations/0005_attribute_clone.py @@ -2,7 +2,6 @@ class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0004_attribute_value_constraints'), ] @@ -10,16 +9,14 @@ class Migration(migrations.Migration): operations = [ # Mark all previously defined attributes as clonable once. migrations.RunSQL( - 'UPDATE attribute ' - 'SET clone = true ' - "WHERE type NOT IN ('reverse', 'supernet', 'domain')" + 'UPDATE attribute ' 'SET clone = true ' "WHERE type NOT IN ('reverse', 'supernet', 'domain')" ), # Forbid attributes of relational types from beeing clonable as they # can't be written to due to beeing drived from other attributes. migrations.RunSQL( 'ALTER TABLE attribute ' 'ADD CONSTRAINT attribute_clone_check ' - " CHECK (NOT clone OR type NOT IN (" + ' CHECK (NOT clone OR type NOT IN (' " 'reverse', 'supernet', 'domain'))" ), ] diff --git a/serveradmin/serverdb/migrations/0006_datetime_datatype.py b/serveradmin/serverdb/migrations/0006_datetime_datatype.py index 0e1212d2..e4eb288b 100644 --- a/serveradmin/serverdb/migrations/0006_datetime_datatype.py +++ b/serveradmin/serverdb/migrations/0006_datetime_datatype.py @@ -1,12 +1,11 @@ # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2019-03-07 13:18 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0005_attribute_clone'), ] @@ -25,12 +24,29 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='attribute', name='type', - field=models.CharField(choices=[('macaddr', 'macaddr'), ('domain', 'domain'), ('boolean', 'boolean'), ('inet', 'inet'), ('reverse', 'reverse'), ('number', 'number'), ('datetime', 'datetime'), ('string', 'string'), ('supernet', 'supernet'), ('relation', 'relation'), ('date', 'date')], max_length=32), + field=models.CharField( + choices=[ + ('macaddr', 'macaddr'), + ('domain', 'domain'), + ('boolean', 'boolean'), + ('inet', 'inet'), + ('reverse', 'reverse'), + ('number', 'number'), + ('datetime', 'datetime'), + ('string', 'string'), + ('supernet', 'supernet'), + ('relation', 'relation'), + ('date', 'date'), + ], + max_length=32, + ), ), migrations.AddField( model_name='serverdatetimeattribute', name='attribute', - field=models.ForeignKey(db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Attribute'), + field=models.ForeignKey( + db_index=False, on_delete=django.db.models.deletion.CASCADE, to='serverdb.Attribute' + ), ), migrations.AddField( model_name='serverdatetimeattribute', diff --git a/serveradmin/serverdb/migrations/0007_hostname_regex_hyphens.py b/serveradmin/serverdb/migrations/0007_hostname_regex_hyphens.py index 6b0e0d81..fe846ef7 100644 --- a/serveradmin/serverdb/migrations/0007_hostname_regex_hyphens.py +++ b/serveradmin/serverdb/migrations/0007_hostname_regex_hyphens.py @@ -7,7 +7,6 @@ class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0006_datetime_datatype'), ] @@ -16,23 +15,28 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='server', name='hostname', - field=models.CharField(max_length=64, unique=True, validators=[ - django.core.validators.RegexValidator( - '\\A(\\*\\.)?([a-z0-9]+(\\.|-+))*[a-z0-9]+\\Z', - 'Invalid hostname')]), + field=models.CharField( + max_length=64, + unique=True, + validators=[ + django.core.validators.RegexValidator( + '\\A(\\*\\.)?([a-z0-9]+(\\.|-+))*[a-z0-9]+\\Z', 'Invalid hostname' + ) + ], + ), ), migrations.RunSQL( sql=( - "ALTER TABLE server " - "DROP CONSTRAINT server_hostname_check, " - "ADD CONSTRAINT server_hostname_check " + 'ALTER TABLE server ' + 'DROP CONSTRAINT server_hostname_check, ' + 'ADD CONSTRAINT server_hostname_check ' "CHECK (hostname::text ~ '\A(\*\.)?([a-z0-9]+(\.|-+))*[a-z0-9]+\Z'::text);" ), reverse_sql=( - "ALTER TABLE server " - "DROP CONSTRAINT server_hostname_check, " - "ADD CONSTRAINT server_hostname_check " + 'ALTER TABLE server ' + 'DROP CONSTRAINT server_hostname_check, ' + 'ADD CONSTRAINT server_hostname_check ' "CHECK (hostname::text ~ '\A(\*\.)?([a-z0-9]+[\.\-])*[a-z0-9]+\Z'::text);" - ) + ), ), ] diff --git a/serveradmin/serverdb/migrations/0008_hostname_length_254.py b/serveradmin/serverdb/migrations/0008_hostname_length_254.py index 39855960..0ecf1c9b 100644 --- a/serveradmin/serverdb/migrations/0008_hostname_length_254.py +++ b/serveradmin/serverdb/migrations/0008_hostname_length_254.py @@ -1,12 +1,11 @@ # Generated by Django 2.2.15 on 2020-10-08 09:16 import django.core.validators -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0007_hostname_regex_hyphens'), ] @@ -15,6 +14,14 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='server', name='hostname', - field=models.CharField(max_length=254, unique=True, validators=[django.core.validators.RegexValidator('\\A(\\*\\.)?([a-z0-9]+(\\.|-+))*[a-z0-9]+\\Z', 'Invalid hostname')]), + field=models.CharField( + max_length=254, + unique=True, + validators=[ + django.core.validators.RegexValidator( + '\\A(\\*\\.)?([a-z0-9]+(\\.|-+))*[a-z0-9]+\\Z', 'Invalid hostname' + ) + ], + ), ), ] diff --git a/serveradmin/serverdb/migrations/0009_servertype_and_attribute_definitions.py b/serveradmin/serverdb/migrations/0009_servertype_and_attribute_definitions.py index 3fc7dc09..74831042 100644 --- a/serveradmin/serverdb/migrations/0009_servertype_and_attribute_definitions.py +++ b/serveradmin/serverdb/migrations/0009_servertype_and_attribute_definitions.py @@ -1,11 +1,10 @@ # Generated by Django 3.2.11 on 2022-01-24 12:03 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0008_hostname_length_254'), ] @@ -14,16 +13,47 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='attribute', name='type', - field=models.CharField(choices=[('string', 'string'), ('boolean', 'boolean'), ('relation', 'relation'), ('reverse', 'reverse'), ('number', 'number'), ('inet', 'inet'), ('macaddr', 'macaddr'), ('date', 'date'), ('datetime', 'datetime'), ('supernet', 'supernet'), ('domain', 'domain')], max_length=32), + field=models.CharField( + choices=[ + ('string', 'string'), + ('boolean', 'boolean'), + ('relation', 'relation'), + ('reverse', 'reverse'), + ('number', 'number'), + ('inet', 'inet'), + ('macaddr', 'macaddr'), + ('date', 'date'), + ('datetime', 'datetime'), + ('supernet', 'supernet'), + ('domain', 'domain'), + ], + max_length=32, + ), ), migrations.AlterField( model_name='serverdatetimeattribute', name='attribute', - field=models.ForeignKey(db_index=False, limit_choices_to={'type': 'datetime'}, on_delete=django.db.models.deletion.CASCADE, to='serverdb.attribute'), + field=models.ForeignKey( + db_index=False, + limit_choices_to={'type': 'datetime'}, + on_delete=django.db.models.deletion.CASCADE, + to='serverdb.attribute', + ), ), migrations.AlterField( model_name='servertype', name='ip_addr_type', - field=models.CharField(choices=[('null', 'null: intern_ip must be empty, no inet attributes'), ('host', 'host: intern_ip and inet must be an ip address and unique across all objects'), ('loadbalancer', 'loadbalancer: intern_ip and inet must be an ip address'), ('network', 'network: intern_ip and inet must be an ip network, not overlapping with same servertype')], max_length=32), + field=models.CharField( + choices=[ + ('null', 'null: intern_ip must be empty, no inet attributes'), + ('host', 'host: intern_ip and inet must be an ip address and unique across all objects'), + ('loadbalancer', 'loadbalancer: intern_ip and inet must be an ip address'), + ( + 'network', + 'network: intern_ip and inet must be an ip network, not overlapping with same servertype', + ), + ], + max_length=32, + ), ), ] diff --git a/serveradmin/serverdb/migrations/0010_delete_change.py b/serveradmin/serverdb/migrations/0010_delete_change.py index 508cb976..e8a59108 100644 --- a/serveradmin/serverdb/migrations/0010_delete_change.py +++ b/serveradmin/serverdb/migrations/0010_delete_change.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0009_servertype_and_attribute_definitions'), ] diff --git a/serveradmin/serverdb/migrations/0011_create_change_table.py b/serveradmin/serverdb/migrations/0011_create_change_table.py index e9a1efb9..0d0de564 100644 --- a/serveradmin/serverdb/migrations/0011_create_change_table.py +++ b/serveradmin/serverdb/migrations/0011_create_change_table.py @@ -1,13 +1,12 @@ # Generated by Django 3.2.16 on 2022-10-24 13:37 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models import serveradmin class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0010_delete_change'), ] @@ -18,7 +17,12 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('object_id', models.IntegerField(db_index=True)), - ('change_type', models.CharField(choices=[('create', 'create'), ('change', 'change'), ('delete', 'delete')], max_length=6)), + ( + 'change_type', + models.CharField( + choices=[('create', 'create'), ('change', 'change'), ('delete', 'delete')], max_length=6 + ), + ), ('change_json', models.JSONField(encoder=serveradmin.serverdb.models.Change.ChangeJSONEncoder)), ('commit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='serverdb.changecommit')), ], diff --git a/serveradmin/serverdb/migrations/0012_migrate_change_tables.py b/serveradmin/serverdb/migrations/0012_migrate_change_tables.py index 1e9f2b2a..39459f59 100644 --- a/serveradmin/serverdb/migrations/0012_migrate_change_tables.py +++ b/serveradmin/serverdb/migrations/0012_migrate_change_tables.py @@ -2,7 +2,7 @@ import math -from django.db import migrations, transaction, connection +from django.db import connection, migrations, transaction from rich.progress import Progress BATCH_SIZE = 100000 @@ -14,12 +14,13 @@ def migrate_change_add(apps, schema_editor): batches = math.ceil(total / BATCH_SIZE) with Progress() as progress: - migration = progress.add_task("\t[green]Migrating ChangeAdd data...", total=batches) + migration = progress.add_task('\t[green]Migrating ChangeAdd data...', total=batches) with connection.cursor() as cursor: while not progress.finished: with transaction.atomic(): - cursor.execute(""" + cursor.execute( + """ WITH moved AS ( DELETE FROM serverdb_changeadd WHERE id IN (SELECT id FROM serverdb_changeadd ORDER BY id DESC LIMIT %s FOR UPDATE) @@ -31,7 +32,9 @@ def migrate_change_add(apps, schema_editor): ) INSERT INTO serverdb_change (object_id, change_type, change_json, commit_id) SELECT * FROM moved; - """, [BATCH_SIZE]) + """, + [BATCH_SIZE], + ) progress.update(migration, advance=1) @@ -42,12 +45,13 @@ def migrate_change_delete(apps, schema_editor): batches = math.ceil(total / BATCH_SIZE) with Progress() as progress: - migration = progress.add_task("\t[green]Migrating ChangeDelete data...", total=batches) + migration = progress.add_task('\t[green]Migrating ChangeDelete data...', total=batches) with connection.cursor() as cursor: while not progress.finished: with transaction.atomic(): - cursor.execute(""" + cursor.execute( + """ WITH moved AS ( DELETE FROM serverdb_changedelete WHERE id IN (SELECT id FROM serverdb_changedelete ORDER BY id DESC LIMIT %s FOR UPDATE) @@ -59,7 +63,9 @@ def migrate_change_delete(apps, schema_editor): ) INSERT INTO serverdb_change (object_id, change_type, change_json, commit_id) SELECT * FROM moved; - """, [BATCH_SIZE]) + """, + [BATCH_SIZE], + ) progress.update(migration, advance=1) @@ -70,12 +76,13 @@ def migrate_change_update(apps, schema_editor): batches = math.ceil(total / BATCH_SIZE) with Progress() as progress: - migration = progress.add_task("\t[green]Migrating ChangeUpdate data...", total=batches) + migration = progress.add_task('\t[green]Migrating ChangeUpdate data...', total=batches) with connection.cursor() as cursor: while not progress.finished: with transaction.atomic(): - cursor.execute(""" + cursor.execute( + """ WITH moved AS ( DELETE FROM serverdb_changeupdate WHERE id IN (SELECT id FROM serverdb_changeupdate ORDER BY id DESC LIMIT %s FOR UPDATE) @@ -87,7 +94,9 @@ def migrate_change_update(apps, schema_editor): ) INSERT INTO serverdb_change (object_id, change_type, change_json, commit_id) SELECT * FROM moved; - """, [BATCH_SIZE]) + """, + [BATCH_SIZE], + ) progress.update(migration, advance=1) diff --git a/serveradmin/serverdb/migrations/0013_change_index.py b/serveradmin/serverdb/migrations/0013_change_index.py index 9bce975e..c1f42237 100644 --- a/serveradmin/serverdb/migrations/0013_change_index.py +++ b/serveradmin/serverdb/migrations/0013_change_index.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0012_migrate_change_tables'), ] diff --git a/serveradmin/serverdb/migrations/0014_delete_deprecated_change_models.py b/serveradmin/serverdb/migrations/0014_delete_deprecated_change_models.py index 0f918a8f..a630c001 100644 --- a/serveradmin/serverdb/migrations/0014_delete_deprecated_change_models.py +++ b/serveradmin/serverdb/migrations/0014_delete_deprecated_change_models.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0013_change_index'), ] diff --git a/serveradmin/serverdb/migrations/0015_attribute_history_field.py b/serveradmin/serverdb/migrations/0015_attribute_history_field.py index 452aca8a..3ed0fcc2 100644 --- a/serveradmin/serverdb/migrations/0015_attribute_history_field.py +++ b/serveradmin/serverdb/migrations/0015_attribute_history_field.py @@ -1,11 +1,9 @@ # Generated by Django 3.2.18 on 2023-03-02 09:12 from django.db import migrations, models -import serveradmin.serverdb.models class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0014_delete_deprecated_change_models'), ] @@ -14,6 +12,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='attribute', name='history', - field=models.BooleanField(default=True, help_text='Log changes to this attribute') + field=models.BooleanField(default=True, help_text='Log changes to this attribute'), ), ] diff --git a/serveradmin/serverdb/migrations/0016_optional_servertype_for_relation.py b/serveradmin/serverdb/migrations/0016_optional_servertype_for_relation.py index 49945bfc..46f6d3ea 100644 --- a/serveradmin/serverdb/migrations/0016_optional_servertype_for_relation.py +++ b/serveradmin/serverdb/migrations/0016_optional_servertype_for_relation.py @@ -4,18 +4,15 @@ class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0015_attribute_history_field'), ] operations = [ - migrations.RunSQL( - "ALTER TABLE attribute DROP CONSTRAINT IF EXISTS attribute_target_servertype_id_check" - ), + migrations.RunSQL('ALTER TABLE attribute DROP CONSTRAINT IF EXISTS attribute_target_servertype_id_check'), # This is the same as before but without a check for type relation. migrations.RunSQL( - "ALTER TABLE attribute ADD CONSTRAINT attribute_target_servertype_id_check " + 'ALTER TABLE attribute ADD CONSTRAINT attribute_target_servertype_id_check ' "CHECK((type IN ('domain', 'supernet', 'relation')) = (target_servertype_id IS NOT NULL OR type = 'relation'))" ), ] diff --git a/serveradmin/serverdb/migrations/0017_inet_family_choice.py b/serveradmin/serverdb/migrations/0017_inet_family_choice.py index 135d5ade..0a8dffa3 100644 --- a/serveradmin/serverdb/migrations/0017_inet_family_choice.py +++ b/serveradmin/serverdb/migrations/0017_inet_family_choice.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0016_optional_servertype_for_relation'), ] @@ -13,6 +12,8 @@ class Migration(migrations.Migration): migrations.AddField( model_name='attribute', name='inet_address_family', - field=models.CharField(blank=True, choices=[(None, 'none or any'), ('IPV4', 'IPv4'), ('IPV6', 'IPv6')], max_length=5), + field=models.CharField( + blank=True, choices=[(None, 'none or any'), ('IPV4', 'IPv4'), ('IPV6', 'IPv6')], max_length=5 + ), ), ] diff --git a/serveradmin/serverdb/migrations/0018_alter_server_hostname.py b/serveradmin/serverdb/migrations/0018_alter_server_hostname.py index bcc3aad1..b082af38 100644 --- a/serveradmin/serverdb/migrations/0018_alter_server_hostname.py +++ b/serveradmin/serverdb/migrations/0018_alter_server_hostname.py @@ -5,7 +5,6 @@ class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0017_inet_family_choice'), ] @@ -14,21 +13,28 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='server', name='hostname', - field=models.CharField(max_length=254, unique=True, validators=[django.core.validators.RegexValidator('\\A(\\*\\.)?([a-z0-9_]+(\\.|-+))*[a-z0-9]+\\Z', 'Invalid hostname')]), + field=models.CharField( + max_length=254, + unique=True, + validators=[ + django.core.validators.RegexValidator( + '\\A(\\*\\.)?([a-z0-9_]+(\\.|-+))*[a-z0-9]+\\Z', 'Invalid hostname' + ) + ], + ), ), migrations.RunSQL( sql=( - "ALTER TABLE server " - "DROP CONSTRAINT server_hostname_check, " - "ADD CONSTRAINT server_hostname_check " + 'ALTER TABLE server ' + 'DROP CONSTRAINT server_hostname_check, ' + 'ADD CONSTRAINT server_hostname_check ' "CHECK (hostname::text ~ '\A(\*\.)?([a-z0-9_]+(\.|-+))*[a-z0-9]+\Z'::text);" ), reverse_sql=( - "ALTER TABLE server " - "DROP CONSTRAINT server_hostname_check, " - "ADD CONSTRAINT server_hostname_check " + 'ALTER TABLE server ' + 'DROP CONSTRAINT server_hostname_check, ' + 'ADD CONSTRAINT server_hostname_check ' "CHECK (hostname::text ~ '\A(\*\.)?([a-z0-9]+(\.|-+))*[a-z0-9]+\Z'::text);" - ) + ), ), ] - diff --git a/serveradmin/serverdb/migrations/0019_drop_intern_ip_constraint.py b/serveradmin/serverdb/migrations/0019_drop_intern_ip_constraint.py index 7a7e987e..b0f3009b 100644 --- a/serveradmin/serverdb/migrations/0019_drop_intern_ip_constraint.py +++ b/serveradmin/serverdb/migrations/0019_drop_intern_ip_constraint.py @@ -4,11 +4,10 @@ class Migration(migrations.Migration): - dependencies = [ ('serverdb', '0018_alter_server_hostname'), ] operations = [ - migrations.RunSQL("ALTER TABLE server DROP CONSTRAINT IF EXISTS server_inter_ip_exclude"), + migrations.RunSQL('ALTER TABLE server DROP CONSTRAINT IF EXISTS server_inter_ip_exclude'), ] diff --git a/serveradmin/serverdb/models.py b/serveradmin/serverdb/models.py index 8adace1f..33fcb72b 100644 --- a/serveradmin/serverdb/models.py +++ b/serveradmin/serverdb/models.py @@ -32,43 +32,43 @@ from serveradmin.apps.models import Application ATTRIBUTE_TYPES = { - "string": str, - "boolean": lambda x: bool(strtobool(x)), - "relation": str, - "reverse": str, - "number": lambda x: float(x) if "." in str(x) else int(x), - "inet": lambda x: inet_to_python(x), - "macaddr": EUI, - "date": str, - "datetime": str, - "supernet": str, - "domain": str, + 'string': str, + 'boolean': lambda x: bool(strtobool(x)), + 'relation': str, + 'reverse': str, + 'number': lambda x: float(x) if '.' in str(x) else int(x), + 'inet': lambda x: inet_to_python(x), + 'macaddr': EUI, + 'date': str, + 'datetime': str, + 'supernet': str, + 'domain': str, } IP_ADDR_TYPES = [ - ("null", "null: intern_ip must be empty, no inet attributes"), + ('null', 'null: intern_ip must be empty, no inet attributes'), ( - "host", - "host: intern_ip and inet must be an ip address and unique across all objects per attribute", + 'host', + 'host: intern_ip and inet must be an ip address and unique across all objects per attribute', ), - ("loadbalancer", "loadbalancer: intern_ip and inet must be an ip address"), + ('loadbalancer', 'loadbalancer: intern_ip and inet must be an ip address'), ( - "network", - "network: intern_ip and inet must be an ip network, not overlapping with same servertype", + 'network', + 'network: intern_ip and inet must be an ip network, not overlapping with same servertype', ), ] LOOKUP_ID_VALIDATORS = [ - RegexValidator(r"\A[a-z][a-z0-9_]+\Z", "Invalid id"), + RegexValidator(r'\A[a-z][a-z0-9_]+\Z', 'Invalid id'), ] HOSTNAME_VALIDATORS = [ - RegexValidator(r"\A(\*\.)?([a-z0-9_]+(\.|-+))*[a-z0-9]+\Z", "Invalid hostname"), + RegexValidator(r'\A(\*\.)?([a-z0-9_]+(\.|-+))*[a-z0-9]+\Z', 'Invalid hostname'), ] REGEX_VALIDATORS = [ RegexValidator( - r"\A\\A.*\\Z\Z", + r'\A\\A.*\\Z\Z', 'You must wrap your pattern in "\\A" and "\\Z" to force line matching', ), ] @@ -95,12 +95,12 @@ def is_ip_address(ip_interface: Union[IPv4Interface, IPv6Interface]) -> None: max_prefix_length = ip_interface.network.max_prefixlen if prefix_length != max_prefix_length: - raise ValidationError("Netmask length must be {0}".format(max_prefix_length)) + raise ValidationError('Netmask length must be {0}'.format(max_prefix_length)) def is_unique_ip( ip_interface: Union[IPv4Interface, IPv6Interface], - server: "Server", + server: 'Server', addr_types: list[str], attribute_id: Optional[int] = None, ) -> None: @@ -133,9 +133,7 @@ def is_unique_ip( # TODO: Make attribute_id mandatory when intern_ip is gone. if attribute_id: - object_attribute_q = Q(server_id=server.server_id) | ~Q( - attribute_id=attribute_id - ) + object_attribute_q = Q(server_id=server.server_id) | ~Q(attribute_id=attribute_id) else: object_attribute_q = Q(server_id=server.server_id) @@ -147,7 +145,7 @@ def is_unique_ip( & ~Q(server_id=server.server_id) # Self-server ) ): - duplicates.append(f"{d.hostname} (intern_ip)") + duplicates.append(f'{d.hostname} (intern_ip)') for d in ServerInetAttribute.objects.filter( Q( @@ -156,7 +154,7 @@ def is_unique_ip( & ~object_attribute_q # Self-server ) ): - duplicates.append(f"{d.server.hostname} ({d.attribute})") + duplicates.append(f'{d.server.hostname} ({d.attribute})') if duplicates: raise ValidationError( @@ -166,7 +164,7 @@ def is_unique_ip( def network_overlaps( ip_interface: Union[IPv4Interface, IPv6Interface], - server: "Server", + server: 'Server', addr_types: list[str], attribute_id: Optional[int] = None, ) -> None: @@ -191,9 +189,7 @@ def network_overlaps( # TODO: Make attribute_id mandatory when intern_ip is gone. if attribute_id: - object_attribute_q = Q(server_id=server.server_id) | ~Q( - attribute_id=attribute_id - ) + object_attribute_q = Q(server_id=server.server_id) | ~Q(attribute_id=attribute_id) else: object_attribute_q = Q(server_id=server.server_id) @@ -206,7 +202,7 @@ def network_overlaps( & ~Q(server_id=server.server_id) # Self-server ) ): - duplicates.append(f"{d.hostname} (intern_ip)") + duplicates.append(f'{d.hostname} (intern_ip)') for d in ServerInetAttribute.objects.filter( Q( @@ -216,7 +212,7 @@ def network_overlaps( & ~object_attribute_q # Self-server ) ): - duplicates.append(f"{d.server.hostname} ({d.attribute})") + duplicates.append(f'{d.server.hostname} ({d.attribute})') if duplicates: raise ValidationError( @@ -269,9 +265,9 @@ class Servertype(models.Model): ) class Meta: - app_label = "serverdb" - db_table = "servertype" - ordering = ["servertype_id"] + app_label = 'serverdb' + db_table = 'servertype' + ordering = ['servertype_id'] def __str__(self): return self.servertype_id @@ -279,16 +275,16 @@ def __str__(self): class Attribute(models.Model): class InetAddressFamilyChoice(models.TextChoices): - IPV4 = "IPV4", _("IPv4") - IPV6 = "IPV6", _("IPv6") - __empty__ = _("none or any") + IPV4 = 'IPV4', _('IPv4') + IPV6 = 'IPV6', _('IPv6') + __empty__ = _('none or any') special = None def __init__(self, *args, **kwargs): - if "special" in kwargs: - self.special = kwargs["special"] - del kwargs["special"] + if 'special' in kwargs: + self.special = kwargs['special'] + del kwargs['special'] super(Attribute, self).__init__(*args, **kwargs) attribute_id = models.CharField( @@ -302,36 +298,30 @@ def __init__(self, *args, **kwargs): choices=get_choices(ATTRIBUTE_TYPES.keys()), ) multi = models.BooleanField(null=False, default=False) - hovertext = models.TextField(null=False, blank=True, default="") - group = models.CharField(max_length=32, null=False, blank=False, default="other") + hovertext = models.TextField(null=False, blank=True, default='') + group = models.CharField(max_length=32, null=False, blank=False, default='other') help_link = models.CharField(max_length=255, blank=True, null=True) - inet_address_family = models.CharField( - choices=InetAddressFamilyChoice.choices, max_length=5, blank=True - ) + inet_address_family = models.CharField(choices=InetAddressFamilyChoice.choices, max_length=5, blank=True) readonly = models.BooleanField(null=False, default=False) - target_servertype = models.ForeignKey( - Servertype, on_delete=models.CASCADE, db_index=False, null=True, blank=True - ) + target_servertype = models.ForeignKey(Servertype, on_delete=models.CASCADE, db_index=False, null=True, blank=True) reversed_attribute = models.ForeignKey( - "self", + 'self', on_delete=models.CASCADE, - related_name="reversed_attribute_set", + related_name='reversed_attribute_set', null=True, blank=True, db_index=False, - limit_choices_to=dict(type="relation"), + limit_choices_to=dict(type='relation'), ) clone = models.BooleanField(null=False, default=False) - history = models.BooleanField( - null=False, default=True, help_text="Log changes to this attribute" - ) + history = models.BooleanField(null=False, default=True, help_text='Log changes to this attribute') regexp = models.CharField(max_length=1024, validators=REGEX_VALIDATORS) _compiled_regexp = None class Meta: - app_label = "serverdb" - db_table = "attribute" - ordering = ["attribute_id"] + app_label = 'serverdb' + db_table = 'attribute' + ordering = ['attribute_id'] def __str__(self): return self.attribute_id @@ -339,13 +329,13 @@ def __str__(self): def initializer(self): if self.multi: return set - if self.type == "boolean": + if self.type == 'boolean': return bool return lambda: None def from_str(self, value): if self.multi and not isinstance(value, (list, set)): - raise ValidationError("Attr is multi, but value is not a list/set") + raise ValidationError('Attr is multi, but value is not a list/set') if value is None: return value @@ -367,11 +357,7 @@ def _get_compiled_regexp(self): def regexp_match(self, value): re_compiled = self._get_compiled_regexp() if re_compiled is None: - raise ValidationError( - "Attribute {} has no value validation regexp set".format( - self.attribute_id - ) - ) + raise ValidationError('Attribute {} has no value validation regexp set'.format(self.attribute_id)) # We use lower case booleans in our regexes but python __str__ methods # on booleans return them in upper case. @@ -383,7 +369,7 @@ def regexp_match(self, value): return re_compiled.match(value) def clean(self): - if self.regexp == "": + if self.regexp == '': self.regexp = None super(Attribute, self).clean() @@ -395,37 +381,37 @@ def __init__(self, field, unique=False): Attribute.specials = { - "object_id": Attribute( - attribute_id="object_id", - type="number", + 'object_id': Attribute( + attribute_id='object_id', + type='number', multi=False, clone=False, - group="base", - special=ServerTableSpecial("server_id"), + group='base', + special=ServerTableSpecial('server_id'), ), - "hostname": Attribute( - attribute_id="hostname", - type="string", + 'hostname': Attribute( + attribute_id='hostname', + type='string', multi=False, clone=True, - group="base", - special=ServerTableSpecial("hostname", unique=True), + group='base', + special=ServerTableSpecial('hostname', unique=True), ), - "servertype": Attribute( - attribute_id="servertype", - type="string", + 'servertype': Attribute( + attribute_id='servertype', + type='string', multi=False, clone=True, - group="base", - special=ServerTableSpecial("servertype_id"), + group='base', + special=ServerTableSpecial('servertype_id'), ), - "intern_ip": Attribute( - attribute_id="intern_ip", - type="inet", + 'intern_ip': Attribute( + attribute_id='intern_ip', + type='inet', multi=False, clone=True, - group="base", - special=ServerTableSpecial("intern_ip"), + group='base', + special=ServerTableSpecial('intern_ip'), ), } @@ -433,36 +419,34 @@ def __init__(self, field, unique=False): class ServertypeAttribute(models.Model): servertype = models.ForeignKey( Servertype, - related_name="attributes", + related_name='attributes', db_index=False, on_delete=models.CASCADE, ) attribute = models.ForeignKey( Attribute, - related_name="servertype_attributes", + related_name='servertype_attributes', db_index=False, on_delete=models.CASCADE, ) related_via_attribute = models.ForeignKey( Attribute, on_delete=models.CASCADE, - related_name="related_via_servertype_attributes", + related_name='related_via_servertype_attributes', null=True, blank=True, db_index=False, # It can only be related via a relation (AKA as an hostname # attribute). - limit_choices_to=models.Q( - type__in=["relation", "reverse", "supernet", "domain"] - ), + limit_choices_to=models.Q(type__in=['relation', 'reverse', 'supernet', 'domain']), ) consistent_via_attribute = models.ForeignKey( Attribute, on_delete=models.CASCADE, - related_name="consistent_via_servertype_attributes", + related_name='consistent_via_servertype_attributes', null=True, blank=True, - db_column="consistent_via_attribute_id", + db_column='consistent_via_attribute_id', db_index=False, ) required = models.BooleanField(null=False, default=False) @@ -470,27 +454,27 @@ class ServertypeAttribute(models.Model): default_visible = models.BooleanField(null=False, default=False) class Meta: - app_label = "serverdb" - db_table = "servertype_attribute" - ordering = ["servertype", "attribute"] - unique_together = [["servertype", "attribute"]] + app_label = 'serverdb' + db_table = 'servertype_attribute' + ordering = ['servertype', 'attribute'] + unique_together = [['servertype', 'attribute']] def __str__(self): - return "{0} - {1}".format(self.servertype, self.attribute) + return '{0} - {1}'.format(self.servertype, self.attribute) def get_default_value(self): if not self.default_value: return self.attribute.initializer()() if self.attribute.multi: - default_value = self.default_value.split(",") + default_value = self.default_value.split(',') else: default_value = self.default_value return self.attribute.from_str(default_value) def clean(self): - if self.default_value == "": + if self.default_value == '': self.default_value = None super(ServertypeAttribute, self).clean() @@ -504,15 +488,13 @@ class Server(models.Model): objects = netfields.NetManager() server_id = models.AutoField(primary_key=True) - hostname = models.CharField( - max_length=254, unique=True, validators=HOSTNAME_VALIDATORS - ) + hostname = models.CharField(max_length=254, unique=True, validators=HOSTNAME_VALIDATORS) intern_ip = netfields.InetAddressField(null=True, blank=True) servertype = models.ForeignKey(Servertype, on_delete=models.PROTECT) class Meta: - app_label = "serverdb" - db_table = "server" + app_label = 'serverdb' + db_table = 'server' def __str__(self): return self.hostname @@ -521,16 +503,14 @@ def clean(self): super(Server, self).clean() ip_addr_type = self.servertype.ip_addr_type - if ip_addr_type == "null": + if ip_addr_type == 'null': if self.intern_ip is not None: - raise ValidationError(_("intern_ip must be null"), code="invalid value") + raise ValidationError(_('intern_ip must be null'), code='invalid value') else: # This is special to intern_ip for inet attributes this is covered # by making them required. if self.intern_ip is None: - raise ValidationError( - _("intern_ip must not be null"), code="missing value" - ) + raise ValidationError(_('intern_ip must not be null'), code='missing value') # TODO: This logic is duplicated to the ServerInetAttribute clean # method but can be removed when we remove the special @@ -538,13 +518,13 @@ def clean(self): if type(self.intern_ip) not in [IPv4Interface, IPv6Interface]: self.intern_ip = inet_to_python(self.intern_ip) - if ip_addr_type == "host": + if ip_addr_type == 'host': is_ip_address(self.intern_ip) - is_unique_ip(self.intern_ip, self, ["host"]) - elif ip_addr_type == "network": + is_unique_ip(self.intern_ip, self, ['host']) + elif ip_addr_type == 'network': is_network(self.intern_ip) - network_overlaps(self.intern_ip, self, ["network"]) - elif ip_addr_type == "loadbalancer": + network_overlaps(self.intern_ip, self, ['network']) + elif ip_addr_type == 'loadbalancer': is_ip_address(self.intern_ip) def get_attributes(self, attribute): @@ -566,7 +546,7 @@ class Meta: abstract = True def __str__(self): - return "{0}->{1}={2}".format(self.server, self.attribute, self.get_value()) + return '{0}->{1}={2}'.format(self.server, self.attribute, self.get_value()) def get_value(self): return self.value @@ -579,21 +559,21 @@ def save_value(self, value): @staticmethod def get_model(attribute_type): - if attribute_type in "string": + if attribute_type in 'string': return ServerStringAttribute - if attribute_type == "relation": + if attribute_type == 'relation': return ServerRelationAttribute - if attribute_type == "boolean": + if attribute_type == 'boolean': return ServerBooleanAttribute - if attribute_type == "number": + if attribute_type == 'number': return ServerNumberAttribute - if attribute_type == "inet": + if attribute_type == 'inet': return ServerInetAttribute - if attribute_type == "macaddr": + if attribute_type == 'macaddr': return ServerMACAddressAttribute - if attribute_type == "date": + if attribute_type == 'date': return ServerDateAttribute - if attribute_type == "datetime": + if attribute_type == 'datetime': return ServerDateTimeAttribute @@ -602,28 +582,24 @@ class ServerStringAttribute(ServerAttribute): Attribute, db_index=False, on_delete=models.CASCADE, - limit_choices_to=dict(type="string"), + limit_choices_to=dict(type='string'), ) value = models.CharField(max_length=1024) class Meta: - app_label = "serverdb" - db_table = "server_string_attribute" - unique_together = [["server", "attribute", "value"]] - index_together = [["attribute", "value"]] + app_label = 'serverdb' + db_table = 'server_string_attribute' + unique_together = [['server', 'attribute', 'value']] + index_together = [['attribute', 'value']] def save_value(self, value): - for char in "'\"": + for char in '\'"': if char in value: - raise ValidationError( - '"{}" character is not allowed on string attributes'.format(char) - ) + raise ValidationError('"{}" character is not allowed on string attributes'.format(char)) for datatype, regexp in STR_BASED_DATATYPES: if regexp.match(value): raise ValidationError( - 'String attribute value "{}" matches with {} type'.format( - value, datatype.__name__ - ) + 'String attribute value "{}" matches with {} type'.format(value, datatype.__name__) ) super().save_value(value) @@ -632,7 +608,7 @@ def save_value(self, value): class ServerRelationAttributeManager(models.Manager): def get_queryset(self): manager = super(ServerRelationAttributeManager, self) - return manager.get_queryset().prefetch_related("value") + return manager.get_queryset().prefetch_related('value') class ServerRelationAttribute(ServerAttribute): @@ -642,22 +618,22 @@ class ServerRelationAttribute(ServerAttribute): Attribute, db_index=False, on_delete=models.CASCADE, - limit_choices_to=dict(type="relation"), + limit_choices_to=dict(type='relation'), ) value = models.ForeignKey( Server, - db_column="value", + db_column='value', db_index=False, on_delete=models.PROTECT, - related_name="relation_attribute_servers", - related_query_name="relation_attribute_server", + related_name='relation_attribute_servers', + related_query_name='relation_attribute_server', ) class Meta: - app_label = "serverdb" - db_table = "server_relation_attribute" - unique_together = [["server", "attribute", "value"]] - index_together = [["attribute", "value"]] + app_label = 'serverdb' + db_table = 'server_relation_attribute' + unique_together = [['server', 'attribute', 'value']] + index_together = [['attribute', 'value']] def save_value(self, value): try: @@ -680,14 +656,14 @@ class ServerBooleanAttribute(ServerAttribute): attribute = models.ForeignKey( Attribute, on_delete=models.CASCADE, - limit_choices_to=dict(type="boolean"), + limit_choices_to=dict(type='boolean'), ) class Meta: - app_label = "serverdb" - db_table = "server_boolean_attribute" - unique_together = [["server", "attribute"]] - index_together = [["attribute"]] + app_label = 'serverdb' + db_table = 'server_boolean_attribute' + unique_together = [['server', 'attribute']] + index_together = [['attribute']] def get_value(self): return True @@ -704,22 +680,18 @@ class ServerNumberAttribute(ServerAttribute): Attribute, db_index=False, on_delete=models.CASCADE, - limit_choices_to=dict(type="number"), + limit_choices_to=dict(type='number'), ) value = models.DecimalField(max_digits=65, decimal_places=0) class Meta: - app_label = "serverdb" - db_table = "server_number_attribute" - unique_together = [["server", "attribute", "value"]] - index_together = [["attribute", "value"]] + app_label = 'serverdb' + db_table = 'server_number_attribute' + unique_together = [['server', 'attribute', 'value']] + index_together = [['attribute', 'value']] def get_value(self): - return ( - int(self.value) - if self.value.as_tuple().exponent == 0 - else float(self.value) - ) + return int(self.value) if self.value.as_tuple().exponent == 0 else float(self.value) class ServerInetAttribute(ServerAttribute): @@ -727,24 +699,22 @@ class ServerInetAttribute(ServerAttribute): Attribute, db_index=False, on_delete=models.CASCADE, - limit_choices_to=dict(type="inet"), + limit_choices_to=dict(type='inet'), ) value = netfields.InetAddressField() class Meta: - app_label = "serverdb" - db_table = "server_inet_attribute" - unique_together = [["server", "attribute", "value"]] - index_together = [["attribute", "value"]] + app_label = 'serverdb' + db_table = 'server_inet_attribute' + unique_together = [['server', 'attribute', 'value']] + index_together = [['attribute', 'value']] def clean(self): super(ServerAttribute, self).clean() if self.attribute.inet_address_family == Attribute.InetAddressFamilyChoice.IPV4: allowed_types = (IPv4Interface,) - elif ( - self.attribute.inet_address_family == Attribute.InetAddressFamilyChoice.IPV6 - ): + elif self.attribute.inet_address_family == Attribute.InetAddressFamilyChoice.IPV6: allowed_types = (IPv6Interface,) else: allowed_types = (IPv4Interface, IPv6Interface) @@ -753,29 +723,28 @@ def clean(self): self.value = inet_to_python(self.value) if type(self.value) not in allowed_types: raise ValidationError( - f"IP address {self.value} is not " - f"of type {self.attribute.get_inet_address_family_display()}!" + f'IP address {self.value} is not ' f'of type {self.attribute.get_inet_address_family_display()}!' ) # Get the ip_addr_type of the servertype ip_addr_type = self.server.servertype.ip_addr_type - if ip_addr_type == "null": + if ip_addr_type == 'null': # A Servertype with ip_addr_type "null" and attributes of type # inet must be denied per configuration. This is just a safety net # in case e.g. somebody creates them programmatically. raise ValidationError( - _("%(attribute_id)s must be null"), - code="invalid value", - params={"attribute_id": self.attribute_id}, + _('%(attribute_id)s must be null'), + code='invalid value', + params={'attribute_id': self.attribute_id}, ) - elif ip_addr_type == "host": + elif ip_addr_type == 'host': is_ip_address(self.value) - is_unique_ip(self.value, self.server, ["host"], self.attribute_id) - elif ip_addr_type == "network": + is_unique_ip(self.value, self.server, ['host'], self.attribute_id) + elif ip_addr_type == 'network': is_network(self.value) - network_overlaps(self.value, self.server, ["network"], self.attribute_id) - elif ip_addr_type == "loadbalancer": + network_overlaps(self.value, self.server, ['network'], self.attribute_id) + elif ip_addr_type == 'loadbalancer': is_ip_address(self.value) @@ -784,15 +753,15 @@ class ServerMACAddressAttribute(ServerAttribute): Attribute, db_index=False, on_delete=models.CASCADE, - limit_choices_to=dict(type="macaddr"), + limit_choices_to=dict(type='macaddr'), ) value = netfields.MACAddressField() class Meta: - app_label = "serverdb" - db_table = "server_macaddr_attribute" - unique_together = [["server", "attribute", "value"]] - index_together = [["attribute", "value"]] + app_label = 'serverdb' + db_table = 'server_macaddr_attribute' + unique_together = [['server', 'attribute', 'value']] + index_together = [['attribute', 'value']] class ServerDateAttribute(ServerAttribute): @@ -800,15 +769,15 @@ class ServerDateAttribute(ServerAttribute): Attribute, db_index=False, on_delete=models.CASCADE, - limit_choices_to=dict(type="date"), + limit_choices_to=dict(type='date'), ) value = models.DateField() class Meta: - app_label = "serverdb" - db_table = "server_date_attribute" - unique_together = [["server", "attribute", "value"]] - index_together = [["attribute", "value"]] + app_label = 'serverdb' + db_table = 'server_date_attribute' + unique_together = [['server', 'attribute', 'value']] + index_together = [['attribute', 'value']] class ServerDateTimeAttribute(ServerAttribute): @@ -816,15 +785,15 @@ class ServerDateTimeAttribute(ServerAttribute): Attribute, db_index=False, on_delete=models.CASCADE, - limit_choices_to=dict(type="datetime"), + limit_choices_to=dict(type='datetime'), ) value = models.DateTimeField() class Meta: - app_label = "serverdb" - db_table = "server_datetime_attribute" - unique_together = [["server", "attribute", "value"]] - index_together = [["attribute", "value"]] + app_label = 'serverdb' + db_table = 'server_datetime_attribute' + unique_together = [['server', 'attribute', 'value']] + index_together = [['attribute', 'value']] class ChangeCommit(models.Model): @@ -833,7 +802,7 @@ class ChangeCommit(models.Model): change_on = models.DateTimeField(default=now, db_index=True) class Meta: - app_label = "serverdb" + app_label = 'serverdb' def __str__(self): return str(self.change_on) @@ -841,9 +810,9 @@ def __str__(self): class Change(models.Model): class Type(models.TextChoices): - CREATE = "create", _("create") - CHANGE = "change", _("change") - DELETE = "delete", _("delete") + CREATE = 'create', _('create') + CHANGE = 'change', _('change') + DELETE = 'delete', _('delete') class ChangeJSONEncoder(DjangoJSONEncoder): _NETWORK_TYPES = ( @@ -877,4 +846,4 @@ def default(self, obj): commit = models.ForeignKey(ChangeCommit, on_delete=models.CASCADE) class Meta: - app_label = "serverdb" + app_label = 'serverdb' diff --git a/serveradmin/serverdb/query_committer.py b/serveradmin/serverdb/query_committer.py index 05cc4f31..a3e33f94 100644 --- a/serveradmin/serverdb/query_committer.py +++ b/serveradmin/serverdb/query_committer.py @@ -21,7 +21,8 @@ ServerAttribute, ServerRelationAttribute, ChangeCommit, - Change, ServertypeAttribute, + Change, + ServertypeAttribute, ) from serveradmin.serverdb.query_materializer import ( QueryMaterializer, @@ -56,17 +57,11 @@ def __init__(self, message, newer=None): def commit_query(created=[], changed=[], deleted=[], app=None, user=None): """The main function to commit queries""" - pre_commit.send_robust( - commit_query, created=created, changed=changed, deleted=deleted - ) + pre_commit.send_robust(commit_query, created=created, changed=changed, deleted=deleted) # TODO: Find out which attributes we actually need attribute_lookup = {a.pk: a for a in Attribute.objects.all()} - joined_attributes = { - a: None - for a - in list(attribute_lookup.values()) + list(Attribute.specials.values()) - } + joined_attributes = {a: None for a in list(attribute_lookup.values()) + list(Attribute.specials.values())} # TODO: We rely on the "protocol" that everything that creates or changes # one or more Server(s) uses this API or also acquires an exclusive @@ -117,16 +112,11 @@ def commit_query(created=[], changed=[], deleted=[], app=None, user=None): # TODO Improve this function by checking only attributes of ACLs that # have actually changed and not all. - _access_control( - user, app, unchanged_objects, - created_objects, changed_objects, deleted_objects - ) + _access_control(user, app, unchanged_objects, created_objects, changed_objects, deleted_objects) _log_changes(user, app, changed, created_objects, deleted_objects) - post_commit.send_robust( - commit_query, created=created, changed=changed, deleted=deleted - ) + post_commit.send_robust(commit_query, created=created, changed=changed, deleted=deleted) return DatasetCommit( list(created_objects.values()), @@ -139,22 +129,11 @@ def _validate(attribute_lookup, changed, changed_objects): servertype_attributes = _get_servertype_attributes(changed_objects) # Attributes must be always validated - violations_attribs = _validate_attributes( - changed, changed_objects, servertype_attributes - ) - violations_readonly = _validate_readonly( - attribute_lookup, changed, changed_objects - ) - violations_regexp = list( - _validate_regexp(changed, changed_objects, attribute_lookup) - ) - violations_required = _validate_required( - changed, changed_objects, servertype_attributes - ) - if ( - violations_attribs or violations_readonly or - violations_regexp or violations_required - ): + violations_attribs = _validate_attributes(changed, changed_objects, servertype_attributes) + violations_readonly = _validate_readonly(attribute_lookup, changed, changed_objects) + violations_regexp = list(_validate_regexp(changed, changed_objects, attribute_lookup)) + violations_required = _validate_required(changed, changed_objects, servertype_attributes) + if violations_attribs or violations_readonly or violations_regexp or violations_required: error_message = _build_error_message( violations_attribs, violations_readonly, @@ -163,10 +142,7 @@ def _validate(attribute_lookup, changed, changed_objects): ) raise CommitValidationFailed( error_message, - violations_attribs + - violations_readonly + - violations_regexp + - violations_required, + violations_attribs + violations_readonly + violations_regexp + violations_required, ) newer = _validate_commit(changed, changed_objects) @@ -179,11 +155,7 @@ def _delete_attributes(attribute_lookup, changed, changed_servers, deleted): # to avoid integrity errors. Other attributes will just go away # with the servers. if deleted: - ( - ServerRelationAttribute.objects - .filter(server_id__in=deleted) - .delete() - ) + (ServerRelationAttribute.objects.filter(server_id__in=deleted).delete()) for changes in changed: object_id = changes['object_id'] @@ -196,9 +168,7 @@ def _delete_attributes(attribute_lookup, changed, changed_servers, deleted): attribute = attribute_lookup[attribute_id] action = change['action'] - if action == 'delete' or ( - action == 'update' and change['new'] is None - ): + if action == 'delete' or (action == 'update' and change['new'] is None): server.get_attributes(attribute).delete() elif action == 'multi' and change['remove']: for server_attribute in server.get_attributes(attribute): @@ -218,8 +188,9 @@ def _delete_servers(changed, deleted, deleted_servers): server.delete() except IntegrityError as error: raise CommitError( - 'Cannot delete servers because they are referenced by {0}' - .format(', '.join(str(o) for o in error.protected_objects)) + 'Cannot delete servers because they are referenced by {0}'.format( + ', '.join(str(o) for o in error.protected_objects) + ) ) # We should ignore the changes to the deleted servers. @@ -310,8 +281,12 @@ def _upsert_attributes(attribute_lookup, changed, changed_servers): def _access_control( - user: Optional[User], app: Optional[Application], unchanged_objects: dict, - created_objects: dict, changed_objects: dict, deleted_objects: dict, + user: Optional[User], + app: Optional[Application], + unchanged_objects: dict, + created_objects: dict, + changed_objects: dict, + deleted_objects: dict, ) -> None: """Enforce serveradmin ACLs @@ -357,17 +332,13 @@ def _access_control( ): # Check app or if not present user permissions for entity_class, entity_name, groups in entities: - acl_violations = { - acl: _acl_violations(unchanged_objects, obj, acl) - for acl in groups - } + acl_violations = {acl: _acl_violations(unchanged_objects, obj, acl) for acl in groups} # If all ACLs resulted in violations, none of them allowed the edit # Build a verbose error message and abort the commit if all(acl_violations.values()): - msg = ( - 'Insufficient access rights to object "{}" for {} "{}": ' - .format(obj['hostname'], entity_class, entity_name) + msg = 'Insufficient access rights to object "{}" for {} "{}": '.format( + obj['hostname'], entity_class, entity_name ) for acl, violations in acl_violations.items(): msg += ' '.join(violations) @@ -413,9 +384,10 @@ def _acl_violations(touched_objects, pending_changes, acl): if not attribute_filter.matches(to_compare.get(attribute_id)): violations.append( - 'Object is not covered by ACL "{}", Attribute "{}" ' - 'does not match the filter "{}".'.format( - acl, attribute_id, attribute_filter, + 'Object is not covered by ACL "{}", Attribute "{}" ' 'does not match the filter "{}".'.format( + acl, + attribute_id, + attribute_filter, ) ) @@ -435,14 +407,11 @@ def _acl_violations(touched_objects, pending_changes, acl): # Check whether all changed attributes are on this ACLs attribute whitelist for attribute_id, attribute_value in pending_changes.items(): - if ( - attribute_id not in attribute_ids and - attribute_value != old_object[attribute_id] - ): + if attribute_id not in attribute_ids and attribute_value != old_object[attribute_id]: is_related_via: bool = ServertypeAttribute.objects.filter( servertype_id=pending_changes['servertype'], attribute_id=attribute_id, - related_via_attribute__isnull=False + related_via_attribute__isnull=False, ).exists() if is_related_via: # Attributes which are related via another servertype can be @@ -453,7 +422,8 @@ def _acl_violations(touched_objects, pending_changes, acl): violations.append( 'Change is not covered by ACL "{}", Attribute "{}" was ' 'modified despite not beeing whitelisted.'.format( - acl, attribute_id, + acl, + attribute_id, ) ) @@ -470,28 +440,34 @@ def _log_changes(user, app, changed, created_objects, deleted_objects): if len(updates.keys() - excl_attrs) > 1: # Get changes for attributes that should be logged. to_log = {k: v for k, v in updates.items() if k not in excl_attrs} - changes.append(Change( - object_id=updates['object_id'], - change_type=Change.Type.CHANGE, - change_json=to_log, - commit=commit, - )) + changes.append( + Change( + object_id=updates['object_id'], + change_type=Change.Type.CHANGE, + change_json=to_log, + commit=commit, + ) + ) for attributes in deleted_objects.values(): - changes.append(Change( - object_id=attributes['object_id'], - change_type=Change.Type.DELETE, - change_json=attributes, - commit=commit, - )) + changes.append( + Change( + object_id=attributes['object_id'], + change_type=Change.Type.DELETE, + change_json=attributes, + commit=commit, + ) + ) for obj in created_objects.values(): - changes.append(Change( - object_id=obj['object_id'], - change_type=Change.Type.CREATE, - change_json=obj, - commit=commit, - )) + changes.append( + Change( + object_id=obj['object_id'], + change_type=Change.Type.CREATE, + change_json=obj, + commit=commit, + ) + ) if changes: commit.save() @@ -499,11 +475,7 @@ def _log_changes(user, app, changed, created_objects, deleted_objects): def _fetch_servers(object_ids): - servers = { - s.server_id: s - for s - in Server.objects.select_for_update().filter(server_id__in=object_ids) - } + servers = {s.server_id: s for s in Server.objects.select_for_update().filter(server_id__in=object_ids)} for object_id in object_ids: if object_id in servers: continue @@ -513,10 +485,7 @@ def _fetch_servers(object_ids): def _materialize(servers, joined_attributes): - return { - o['object_id']: o - for o in QueryMaterializer(list(servers.values()), joined_attributes) - } + return {o['object_id']: o for o in QueryMaterializer(list(servers.values()), joined_attributes)} def _get_servertype_attributes(servers): @@ -548,7 +517,8 @@ def _validate_attributes(changes, servers, servertype_attributes): if ( # No such attribute. - attribute_id not in attributes or + attribute_id not in attributes + or # Attributes related via another one, cannot be changed. attributes[attribute_id].related_via_attribute ): @@ -635,9 +605,7 @@ def _validate_commit(changes, servers): return newer -def _build_error_message(violations_attribs, violations_readonly, - violations_regexp, violations_required): - +def _build_error_message(violations_attribs, violations_readonly, violations_regexp, violations_required): violation_types = [ (violations_attribs, 'Attribute not on servertype'), (violations_readonly, 'Attribute is read-only'), @@ -656,9 +624,7 @@ def _build_error_message(violations_attribs, violations_readonly, if seen: for vattr, num_affected in seen.items(): - message.append('{0}: {1} (#affected: {2})'.format( - message_type, vattr, num_affected - )) + message.append('{0}: {1} (#affected: {2})'.format(message_type, vattr, num_affected)) return '. '.join(message) @@ -676,20 +642,19 @@ def _get_real_attributes(attributes, attribute_lookup): continue attribute = attribute_lookup[attribute_id] - value_multi = ( - isinstance(value, (list, set)) or - hasattr(value, '_proxied_set') - ) + value_multi = isinstance(value, (list, set)) or hasattr(value, '_proxied_set') if attribute.multi and not value_multi: raise CommitError( - '{0} is a multi attribute, but {1} of type {2} given.' - .format(attribute, repr(value), type(value).__name__) + '{0} is a multi attribute, but {1} of type {2} given.'.format( + attribute, repr(value), type(value).__name__ + ) ) if not attribute.multi and value_multi: raise CommitError( - '{0} is not a multi attribute, but {1} of type {2} given.' - .format(attribute, repr(value), type(value).__name__) + '{0} is not a multi attribute, but {1} of type {2} given.'.format( + attribute, repr(value), type(value).__name__ + ) ) # Ignore nulls @@ -703,7 +668,7 @@ def _get_real_attributes(attributes, attribute_lookup): yield attribute, value -def _validate_real_attributes(servertype, real_attributes): # NOQA: C901 +def _validate_real_attributes(servertype, real_attributes): # NOQA: C901 violations_regexp = [] violations_required = [] servertype_attributes = set() @@ -757,7 +722,6 @@ def _validate_real_attributes(servertype, real_attributes): # NOQA: C901 def _insert_server(hostname, intern_ip, servertype, attributes): - if Server.objects.filter(hostname=hostname).exists(): raise CommitError('Server with that hostname already exists') @@ -786,15 +750,11 @@ def handle_violations( ): if violations_regexp or violations_required: if violations_regexp: - regexp_msg = 'Attributes violating regexp: {0}. '.format( - ', '.join(violations_regexp) - ) + regexp_msg = 'Attributes violating regexp: {0}. '.format(', '.join(violations_regexp)) else: regexp_msg = '' if violations_required: - required_msg = 'Attributes violating required: {0}.'.format( - ', '.join(violations_required) - ) + required_msg = 'Attributes violating required: {0}.'.format(', '.join(violations_required)) else: required_msg = '' @@ -804,8 +764,8 @@ def handle_violations( ) if violations_attribs: raise CommitError( - 'Attributes {0} are not defined on ' - 'this servertype. You can\'t skip this validation!' - .format(', '.join(violations_attribs)), + 'Attributes {0} are not defined on ' "this servertype. You can't skip this validation!".format( + ', '.join(violations_attribs) + ), violations_regexp + violations_required + violations_attribs, ) diff --git a/serveradmin/serverdb/query_executer.py b/serveradmin/serverdb/query_executer.py index d9228bb4..58abd0ab 100644 --- a/serveradmin/serverdb/query_executer.py +++ b/serveradmin/serverdb/query_executer.py @@ -7,9 +7,9 @@ from django.db import DataError, connection, transaction from adminapi.filters import Any -from serveradmin.serverdb.models import Attribute, ServertypeAttribute, Server -from serveradmin.serverdb.sql_generator import get_server_query +from serveradmin.serverdb.models import Attribute, Server, ServertypeAttribute from serveradmin.serverdb.query_materializer import QueryMaterializer +from serveradmin.serverdb.sql_generator import get_server_query def execute_query(filters, restrict, order_by): @@ -50,19 +50,12 @@ def execute_query(filters, restrict, order_by): related_vias = {} real_attribute_ids = [a for a in filters if a not in Attribute.specials] if real_attribute_ids: - servertype_attributes = list(ServertypeAttribute.objects.filter( - attribute_id__in=real_attribute_ids - )) + servertype_attributes = list(ServertypeAttribute.objects.filter(attribute_id__in=real_attribute_ids)) servertype_ids = _get_possible_servertype_ids(servertype_attributes) filters = dict(filters) servertype_ids = _override_servertype_filter(filters, servertype_ids) - servertype_attributes = [ - sa for sa in servertype_attributes - if sa.servertype_id in servertype_ids - ] - _update_related_vias( - related_vias, servertype_attributes, attribute_lookup - ) + servertype_attributes = [sa for sa in servertype_attributes if sa.servertype_id in servertype_ids] + _update_related_vias(related_vias, servertype_attributes, attribute_lookup) # Here we prepare the join dictionary for the query materializer. # For None on the restrict argument, we just use the complete list of @@ -70,11 +63,10 @@ def execute_query(filters, restrict, order_by): if restrict is None: materializer_args = [{a: None for a in attribute_lookup.values()}] else: + def cast(join): - return { - attribute_lookup[a]: j if j is None else cast(j) - for a, j in join - } + return {attribute_lookup[a]: j if j is None else cast(j) for a, j in join} + materializer_args = [cast(joins)] if order_by is not None: @@ -85,9 +77,7 @@ def cast(join): # is a query operation. Perhaps this is also enabling some optimization # on the Postgres side. with transaction.atomic(): - connection.cursor().execute( - 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY' - ) + connection.cursor().execute('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY') # The actual query execution procedure is 2 steps: first filtering # the objects, and then materializing the requested attributes. @@ -184,9 +174,7 @@ def _override_servertype_filter(filters, servertype_ids): # it ourself. This is an optimization. We could not do this, but # then we wouldn't be able to override the same filter. if 'servertype' in filters: - servertype_ids = [ - s for s in servertype_ids if filters['servertype'].matches(s) - ] + servertype_ids = [s for s in servertype_ids if filters['servertype'].matches(s)] # Here we add the servertype filter or override the existing one. filters['servertype'] = Any(*servertype_ids) @@ -194,9 +182,7 @@ def _override_servertype_filter(filters, servertype_ids): return servertype_ids -def _update_related_vias( - related_vias, servertype_attributes, attribute_lookup -): +def _update_related_vias(related_vias, servertype_attributes, attribute_lookup): """Prepare the related_vias dictionary for the SQL generator module It is lists in dictionaries of dictionaries indexed first by attribute_id @@ -216,12 +202,7 @@ def _update_related_vias( else: related_via_attribute = attribute_lookup[related_via_attribute_id] - ( - related_vias - .setdefault(sa.attribute_id, {}) - .setdefault(related_via_attribute, []) - .append(sa.servertype_id) - ) + (related_vias.setdefault(sa.attribute_id, {}).setdefault(related_via_attribute, []).append(sa.servertype_id)) if to_be_looked_up: _update_attribute_lookup( @@ -239,7 +220,6 @@ def _get_servers(filters, attribute_lookup, related_vias): # the properties of the attributes. attribute_filters = [] for attribute_id, filt in filters.items(): - # Before we actually execute the query, we can check the destiny of # the filters. If one is destined to fail, we can just return empty # result. If some are destined to pass, we can just remove them. diff --git a/serveradmin/serverdb/signals.py b/serveradmin/serverdb/signals.py index 25351e6e..d3e4d531 100644 --- a/serveradmin/serverdb/signals.py +++ b/serveradmin/serverdb/signals.py @@ -1,6 +1,4 @@ from django.dispatch import Signal - pre_commit = Signal() post_commit = Signal() - diff --git a/serveradmin/serverdb/tests/test_acls.py b/serveradmin/serverdb/tests/test_acls.py index 7e707ca9..f8aea065 100644 --- a/serveradmin/serverdb/tests/test_acls.py +++ b/serveradmin/serverdb/tests/test_acls.py @@ -65,9 +65,7 @@ def test_deny_if_app_acl_does_not_cover_object(self): changed_objects = {changed_object['object_id']: changed_object} with self.assertRaises(PermissionDenied) as error: - query_committer._access_control( - None, app, unchanged_objects, {}, changed_objects, {} - ) + query_committer._access_control(None, app, unchanged_objects, {}, changed_objects, {}) self.assertEqual( 'Insufficient access rights to object "test0" for application ' '"superuser test": Object is not covered by ACL "app test", ' @@ -91,9 +89,7 @@ def test_deny_if_user_acl_does_not_cover_object(self): changed_objects = {changed_object['object_id']: changed_object} with self.assertRaises(PermissionDenied) as error: - query_committer._access_control( - user, None, unchanged_objects, {}, changed_objects, {} - ) + query_committer._access_control(user, None, unchanged_objects, {}, changed_objects, {}) self.assertEqual( 'Insufficient access rights to object "test0" for user ' '"hannah.acker": Object is not covered by ACL "app test", ' @@ -110,50 +106,34 @@ def test_permit_if_app_acl_covers_object(self): owner=user, location='test', ) - acl = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=False - ) + acl = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=False) acl.applications.add(app) acl.save() - unchanged_object = Query( - {'object_id': 1}, ['os', 'hostname', 'servertype'] - ).get() + unchanged_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} changed_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() changed_object['os'] = 'bookworm' changed_objects = {changed_object['object_id']: changed_object} - self.assertIsNone( - query_committer._access_control( - None, app, unchanged_objects, {}, changed_objects, {} - ) - ) + self.assertIsNone(query_committer._access_control(None, app, unchanged_objects, {}, changed_objects, {})) def test_permit_if_user_acl_covers_object(self): user = User.objects.first() user.is_superuser = False - acl = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=False - ) + acl = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=False) acl.members.add(user) acl.save() - unchanged_object = Query( - {'object_id': 1}, ['os', 'hostname', 'servertype'] - ).get() + unchanged_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} changed_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() changed_object['os'] = 'bookworm' changed_objects = {changed_object['object_id']: changed_object} - self.assertIsNone( - query_committer._access_control( - user, None, unchanged_objects, {}, changed_objects, {} - ) - ) + self.assertIsNone(query_committer._access_control(user, None, unchanged_objects, {}, changed_objects, {})) def test_deny_if_app_acl_whitelist_does_not_list_attribute(self): user = User.objects.first() @@ -164,15 +144,11 @@ def test_deny_if_app_acl_whitelist_does_not_list_attribute(self): owner=user, location='test', ) - acl = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=True - ) + acl = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=True) acl.applications.add(app) acl.save() - unchanged_object = Query( - {'object_id': 1}, ['os', 'hostname', 'servertype'] - ).get() + unchanged_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} changed_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() @@ -180,9 +156,7 @@ def test_deny_if_app_acl_whitelist_does_not_list_attribute(self): changed_objects = {changed_object['object_id']: changed_object} with self.assertRaises(PermissionDenied) as error: - query_committer._access_control( - None, app, unchanged_objects, {}, changed_objects, {} - ) + query_committer._access_control(None, app, unchanged_objects, {}, changed_objects, {}) self.assertEqual( 'Insufficient access rights to object "test0" for application ' '"superuser test": Change is not covered by ACL "app test", ' @@ -194,15 +168,11 @@ def test_deny_if_user_acl_whitelist_does_not_list_attribute(self): user = User.objects.first() user.is_superuser = False - acl = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=True - ) + acl = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=True) acl.members.add(user) acl.save() - unchanged_object = Query( - {'object_id': 1}, ['os', 'hostname', 'servertype'] - ).get() + unchanged_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} changed_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() @@ -210,9 +180,7 @@ def test_deny_if_user_acl_whitelist_does_not_list_attribute(self): changed_objects = {changed_object['object_id']: changed_object} with self.assertRaises(PermissionDenied) as error: - query_committer._access_control( - user, None, unchanged_objects, {}, changed_objects, {} - ) + query_committer._access_control(user, None, unchanged_objects, {}, changed_objects, {}) self.assertEqual( 'Insufficient access rights to object "test0" for user ' '"hannah.acker": Change is not covered by ACL "app test", ' @@ -229,52 +197,36 @@ def test_permit_if_app_acl_whitelist_lists_attribute(self): owner=user, location='test', ) - acl = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=True - ) + acl = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=True) acl.applications.add(app) acl.attributes.add(Attribute.objects.get(attribute_id='os')) acl.save() - unchanged_object = Query( - {'object_id': 1}, ['os', 'hostname', 'servertype'] - ).get() + unchanged_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} changed_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() changed_object['os'] = 'bookworm' changed_objects = {changed_object['object_id']: changed_object} - self.assertIsNone( - query_committer._access_control( - None, app, unchanged_objects, {}, changed_objects, {} - ) - ) + self.assertIsNone(query_committer._access_control(None, app, unchanged_objects, {}, changed_objects, {})) def test_permit_if_user_acl_whitelist_lists_attribute(self): user = User.objects.first() user.is_superuser = False - acl = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=True - ) + acl = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=True) acl.members.add(user) acl.attributes.add(Attribute.objects.get(attribute_id='os')) acl.save() - unchanged_object = Query( - {'object_id': 1}, ['os', 'hostname', 'servertype'] - ).get() + unchanged_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} changed_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() changed_object['os'] = 'bookworm' changed_objects = {changed_object['object_id']: changed_object} - self.assertIsNone( - query_committer._access_control( - user, None, unchanged_objects, {}, changed_objects, {} - ) - ) + self.assertIsNone(query_committer._access_control(user, None, unchanged_objects, {}, changed_objects, {})) def test_deny_if_app_acl_blacklist_lists_attribute(self): user = User.objects.first() @@ -285,16 +237,12 @@ def test_deny_if_app_acl_blacklist_lists_attribute(self): owner=user, location='test', ) - acl = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=False - ) + acl = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=False) acl.applications.add(app) acl.attributes.add(Attribute.objects.get(attribute_id='os')) acl.save() - unchanged_object = Query( - {'object_id': 1}, ['os', 'hostname', 'servertype'] - ).get() + unchanged_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} changed_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() @@ -302,9 +250,7 @@ def test_deny_if_app_acl_blacklist_lists_attribute(self): changed_objects = {changed_object['object_id']: changed_object} with self.assertRaises(PermissionDenied) as error: - query_committer._access_control( - None, app, unchanged_objects, {}, changed_objects, {} - ) + query_committer._access_control(None, app, unchanged_objects, {}, changed_objects, {}) self.assertEqual( 'Insufficient access rights to object "test0" for application ' '"superuser test": Change is not covered by ACL "app test", ' @@ -315,16 +261,12 @@ def test_deny_if_app_acl_blacklist_lists_attribute(self): def test_deny_if_user_acl_blacklist_lists_attribute(self): user = User.objects.first() user.is_superuser = False - acl = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=False - ) + acl = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=False) acl.members.add(user) acl.attributes.add(Attribute.objects.get(attribute_id='os')) acl.save() - unchanged_object = Query( - {'object_id': 1}, ['os', 'hostname', 'servertype'] - ).get() + unchanged_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} changed_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() @@ -332,9 +274,7 @@ def test_deny_if_user_acl_blacklist_lists_attribute(self): changed_objects = {changed_object['object_id']: changed_object} with self.assertRaises(PermissionDenied) as error: - query_committer._access_control( - user, None, unchanged_objects, {}, changed_objects, {} - ) + query_committer._access_control(user, None, unchanged_objects, {}, changed_objects, {}) self.assertEqual( 'Insufficient access rights to object "test0" for user ' '"hannah.acker": Change is not covered by ACL "app test", ' @@ -351,50 +291,34 @@ def test_permit_if_app_acl_blacklist_misses_attribute(self): owner=user, location='test', ) - acl = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=False - ) + acl = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=False) acl.applications.add(app) acl.save() - unchanged_object = Query( - {'object_id': 1}, ['os', 'hostname', 'servertype'] - ).get() + unchanged_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} changed_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() changed_object['os'] = 'bookworm' changed_objects = {changed_object['object_id']: changed_object} - self.assertIsNone( - query_committer._access_control( - None, app, unchanged_objects, {}, changed_objects, {} - ) - ) + self.assertIsNone(query_committer._access_control(None, app, unchanged_objects, {}, changed_objects, {})) def test_permit_if_user_acl_blacklist_misses_attribute(self): user = User.objects.first() user.is_superuser = False - acl = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=False - ) + acl = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=False) acl.members.add(user) acl.save() - unchanged_object = Query( - {'object_id': 1}, ['os', 'hostname', 'servertype'] - ).get() + unchanged_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} changed_object = Query({'object_id': 1}, ['os', 'hostname', 'servertype']).get() changed_object['os'] = 'bookworm' changed_objects = {changed_object['object_id']: changed_object} - self.assertIsNone( - query_committer._access_control( - user, None, unchanged_objects, {}, changed_objects, {} - ) - ) + self.assertIsNone(query_committer._access_control(user, None, unchanged_objects, {}, changed_objects, {})) def test_deny_if_multiple_app_acls_cover_one_object_change_set(self): # One ACL must cover all changes made to one object. Changes to one @@ -409,36 +333,26 @@ def test_deny_if_multiple_app_acls_cover_one_object_change_set(self): location='test', ) - acl_1 = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=True - ) + acl_1 = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=True) acl_1.applications.add(app) acl_1.attributes.add(Attribute.objects.get(attribute_id='os')) acl_1.save() - acl_2 = AccessControlGroup.objects.create( - name='app test 2', query='servertype=test0', is_whitelist=True - ) + acl_2 = AccessControlGroup.objects.create(name='app test 2', query='servertype=test0', is_whitelist=True) acl_2.applications.add(app) acl_2.attributes.add(Attribute.objects.get(attribute_id='database')) acl_2.save() - unchanged_object = Query( - {'object_id': 1}, ['os', 'database', 'hostname', 'servertype'] - ).get() + unchanged_object = Query({'object_id': 1}, ['os', 'database', 'hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} - changed_object = Query( - {'object_id': 1}, ['os', 'database', 'hostname', 'servertype'] - ).get() + changed_object = Query({'object_id': 1}, ['os', 'database', 'hostname', 'servertype']).get() changed_object['os'] = 'bookworm' changed_object['database'] = 'bingo' changed_objects = {changed_object['object_id']: changed_object} with self.assertRaises(PermissionDenied) as error: - query_committer._access_control( - None, app, unchanged_objects, {}, changed_objects, {} - ) + query_committer._access_control(None, app, unchanged_objects, {}, changed_objects, {}) self.assertEqual( 'Insufficient access rights to object "test0" for application ' '"superuser test": Change is not covered by ACL "app test", ' @@ -455,36 +369,26 @@ def test_deny_if_multiple_user_acls_cover_one_object_change_set(self): user = User.objects.first() user.is_superuser = False - acl_1 = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=True - ) + acl_1 = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=True) acl_1.members.add(user) acl_1.attributes.add(Attribute.objects.get(attribute_id='os')) acl_1.save() - acl_2 = AccessControlGroup.objects.create( - name='app test 2', query='servertype=test0', is_whitelist=True - ) + acl_2 = AccessControlGroup.objects.create(name='app test 2', query='servertype=test0', is_whitelist=True) acl_1.members.add(user) acl_2.attributes.add(Attribute.objects.get(attribute_id='database')) acl_2.save() - unchanged_object = Query( - {'object_id': 1}, ['os', 'database', 'hostname', 'servertype'] - ).get() + unchanged_object = Query({'object_id': 1}, ['os', 'database', 'hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} - changed_object = Query( - {'object_id': 1}, ['os', 'database', 'hostname', 'servertype'] - ).get() + changed_object = Query({'object_id': 1}, ['os', 'database', 'hostname', 'servertype']).get() changed_object['os'] = 'bookworm' changed_object['database'] = 'bingo' changed_objects = {changed_object['object_id']: changed_object} with self.assertRaises(PermissionDenied) as error: - query_committer._access_control( - user, None, unchanged_objects, {}, changed_objects, {} - ) + query_committer._access_control(user, None, unchanged_objects, {}, changed_objects, {}) self.assertEqual( 'Insufficient access rights to object "test0" for user ' '"hannah.acker": Change is not covered by ACL "app test", ' @@ -501,24 +405,16 @@ def test_hijack_objects_not_possible(self): user = User.objects.first() user.is_superuser = False - acl = AccessControlGroup.objects.create( - name='app test', query='servertype=test0', is_whitelist=False - ) + acl = AccessControlGroup.objects.create(name='app test', query='servertype=test0', is_whitelist=False) acl.members.add(user) acl.save() - unchanged_object = Query( - {'hostname': 'test2', 'servertype': 'test2'}, ['hostname', 'servertype'] - ).get() + unchanged_object = Query({'hostname': 'test2', 'servertype': 'test2'}, ['hostname', 'servertype']).get() unchanged_objects = {unchanged_object['object_id']: unchanged_object} - changed_object = Query( - {'hostname': 'test2', 'servertype': 'test2'}, ['hostname', 'servertype'] - ).get() + changed_object = Query({'hostname': 'test2', 'servertype': 'test2'}, ['hostname', 'servertype']).get() changed_object['servertype'] = 'test0' # Attacker attempts to hijack object changed_objects = {changed_object['object_id']: changed_object} with self.assertRaises(PermissionDenied) as error: - query_committer._access_control( - user, None, unchanged_objects, {}, changed_objects, {} - ) + query_committer._access_control(user, None, unchanged_objects, {}, changed_objects, {}) diff --git a/serveradmin/serverdb/tests/test_attribute.py b/serveradmin/serverdb/tests/test_attribute.py index 715cf738..4d5fbd30 100644 --- a/serveradmin/serverdb/tests/test_attribute.py +++ b/serveradmin/serverdb/tests/test_attribute.py @@ -19,7 +19,7 @@ def setUp(self): def test_attribute_history_is_logged(self): project = Query().new_object('project') project['hostname'] = self.faker.hostname() - project['owner'] = 'john.doe' # Attribute with history enabled + project['owner'] = 'john.doe' # Attribute with history enabled project.commit(user=User.objects.first()) projects = Query({'hostname': project['hostname']}, ['owner']) @@ -28,7 +28,10 @@ def test_attribute_history_is_logged(self): oid = projects.get()['object_id'] change = Change.objects.last() - self.assertEqual(change.change_json, {"owner": {"new": "max.mustermann", "old": "john.doe", "action": "update"}, "object_id": oid}) + self.assertEqual( + change.change_json, + {'owner': {'new': 'max.mustermann', 'old': 'john.doe', 'action': 'update'}, 'object_id': oid}, + ) def test_attribute_history_is_not_logged(self): project = Query().new_object('project') @@ -56,4 +59,7 @@ def test_only_required_attribute_history_is_logged(self): oid = projects.get()['object_id'] change = Change.objects.last() - self.assertEqual(change.change_json, {"owner": {"new": "max.mustermann", "old": "john.doe", "action": "update"}, "object_id": oid}) + self.assertEqual( + change.change_json, + {'owner': {'new': 'max.mustermann', 'old': 'john.doe', 'action': 'update'}, 'object_id': oid}, + ) diff --git a/serveradmin/serverdb/tests/test_views.py b/serveradmin/serverdb/tests/test_views.py index 039dc1c9..9f54bc07 100644 --- a/serveradmin/serverdb/tests/test_views.py +++ b/serveradmin/serverdb/tests/test_views.py @@ -27,10 +27,8 @@ def test_recreate_succeeds(self): vm.delete() vm.commit(user=User.objects.first()) - change_id = Change.objects.filter( - object_id=object_id, change_type=Change.Type.DELETE).first().id - response = self.client.get( - f'/serverdb/recreate/{change_id}', follow=True) + change_id = Change.objects.filter(object_id=object_id, change_type=Change.Type.DELETE).first().id + response = self.client.get(f'/serverdb/recreate/{change_id}', follow=True) # recreate view should have created the object again and redirect us # to the history of it. @@ -54,10 +52,8 @@ def test_recreate_fails_if_hostname_exists(self): vm['intern_ip'] = IPAddress('10.0.0.2') vm.commit(user=User.objects.first()) - change_id = Change.objects.filter( - object_id=object_id, change_type=Change.Type.DELETE).first().id - response = self.client.get( - f'/serverdb/recreate/{change_id}', follow=True) + change_id = Change.objects.filter(object_id=object_id, change_type=Change.Type.DELETE).first().id + response = self.client.get(f'/serverdb/recreate/{change_id}', follow=True) # Restore should have failed as there is already an object with that # hostname (again) and redirect us to changes view and display an diff --git a/serveradmin/serverdb/urls.py b/serveradmin/serverdb/urls.py index 303c1b0a..c31bd876 100644 --- a/serveradmin/serverdb/urls.py +++ b/serveradmin/serverdb/urls.py @@ -5,7 +5,7 @@ from django.urls import path -from serveradmin.serverdb.views import changes, recreate, history +from serveradmin.serverdb.views import changes, history, recreate urlpatterns = [ path('changes', changes, name='serverdb_changes'), diff --git a/serveradmin/serverdb/views.py b/serveradmin/serverdb/views.py index 3825ec9d..2d6c480f 100644 --- a/serveradmin/serverdb/views.py +++ b/serveradmin/serverdb/views.py @@ -30,9 +30,7 @@ @login_required def changes(request): commits = ChangeCommit.objects.all().order_by('-change_on') - date_settings = { - 'TIMEZONE': settings.TIME_ZONE, 'RETURN_AS_TIMEZONE_AWARE': True - } + date_settings = {'TIMEZONE': settings.TIME_ZONE, 'RETURN_AS_TIMEZONE_AWARE': True} f_commit = request.GET.get('commit_id') if f_commit: @@ -51,10 +49,11 @@ def changes(request): f_hostname = request.GET.get('hostname') if f_hostname: # Display all changes that have or had this hostname - object_ids = set(Change.objects.filter( - change_type__in=[Change.Type.CREATE, Change.Type.DELETE], - change_json__hostname=f_hostname).values_list( - 'change_json__object_id', flat=True)) + object_ids = set( + Change.objects.filter( + change_type__in=[Change.Type.CREATE, Change.Type.DELETE], change_json__hostname=f_hostname + ).values_list('change_json__object_id', flat=True) + ) commits = commits.filter(change__object_id__in=object_ids) f_object_id = request.GET.get('object_id') @@ -63,30 +62,33 @@ def changes(request): f_user_or_app = request.GET.get('user_or_app') if f_user_or_app: - commits = commits.filter( - Q(app__name=f_user_or_app) | Q(user__username=f_user_or_app)) + commits = commits.filter(Q(app__name=f_user_or_app) | Q(user__username=f_user_or_app)) commits = commits.select_related('app', 'user') # This complex statement is just here to be able to prefetch the changes' # relation including the hostname fetched either from the server table # or from the change entry where the object was deleted. - server_hostname = Server.objects.filter( - server_id=OuterRef('object_id')).values('hostname') + server_hostname = Server.objects.filter(server_id=OuterRef('object_id')).values('hostname') # Workaround: In previous versions of Serveradmin restoring objects with # the same id was possible, so we can end up with objects being deleted # multiple times. We only take the latest into account. - change_hostname = Change.objects.filter( - object_id=OuterRef('object_id'), - change_type=Change.Type.DELETE).values('change_json').order_by('-id')[:1] - commits = commits.prefetch_related(Prefetch( - 'change_set', - queryset=Change.objects.all().annotate(hostname=Coalesce( - Subquery(server_hostname), - Cast( - KeyTextTransform('hostname', Subquery(change_hostname)), - output_field=CharField()) - )))) + change_hostname = ( + Change.objects.filter(object_id=OuterRef('object_id'), change_type=Change.Type.DELETE) + .values('change_json') + .order_by('-id')[:1] + ) + commits = commits.prefetch_related( + Prefetch( + 'change_set', + queryset=Change.objects.all().annotate( + hostname=Coalesce( + Subquery(server_hostname), + Cast(KeyTextTransform('hostname', Subquery(change_hostname)), output_field=CharField()), + ) + ), + ) + ) class NoCountPaginator(Paginator): @cached_property @@ -100,15 +102,19 @@ def count(self): if len(page.object_list) == 0: page = paginator.get_page(1) - return TemplateResponse(request, 'serverdb/changes.html', { - 'commits': page, - 'from': f_from, - 'until': f_until, - 'hostname': f_hostname, - 'object_id': f_object_id, - 'commit_id': f_commit, - 'user_or_app': f_user_or_app, - }) + return TemplateResponse( + request, + 'serverdb/changes.html', + { + 'commits': page, + 'from': f_from, + 'until': f_until, + 'hostname': f_hostname, + 'object_id': f_object_id, + 'commit_id': f_commit, + 'user_or_app': f_user_or_app, + }, + ) @login_required @@ -120,15 +126,12 @@ def history(request): query = Q(hostname=request.GET['hostname']) error_text = f'hostname {request.GET["hostname"]}' else: - return HttpResponseBadRequest( - 'object_id or hostname parameter is mandatory') + return HttpResponseBadRequest('object_id or hostname parameter is mandatory') try: server = Server.objects.get(query) except Server.DoesNotExist: - messages.error( - request, - f'Object with {error_text} does not or no longer exist.') + messages.error(request, f'Object with {error_text} does not or no longer exist.') return redirect(reverse('serverdb_changes')) obj_history = Change.objects.filter(object_id=server.server_id) @@ -148,20 +151,25 @@ def history(request): pager = Paginator(obj_history, 25) page_obj = pager.get_page(page) - no_history_attributes = ServertypeAttribute.objects.filter( - servertype_id=server.servertype_id - ).select_related('attribute').filter( - attribute__history=False - ).only('attribute_id') - - return TemplateResponse(request, 'serverdb/history.html', { - 'changes': page_obj, - 'commit_id': commit_id, - 'object_id': server.server_id, - 'name': server.hostname, - 'attribute_filter': attribute_filter, - 'no_history_attributes': no_history_attributes, - }) + no_history_attributes = ( + ServertypeAttribute.objects.filter(servertype_id=server.servertype_id) + .select_related('attribute') + .filter(attribute__history=False) + .only('attribute_id') + ) + + return TemplateResponse( + request, + 'serverdb/history.html', + { + 'changes': page_obj, + 'commit_id': commit_id, + 'object_id': server.server_id, + 'name': server.hostname, + 'attribute_filter': attribute_filter, + 'no_history_attributes': no_history_attributes, + }, + ) @login_required @@ -174,8 +182,7 @@ def recreate(request, change_id): servertype_id = server_object['servertype'] exclude = ServertypeAttribute.objects.filter(servertype_id=servertype_id) exclude = exclude.filter( - ~Q(related_via_attribute=None) | - Q(attribute__type__in=['supernet', 'domain', 'reverse']) + ~Q(related_via_attribute=None) | Q(attribute__type__in=['supernet', 'domain', 'reverse']) ).values_list('attribute_id', flat=True) for attribute_id in exclude: diff --git a/serveradmin/servershell/__init__.py b/serveradmin/servershell/__init__.py index 11357d91..eeaaf88f 100644 --- a/serveradmin/servershell/__init__.py +++ b/serveradmin/servershell/__init__.py @@ -2,4 +2,3 @@ Copyright (c) 2019 InnoGames GmbH """ - diff --git a/serveradmin/servershell/helper/__init__.py b/serveradmin/servershell/helper/__init__.py index 3f2648f2..0aa7b05b 100644 --- a/serveradmin/servershell/helper/__init__.py +++ b/serveradmin/servershell/helper/__init__.py @@ -9,9 +9,12 @@ def get_default_shown_attributes(): shown_attributes = list(Attribute.specials.keys()) shown_attributes.remove('object_id') - default_attributes = ServertypeAttribute.objects.filter( - default_visible=True).only('attribute_id').order_by( - 'attribute_id').distinct('attribute_id') + default_attributes = ( + ServertypeAttribute.objects.filter(default_visible=True) + .only('attribute_id') + .order_by('attribute_id') + .distinct('attribute_id') + ) shown_attributes.extend([attr.attribute_id for attr in default_attributes]) shown_attributes.sort() diff --git a/serveradmin/servershell/helper/autocomplete.py b/serveradmin/servershell/helper/autocomplete.py index 0316cc94..51c63ff5 100644 --- a/serveradmin/servershell/helper/autocomplete.py +++ b/serveradmin/servershell/helper/autocomplete.py @@ -1,7 +1,6 @@ -from django.db import connection, ProgrammingError +from django.db import ProgrammingError, connection -from serveradmin.serverdb.models import Attribute, ServerAttribute, Server -from django.core.exceptions import ObjectDoesNotExist +from serveradmin.serverdb.models import Attribute, Server, ServerAttribute def attribute_startswith(search_string, limit=20): @@ -13,9 +12,9 @@ def attribute_startswith(search_string, limit=20): :return: """ - query = Attribute.objects.filter( - attribute_id__startswith=search_string).only('attribute_id').order_by( - 'attribute_id') + query = ( + Attribute.objects.filter(attribute_id__startswith=search_string).only('attribute_id').order_by('attribute_id') + ) attributes = [attribute.attribute_id for attribute in query[:limit]] for attribute in Attribute.specials.keys(): @@ -53,8 +52,9 @@ def _specials_value_startswith(attribute_id, search_string, limit=20): with connection.cursor() as cursor: # This is safe because field_name comes from us - sql = "SELECT DISTINCT {} FROM server WHERE {} LIKE %s ORDER BY {} ASC LIMIT {}".format( - column_name, column_name, column_name, limit) + sql = 'SELECT DISTINCT {} FROM server WHERE {} LIKE %s ORDER BY {} ASC LIMIT {}'.format( + column_name, column_name, column_name, limit + ) # This MUST be escaped to prevent SQL injection try: cursor.execute(sql, [search_string + '%']) @@ -85,14 +85,21 @@ def _value_startswith(attribute_id, search_string, limit=20): return [] if attribute.type == 'relation': - query = Server.objects.filter(servertype_id=attribute_id).filter( - hostname__startswith=search_string).only('hostname').order_by( - 'hostname') + query = ( + Server.objects.filter(servertype_id=attribute_id) + .filter(hostname__startswith=search_string) + .only('hostname') + .order_by('hostname') + ) return [server.hostname for server in query[:limit]] if attribute.type == 'boolean': return ['true', 'false'] - query = attribute_model.objects.filter(attribute_id=attribute_id).filter( - value__startswith=search_string).only('value').distinct( - 'value').order_by('value') + query = ( + attribute_model.objects.filter(attribute_id=attribute_id) + .filter(value__startswith=search_string) + .only('value') + .distinct('value') + .order_by('value') + ) return [attr.value for attr in query[:limit]] diff --git a/serveradmin/servershell/merged_query_iterator.py b/serveradmin/servershell/merged_query_iterator.py index 198d0d10..3438e69c 100644 --- a/serveradmin/servershell/merged_query_iterator.py +++ b/serveradmin/servershell/merged_query_iterator.py @@ -3,6 +3,7 @@ class MergedQuery: Holds an arbitrary amount of serveradmin queries that can be used as a single iteratable object. """ + queries = [] def __init__(self, queries): @@ -17,6 +18,7 @@ class MergedQueryIterator: Iterates over each query to retrieve the server's data. Avoids duplicate items by saving already iterated server-ids. """ + served_ids = [] queries = [] current_query = 0 diff --git a/serveradmin/servershell/templatetags/serversearch.py b/serveradmin/servershell/templatetags/serversearch.py index ff850edc..bfa51b66 100644 --- a/serveradmin/servershell/templatetags/serversearch.py +++ b/serveradmin/servershell/templatetags/serversearch.py @@ -22,14 +22,16 @@ def serversearch_js(search_id): return { 'servertypes_json': dumps({s.servertype_id: {} for s in servertypes}), - 'attributes_json': dumps({ - a.attribute_id: { - 'multi': a.multi, - 'type': a.type, - 'regexp': a.regexp, + 'attributes_json': dumps( + { + a.attribute_id: { + 'multi': a.multi, + 'type': a.type, + 'regexp': a.regexp, + } + for a in attributes } - for a in attributes - }), + ), 'filters_json': dumps([f.__name__ for f in filter_classes]), 'search_id': search_id, 'STATIC_URL': settings.STATIC_URL, diff --git a/serveradmin/servershell/templatetags/servershell.py b/serveradmin/servershell/templatetags/servershell.py index 337b393a..c33a09e2 100644 --- a/serveradmin/servershell/templatetags/servershell.py +++ b/serveradmin/servershell/templatetags/servershell.py @@ -1,8 +1,8 @@ from datetime import timezone from django import template -from django.utils.safestring import mark_safe from django.utils.html import escape +from django.utils.safestring import mark_safe register = template.Library() diff --git a/serveradmin/servershell/urls.py b/serveradmin/servershell/urls.py index 189082f3..a168d0ac 100644 --- a/serveradmin/servershell/urls.py +++ b/serveradmin/servershell/urls.py @@ -7,19 +7,19 @@ from django.views.generic.base import TemplateView from serveradmin.servershell.views import ( - index, autocomplete, - get_results, + choose_ip_addr, + clone_object, + commit, + diff, edit, + get_results, + index, inspect, - commit, new_object, - clone_object, - choose_ip_addr, - settings, diff, + settings, ) - urlpatterns = [ path('', index, name='servershell_index'), path('autocomplete', autocomplete, name='servershell_autocomplete'), diff --git a/serveradmin/servershell/utils.py b/serveradmin/servershell/utils.py index 114b1a79..022ec223 100644 --- a/serveradmin/servershell/utils.py +++ b/serveradmin/servershell/utils.py @@ -12,9 +12,9 @@ def servershell_plugins(): @return: """ js_files = list() - app_names = [app.name for app in apps.get_app_configs() if app.name.startswith("serveradmin_")] + app_names = [app.name for app in apps.get_app_configs() if app.name.startswith('serveradmin_')] for app_name in app_names: - path = f"js/{app_name}.servershell.plugin.js" + path = f'js/{app_name}.servershell.plugin.js' js_file = finders.find(path) if js_file: js_files.append(path) diff --git a/serveradmin/servershell/views.py b/serveradmin/servershell/views.py index fea02c0e..33a2dbc7 100644 --- a/serveradmin/servershell/views.py +++ b/serveradmin/servershell/views.py @@ -10,18 +10,15 @@ from django.contrib import messages from django.contrib.auth.decorators import login_required -from django.core.exceptions import ( - ObjectDoesNotExist, - PermissionDenied, - ValidationError -) +from django.core.exceptions import ObjectDoesNotExist, PermissionDenied, ValidationError from django.http import ( HttpResponse, HttpResponseRedirect, Http404, JsonResponse, HttpResponseBadRequest, - HttpResponseNotFound, HttpRequest + HttpResponseNotFound, + HttpRequest, ) from django.shortcuts import redirect, render from django.template.response import TemplateResponse @@ -35,12 +32,7 @@ from adminapi.parse import parse_query from adminapi.request import json_encode_extra from serveradmin.dataset import Query -from serveradmin.serverdb.models import ( - Servertype, - Attribute, - ServertypeAttribute, - Server -) +from serveradmin.serverdb.models import Servertype, Attribute, ServertypeAttribute, Server from serveradmin.serverdb.query_committer import commit_query from serveradmin.servershell.helper import get_default_shown_attributes from serveradmin.servershell.merged_query_iterator import MergedQuery @@ -64,19 +56,20 @@ def index(request): attributes.extend(Attribute.specials.values()) attributes_json = list() for attribute in attributes: - attributes_json.append({ - 'attribute_id': attribute.attribute_id, - 'type': attribute.type, - 'multi': attribute.multi, - 'hovertext': attribute.hovertext, - 'help_link': attribute.help_link, - 'group': attribute.group, - 'regex': ( - # XXX: HTML5 input patterns do not support these - None if not attribute.regexp else - attribute.regexp.replace('\\A', '^').replace('\\Z', '$') - ), - }) + attributes_json.append( + { + 'attribute_id': attribute.attribute_id, + 'type': attribute.type, + 'multi': attribute.multi, + 'hovertext': attribute.hovertext, + 'help_link': attribute.help_link, + 'group': attribute.group, + 'regex': ( + # XXX: HTML5 input patterns do not support these + None if not attribute.regexp else attribute.regexp.replace('\\A', '^').replace('\\Z', '$') + ), + } + ) attributes_json.sort(key=lambda attr: attr['group']) # Load user search settings or set default values @@ -87,24 +80,27 @@ def index(request): shown_attributes = request.GET.getlist('shown_attributes[]') if not shown_attributes: if search_settings['save_attributes']: - shown_attributes = request.session.setdefault( - 'shown_attributes', get_default_shown_attributes()) + shown_attributes = request.session.setdefault('shown_attributes', get_default_shown_attributes()) else: shown_attributes = get_default_shown_attributes() - return TemplateResponse(request, 'servershell/index.html', { - 'term': request.GET.get('term', request.session.get('term')), - 'shown_attributes': shown_attributes, - 'deep_link': bool(strtobool(request.GET.get('deep_link', 'false'))), - 'attributes': attributes_json, - 'servertypes': list(Servertype.objects.values_list('servertype_id', flat=True)), - 'offset': 0, - 'limit': request.session.get('limit', NUM_SERVERS_DEFAULT), - 'order_by': 'hostname', - 'filters': sorted([(f.__name__, f.__doc__) for f in filter_classes]), - 'search_settings': search_settings, - 'servershell_plugins': servershell_plugins(), - }) + return TemplateResponse( + request, + 'servershell/index.html', + { + 'term': request.GET.get('term', request.session.get('term')), + 'shown_attributes': shown_attributes, + 'deep_link': bool(strtobool(request.GET.get('deep_link', 'false'))), + 'attributes': attributes_json, + 'servertypes': list(Servertype.objects.values_list('servertype_id', flat=True)), + 'offset': 0, + 'limit': request.session.get('limit', NUM_SERVERS_DEFAULT), + 'order_by': 'hostname', + 'filters': sorted([(f.__name__, f.__doc__) for f in filter_classes]), + 'search_settings': search_settings, + 'servershell_plugins': servershell_plugins(), + }, + ) @login_required @@ -113,18 +109,15 @@ def autocomplete(request): if hostname: try: - query = Server.objects.filter(hostname__startswith=hostname).only( - 'hostname').order_by('hostname') - autocomplete_list = [server.hostname for server in - query[:AUTOCOMPLETE_LIMIT]] + query = Server.objects.filter(hostname__startswith=hostname).only('hostname').order_by('hostname') + autocomplete_list = [server.hostname for server in query[:AUTOCOMPLETE_LIMIT]] except (DatatypeError, ValidationError): # If there is no valid query, just don't auto-complete autocomplete_list = list() else: autocomplete_list = list() - return HttpResponse(json.dumps({'autocomplete': autocomplete_list}), - content_type='application/x-json') + return HttpResponse(json.dumps({'autocomplete': autocomplete_list}), content_type='application/x-json') @login_required @@ -158,20 +151,19 @@ def get_results(request): restrict.append('servertype') main_query = Query(parse_query(term), restrict, order_by) - merged_query = MergedQuery([ - Query({'object_id': Any(*pinned)}, restrict), - main_query, - ]) + merged_query = MergedQuery( + [ + Query({'object_id': Any(*pinned)}, restrict), + main_query, + ] + ) # TODO: Using len is terribly slow for large datasets because it has # to query all objects but we cannot use count which is available on # Django QuerySet num_servers = len(list(merged_query)) except (DatatypeError, ObjectDoesNotExist, ValidationError) as error: - return HttpResponse(json.dumps({ - 'status': 'error', - 'message': str(error) - })) + return HttpResponse(json.dumps({'status': 'error', 'message': str(error)})) # Query successful term must be valid here, so we can save it safely now. request.session['term'] = term @@ -190,20 +182,26 @@ def get_results(request): for servertype_id in servertype_ids: editable_attributes[servertype_id] = default_editable.copy() for sa in ServertypeAttribute.objects.filter( - servertype_id__in=servertype_ids, - attribute_id__in=shown_attributes, - related_via_attribute_id__isnull=True, - attribute__readonly=False, + servertype_id__in=servertype_ids, + attribute_id__in=shown_attributes, + related_via_attribute_id__isnull=True, + attribute__readonly=False, ): editable_attributes[sa.servertype_id].append(sa.attribute_id) - return HttpResponse(json.dumps({ - 'status': 'success', - 'understood': repr(main_query), - 'servers': servers, - 'num_servers': num_servers, - 'editable_attributes': editable_attributes, - }, default=json_encode_extra), content_type='application/x-json') + return HttpResponse( + json.dumps( + { + 'status': 'success', + 'understood': repr(main_query), + 'servers': servers, + 'num_servers': num_servers, + 'editable_attributes': editable_attributes, + }, + default=json_encode_extra, + ), + content_type='application/x-json', + ) @login_required @@ -214,8 +212,7 @@ def inspect(request): elif 'hostname' in request.GET: query = Query({'hostname': request.GET['hostname']}, None) else: - return HttpResponseBadRequest( - 'object_id or hostname parameter is mandatory') + return HttpResponseBadRequest('object_id or hostname parameter is mandatory') if not query: return HttpResponseNotFound('No such object exists') @@ -240,20 +237,20 @@ def _edit(request: HttpRequest, server, edit_mode=False, template='edit'): # NO # @TODO work with ServerAttribute models here and use Django forms invalid_attrs = set() if edit_mode and request.POST: - attribute_lookup = {a.pk: a for a in Attribute.objects.filter( - attribute_id__in=(k[len('attr_'):] for k in request.POST.keys()))} + attribute_lookup = { + a.pk: a for a in Attribute.objects.filter(attribute_id__in=(k[len('attr_') :] for k in request.POST.keys())) + } attribute_lookup.update(Attribute.specials) # Get current values to be able to submit only changes current = None if server['object_id']: - current = Query({'object_id': server['object_id']}, - list(attribute_lookup.keys())).get() + current = Query({'object_id': server['object_id']}, list(attribute_lookup.keys())).get() for key, value in request.POST.items(): if not key.startswith('attr_'): continue - attribute_id = key[len('attr_'):] + attribute_id = key[len('attr_') :] attribute = attribute_lookup[attribute_id] value = value.strip() if attribute.multi: @@ -272,8 +269,7 @@ def _edit(request: HttpRequest, server, edit_mode=False, template='edit'): # NO invalid_attrs.add(attribute_id) if attribute_id not in server.keys(): - messages.error(request, - 'Unknown attribute {}'.format(attribute_id)) + messages.error(request, 'Unknown attribute {}'.format(attribute_id)) continue if current: @@ -308,8 +304,7 @@ def _edit(request: HttpRequest, server, edit_mode=False, template='edit'): # NO messages.info(request, str('Nothing has changed.')) else: try: - commit_obj = commit_query(created, changed, - user=request.user) + commit_obj = commit_query(created, changed, user=request.user) except (PermissionDenied, ValidationError) as err: messages.error(request, str(err)) else: @@ -327,21 +322,16 @@ def _edit(request: HttpRequest, server, edit_mode=False, template='edit'): # NO messages.error(request, 'Attributes contains invalid values') servertype = Servertype.objects.get(pk=server['servertype']) - attribute_lookup = {a.pk: a for a in Attribute.objects.filter( - attribute_id__in=(server.keys()) - )} + attribute_lookup = {a.pk: a for a in Attribute.objects.filter(attribute_id__in=(server.keys()))} attribute_lookup.update(Attribute.specials) - servertype_attributes = {sa.attribute_id: sa for sa in ( - ServertypeAttribute.objects.filter(servertype_id=server['servertype']) - )} + servertype_attributes = { + sa.attribute_id: sa for sa in (ServertypeAttribute.objects.filter(servertype_id=server['servertype'])) + } fields = [] fields_set = set() for key, value in server.items(): - if ( - key == 'object_id' or - key == 'intern_ip' and servertype.ip_addr_type == 'null' - ): + if key == 'object_id' or key == 'intern_ip' and servertype.ip_addr_type == 'null': continue # Apply pre-filled values from query string if submitted @@ -350,44 +340,43 @@ def _edit(request: HttpRequest, server, edit_mode=False, template='edit'): # NO is_related_attribute = False attribute = attribute_lookup[key] servertype_attribute = servertype_attributes.get(key) - if ( - servertype_attribute and - servertype_attribute.related_via_attribute - ): + if servertype_attribute and servertype_attribute.related_via_attribute: is_related_attribute = True fields_set.add(key) - fields.append({ - 'key': key, - 'value': value, - 'type': attribute.type if not is_related_attribute else 'related', - 'multi': attribute.multi, - 'required': ( - servertype_attribute and servertype_attribute.required or - key in Attribute.specials.keys() - ), - 'regexp_display': _prepare_regexp_html(attribute.regexp), - 'regexp': ( - # XXX: HTML5 input patterns do not support these - None if not attribute.regexp else - attribute.regexp.replace('\\A', '^').replace('\\Z', '$') - ), - 'default': ( - servertype_attribute and servertype_attribute.default_value - ), - 'readonly': attribute.readonly, - 'error': key in invalid_attrs, - 'hovertext': attribute.hovertext, - }) + fields.append( + { + 'key': key, + 'value': value, + 'type': attribute.type if not is_related_attribute else 'related', + 'multi': attribute.multi, + 'required': ( + servertype_attribute and servertype_attribute.required or key in Attribute.specials.keys() + ), + 'regexp_display': _prepare_regexp_html(attribute.regexp), + 'regexp': ( + # XXX: HTML5 input patterns do not support these + None if not attribute.regexp else attribute.regexp.replace('\\A', '^').replace('\\Z', '$') + ), + 'default': (servertype_attribute and servertype_attribute.default_value), + 'readonly': attribute.readonly, + 'error': key in invalid_attrs, + 'hovertext': attribute.hovertext, + } + ) fields.sort(key=lambda k: (not k['required'], k['key'])) - return TemplateResponse(request, 'servershell/{}.html'.format(template), { - 'object_id': server.object_id, - 'hostname': server['hostname'], - 'fields': fields, - 'base_template': 'base.html', - 'link': request.get_full_path(), - }) + return TemplateResponse( + request, + 'servershell/{}.html'.format(template), + { + 'object_id': server.object_id, + 'hostname': server['hostname'], + 'fields': fields, + 'base_template': 'base.html', + 'link': request.get_full_path(), + }, + ) @login_required @@ -429,8 +418,7 @@ def new_object(request: HttpRequest): try: new_object = Query().new_object(servertype) except Servertype.DoesNotExist: - messages.error(request, - 'The servertype {} does not exist!'.format(servertype)) + messages.error(request, 'The servertype {} does not exist!'.format(servertype)) return redirect('servershell_index') return _edit(request, new_object) @@ -443,13 +431,9 @@ def clone_object(request): # intern_ip is usually unique (except for loadbalancers) therefore it # makes sense to not clone it. cloned_attributes.remove('intern_ip') - cloned_attributes.extend( - list(Attribute.objects.filter(clone=True).values_list( - 'attribute_id', flat=True))) + cloned_attributes.extend(list(Attribute.objects.filter(clone=True).values_list('attribute_id', flat=True))) - old_object = Query( - {'object_id': request.GET.get('object_id')}, cloned_attributes - ).get() + old_object = Query({'object_id': request.GET.get('object_id')}, cloned_attributes).get() except ValidationError as e: messages.error(request, e.message) return redirect('servershell_index') @@ -464,37 +448,31 @@ def clone_object(request): @login_required def choose_ip_addr(request): if 'network' not in request.GET: - servers = list( - Query({'servertype': 'route_network'}, ['hostname', 'intern_ip'], - ['hostname'])) + servers = list(Query({'servertype': 'route_network'}, ['hostname', 'intern_ip'], ['hostname'])) - return TemplateResponse(request, 'servershell/choose_ip_addr.html', - {'servers': servers}) + return TemplateResponse(request, 'servershell/choose_ip_addr.html', {'servers': servers}) network = request.GET['network'] - servers = list(Query( - { - 'servertype': Any(*( - s.servertype_id - for s in Servertype.objects.filter(ip_addr_type='network') - )), - 'intern_ip': ContainedOnlyBy(network), - }, - ['hostname', 'intern_ip'], - ['hostname'], - )) + servers = list( + Query( + { + 'servertype': Any(*(s.servertype_id for s in Servertype.objects.filter(ip_addr_type='network'))), + 'intern_ip': ContainedOnlyBy(network), + }, + ['hostname', 'intern_ip'], + ['hostname'], + ) + ) if servers: - return TemplateResponse(request, 'servershell/choose_ip_addr.html', - {'servers': servers}) + return TemplateResponse(request, 'servershell/choose_ip_addr.html', {'servers': servers}) # TODO: This is specific to our data model, we should get it independent - network_query = Query( - {'intern_ip': network, 'servertype': Not('provider_network')}, - ['intern_ip', 'servertype']) + network_query = Query({'intern_ip': network, 'servertype': Not('provider_network')}, ['intern_ip', 'servertype']) - return TemplateResponse(request, 'servershell/choose_ip_addr.html', { - 'ip_addrs': islice(network_query.get_free_ip_addrs(), 50)}) + return TemplateResponse( + request, 'servershell/choose_ip_addr.html', {'ip_addrs': islice(network_query.get_free_ip_addrs(), 50)} + ) @login_required @@ -514,8 +492,7 @@ def settings(request): else: request.session[setting] = int(value) - return JsonResponse( - {key: request.session.get(key) for key in SEARCH_SETTINGS}) + return JsonResponse({key: request.session.get(key) for key in SEARCH_SETTINGS}) def _prepare_regexp_html(regexp): @@ -523,8 +500,7 @@ def _prepare_regexp_html(regexp): if not regexp: return '' else: - regexp_html = (escape_html(regexp).replace('|', '|​') - .replace(']', ']​').replace(')', ')​')) + regexp_html = escape_html(regexp).replace('|', '|​').replace(']', ']​').replace(')', ')​') return mark_safe(regexp_html) diff --git a/serveradmin/settings.py b/serveradmin/settings.py index e26bd51b..d849cf7a 100644 --- a/serveradmin/settings.py +++ b/serveradmin/settings.py @@ -3,9 +3,10 @@ Copyright (c) 2019 InnoGames GmbH """ -import environ import os +import environ + env = environ.Env() ROOT_DIR = os.path.abspath(os.path.dirname(__file__)) @@ -115,7 +116,7 @@ STATICFILES_FINDERS = [ 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', - 'compressor.finders.CompressorFinder' + 'compressor.finders.CompressorFinder', ] # Absolute path to the directory static files should be collected to. @@ -148,10 +149,13 @@ ], 'debug': DEBUG, 'loaders': [ - ('django.template.loaders.cached.Loader', [ - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - ]), + ( + 'django.template.loaders.cached.Loader', + [ + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', + ], + ), ], }, }, @@ -182,7 +186,7 @@ }, 'serveradmin': { 'level': 'INFO', - } + }, }, } @@ -191,9 +195,7 @@ GRAPHITE_SPRITE_WIDTH = 150 GRAPHITE_SPRITE_HEIGHT = 100 GRAPHITE_SPRITE_PARAMS = ( - 'width=' + str(GRAPHITE_SPRITE_WIDTH) + '&' + - 'height=' + str(GRAPHITE_SPRITE_HEIGHT) + '&' + - 'graphOnly=true' + 'width=' + str(GRAPHITE_SPRITE_WIDTH) + '&' + 'height=' + str(GRAPHITE_SPRITE_HEIGHT) + '&' + 'graphOnly=true' ) # Using exec certainly isn't an awesome solution but it's the best we've got. @@ -218,7 +220,7 @@ code = compile(config.read(), config_path, 'exec') exec(code) - print("Serveradmin config loaded from " + config_path) + print('Serveradmin config loaded from ' + config_path) break except OSError: print("Couldn't load serveradmin config from " + config_path) diff --git a/serveradmin/test_dataset.py b/serveradmin/test_dataset.py index c2bf5ef7..c784de64 100644 --- a/serveradmin/test_dataset.py +++ b/serveradmin/test_dataset.py @@ -3,8 +3,9 @@ Copyright (c) 2019 InnoGames GmbH """ -from ipaddress import IPv4Address, IPv6Address, IPv4Network, IPv6Network -from datetime import datetime, timezone, tzinfo, timedelta, date +from datetime import date, datetime, timedelta, timezone, tzinfo +from ipaddress import IPv4Address, IPv4Network, IPv6Address, IPv6Network + from django.contrib.auth.models import User from django.core.exceptions import ValidationError from django.test import TransactionTestCase diff --git a/serveradmin/urls.py b/serveradmin/urls.py index 28ee3aa7..a7446095 100644 --- a/serveradmin/urls.py +++ b/serveradmin/urls.py @@ -13,7 +13,7 @@ from django.contrib.auth.signals import user_logged_in from django.contrib.auth.views import logout_then_login from django.shortcuts import redirect -from django.urls import path, include +from django.urls import include, path user_logged_in.disconnect(update_last_login) @@ -34,12 +34,10 @@ module = module_spec.loader.load_module() if name.startswith('serveradmin.') or name.startswith('serveradmin_'): - url_path = name[(len('serveradmin') + 1):] + url_path = name[(len('serveradmin') + 1) :] urlpatterns.append(path('{}/'.format(url_path), include(module))) elif name == 'igrestlogin': urlpatterns.append(path('loginapi/', include(module))) if settings.DEBUG: - urlpatterns += static( - settings.MEDIA_URL, document_root=settings.MEDIA_ROOT - ) + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/serveradmin/wsgi.py b/serveradmin/wsgi.py index 4af4d3b0..eecb9a02 100644 --- a/serveradmin/wsgi.py +++ b/serveradmin/wsgi.py @@ -1,3 +1,7 @@ +import os + +from django.core.wsgi import get_wsgi_application + """Serveradmin Copyright (c) 2019 InnoGames GmbH @@ -18,14 +22,12 @@ framework. """ -import os -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "serveradmin.settings") +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'serveradmin.settings') # This application object is used by any WSGI server configured to use this # file. This includes Django's development server, if the WSGI_APPLICATION # setting points here. -from django.core.wsgi import get_wsgi_application application = get_wsgi_application() # Apply WSGI middleware here. diff --git a/setup.py b/setup.py index be3729a6..a34c708c 100755 --- a/setup.py +++ b/setup.py @@ -4,9 +4,9 @@ Copyright (c) 2021 InnoGames GmbH """ -from setuptools import setup, find_packages -from adminapi import VERSION as SERVERADMIN_VERSION +from setuptools import find_packages, setup +from adminapi import VERSION as SERVERADMIN_VERSION if __name__ == '__main__': setup( From 181225f201917774674ae6624b8343a65366d25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kr=C3=B6ger?= Date: Wed, 19 Mar 2025 10:34:22 +0100 Subject: [PATCH 04/11] Fix possible reflected server-side cross-site scripting --- serveradmin/resources/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/serveradmin/resources/views.py b/serveradmin/resources/views.py index 53793291..6a31b5d9 100644 --- a/serveradmin/resources/views.py +++ b/serveradmin/resources/views.py @@ -3,6 +3,7 @@ Copyright (c) 2019 InnoGames GmbH """ +import html from collections import OrderedDict from django.conf import settings @@ -40,7 +41,7 @@ def index(request): current_collection = collection break else: - return HttpResponseBadRequest(f'Collection {current_collection_id} does not exist!') + return HttpResponseBadRequest(f'Collection {html.escape(current_collection_id)} does not exist!') # Save latest choice for collection request.session['current_collection'] = current_collection.id From ecafab8bacf8febcb2882d23e7501fdea81b3605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kr=C3=B6ger?= Date: Wed, 19 Mar 2025 10:38:44 +0100 Subject: [PATCH 05/11] Delete obsolete flake8 config --- .flake8 | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 .flake8 diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 771c66a5..00000000 --- a/.flake8 +++ /dev/null @@ -1,6 +0,0 @@ -[flake8] -max-complexity = 10 -# After a PEP8 change W503 was superseded by the opposing W504. Before it was -# correct to break after a binary operator, now before. We stick to the old -# style for now. -ignore = W504 From b20b8485859b997149cc868a373f149711113aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kr=C3=B6ger?= Date: Wed, 19 Mar 2025 10:39:34 +0100 Subject: [PATCH 06/11] Update PostgreSQL default version to 17 --- .github/workflows/tests.yml | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4bf000f1..b27ae0be 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,7 @@ jobs: services: db: - image: 'postgres:15' + image: 'postgres:17' env: POSTGRES_USER: serveradmin POSTGRES_PASSWORD: serveradmin diff --git a/docker-compose.yml b/docker-compose.yml index 603a23ba..822e2960 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.9" services: db: - image: "postgres:15" + image: "postgres:17" environment: - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} From b4ecc3ced7d6c8eb80d504ecafde66a470bf801a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kr=C3=B6ger?= Date: Wed, 19 Mar 2025 10:47:10 +0100 Subject: [PATCH 07/11] Remove obsolete version attribute --- docker-compose.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 822e2960..29df3346 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3.9" - services: db: image: "postgres:17" From 42b5b1b3fc368552aefb38d63bd45df33171afb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kr=C3=B6ger?= Date: Wed, 19 Mar 2025 10:52:27 +0100 Subject: [PATCH 08/11] Remove obsolete and outdated files --- CHANGELOG.md | 14 - serveradmin.sql | 4111 ----------------------------------------------- 2 files changed, 4125 deletions(-) delete mode 100644 CHANGELOG.md delete mode 100644 serveradmin.sql diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index e9d3df2f..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,14 +0,0 @@ -# Change Log - -## 4.14.0 -* Allow Serveradmin apps to extend the Servershell (Javascript) [PR!348](https://github.com/innogames/serveradmin/pull/348) -* Support pagination with multiple forms [PR!349](https://github.com/innogames/serveradmin/pull/349) -* Skip check for permission to change for related_via attrs [PR!351](https://github.com/innogames/serveradmin/pull/351) - -## 4.13.0 -* Extend inet attributes and improve ip address type validation [PR!346](https://github.com/innogames/serveradmin/pull/346) -* Bump cryptography from 42.0.2 to 42.0.4 (#347) - -## 4.12.1 - -* Support prefilled values via GET parameter for new objects [PR!344](https://github.com/innogames/serveradmin/pull/344) diff --git a/serveradmin.sql b/serveradmin.sql deleted file mode 100644 index 4517425f..00000000 --- a/serveradmin.sql +++ /dev/null @@ -1,4111 +0,0 @@ --- --- PostgreSQL database dump --- - --- Dumped from database version 14.2 (Debian 14.2-1.pgdg110+1) --- Dumped by pg_dump version 14.3 (Debian 14.3-1.pgdg110+1) - -SET statement_timeout = 0; -SET lock_timeout = 0; -SET idle_in_transaction_session_timeout = 0; -SET client_encoding = 'UTF8'; -SET standard_conforming_strings = on; -SELECT pg_catalog.set_config('search_path', '', false); -SET check_function_bodies = false; -SET xmloption = content; -SET client_min_messages = warning; -SET row_security = off; - --- --- Name: btree_gist; Type: EXTENSION; Schema: -; Owner: - --- - -CREATE EXTENSION IF NOT EXISTS btree_gist WITH SCHEMA public; - - --- --- Name: EXTENSION btree_gist; Type: COMMENT; Schema: -; Owner: --- - -COMMENT ON EXTENSION btree_gist IS 'support for indexing common datatypes in GiST'; - - --- --- Name: pg_trgm; Type: EXTENSION; Schema: -; Owner: - --- - -CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA public; - - --- --- Name: EXTENSION pg_trgm; Type: COMMENT; Schema: -; Owner: --- - -COMMENT ON EXTENSION pg_trgm IS 'text similarity measurement and index searching based on trigrams'; - - -SET default_tablespace = ''; - -SET default_table_access_method = heap; - --- --- Name: access_control_group; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.access_control_group ( - id integer NOT NULL, - name character varying(80) NOT NULL, - query character varying(1000) NOT NULL, - is_whitelist boolean NOT NULL -); - - -ALTER TABLE public.access_control_group OWNER TO serveradmin; - --- --- Name: access_control_group_applications; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.access_control_group_applications ( - id integer NOT NULL, - accesscontrolgroup_id integer NOT NULL, - application_id integer NOT NULL -); - - -ALTER TABLE public.access_control_group_applications OWNER TO serveradmin; - --- --- Name: access_control_group_applications_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.access_control_group_applications_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.access_control_group_applications_id_seq OWNER TO serveradmin; - --- --- Name: access_control_group_applications_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.access_control_group_applications_id_seq OWNED BY public.access_control_group_applications.id; - - --- --- Name: access_control_group_attributes; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.access_control_group_attributes ( - id integer NOT NULL, - accesscontrolgroup_id integer NOT NULL, - attribute_id character varying(32) NOT NULL -); - - -ALTER TABLE public.access_control_group_attributes OWNER TO serveradmin; - --- --- Name: access_control_group_attributes_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.access_control_group_attributes_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.access_control_group_attributes_id_seq OWNER TO serveradmin; - --- --- Name: access_control_group_attributes_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.access_control_group_attributes_id_seq OWNED BY public.access_control_group_attributes.id; - - --- --- Name: access_control_group_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.access_control_group_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.access_control_group_id_seq OWNER TO serveradmin; - --- --- Name: access_control_group_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.access_control_group_id_seq OWNED BY public.access_control_group.id; - - --- --- Name: access_control_group_members; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.access_control_group_members ( - id integer NOT NULL, - accesscontrolgroup_id integer NOT NULL, - user_id integer NOT NULL -); - - -ALTER TABLE public.access_control_group_members OWNER TO serveradmin; - --- --- Name: access_control_group_members_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.access_control_group_members_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.access_control_group_members_id_seq OWNER TO serveradmin; - --- --- Name: access_control_group_members_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.access_control_group_members_id_seq OWNED BY public.access_control_group_members.id; - - --- --- Name: api_lock; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.api_lock ( - id integer NOT NULL, - hash_sum character varying(40) NOT NULL, - until timestamp with time zone, - duration integer, - CONSTRAINT api_lock_duration_check CHECK ((duration >= 0)) -); - - -ALTER TABLE public.api_lock OWNER TO serveradmin; - --- --- Name: api_lock_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.api_lock_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.api_lock_id_seq OWNER TO serveradmin; - --- --- Name: api_lock_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.api_lock_id_seq OWNED BY public.api_lock.id; - - --- --- Name: apps_application; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.apps_application ( - id integer NOT NULL, - name character varying(80) NOT NULL, - app_id character varying(64) NOT NULL, - auth_token character varying(64) NOT NULL, - location character varying(150) NOT NULL, - disabled boolean NOT NULL, - superuser boolean NOT NULL, - allowed_methods text NOT NULL, - owner_id integer NOT NULL, - last_login timestamp with time zone -); - - -ALTER TABLE public.apps_application OWNER TO serveradmin; - --- --- Name: apps_application_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.apps_application_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.apps_application_id_seq OWNER TO serveradmin; - --- --- Name: apps_application_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.apps_application_id_seq OWNED BY public.apps_application.id; - - --- --- Name: apps_publickey; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.apps_publickey ( - key_algorithm character varying(80) NOT NULL, - key_base64 character varying(2048) NOT NULL, - key_comment character varying(80) NOT NULL, - application_id integer NOT NULL -); - - -ALTER TABLE public.apps_publickey OWNER TO serveradmin; - --- --- Name: attribute; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.attribute ( - attribute_id character varying(32) NOT NULL, - type character varying(32) NOT NULL, - multi boolean NOT NULL, - hovertext text NOT NULL, - "group" character varying(32) NOT NULL, - help_link character varying(255), - readonly boolean NOT NULL, - clone boolean NOT NULL, - regexp character varying(1024) NOT NULL, - reversed_attribute_id character varying(32), - target_servertype_id character varying(32), - CONSTRAINT attribute_attribute_id_check CHECK (((attribute_id)::text ~ '\A[a-z][a-z0-9_]+\Z'::text)), - CONSTRAINT attribute_clone_check CHECK (((NOT clone) OR ((type)::text <> ALL ((ARRAY['reverse'::character varying, 'supernet'::character varying, 'domain'::character varying])::text[])))), - CONSTRAINT attribute_multi_check CHECK ((((type)::text <> ALL ((ARRAY['boolean'::character varying, 'supernet'::character varying, 'domain'::character varying])::text[])) OR (NOT multi))), - CONSTRAINT attribute_readonly_check CHECK ((((type)::text <> ALL ((ARRAY['reverse'::character varying, 'supernet'::character varying, 'domain'::character varying])::text[])) OR readonly)), - CONSTRAINT attribute_regexp_check CHECK (((regexp)::text ~ '\A\\A.*\\Z\Z'::text)), - CONSTRAINT attribute_reversed_attribute_id_check CHECK ((((type)::text = 'reverse'::text) = (reversed_attribute_id IS NOT NULL))), - CONSTRAINT attribute_target_servertype_id_check CHECK ((((type)::text = ANY ((ARRAY['relation'::character varying, 'supernet'::character varying, 'domain'::character varying])::text[])) = (target_servertype_id IS NOT NULL))) -); - - -ALTER TABLE public.attribute OWNER TO serveradmin; - --- --- Name: auth_group; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.auth_group ( - id integer NOT NULL, - name character varying(150) NOT NULL -); - - -ALTER TABLE public.auth_group OWNER TO serveradmin; - --- --- Name: auth_group_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.auth_group_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.auth_group_id_seq OWNER TO serveradmin; - --- --- Name: auth_group_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.auth_group_id_seq OWNED BY public.auth_group.id; - - --- --- Name: auth_group_permissions; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.auth_group_permissions ( - id integer NOT NULL, - group_id integer NOT NULL, - permission_id integer NOT NULL -); - - -ALTER TABLE public.auth_group_permissions OWNER TO serveradmin; - --- --- Name: auth_group_permissions_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.auth_group_permissions_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.auth_group_permissions_id_seq OWNER TO serveradmin; - --- --- Name: auth_group_permissions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.auth_group_permissions_id_seq OWNED BY public.auth_group_permissions.id; - - --- --- Name: auth_permission; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.auth_permission ( - id integer NOT NULL, - name character varying(255) NOT NULL, - content_type_id integer NOT NULL, - codename character varying(100) NOT NULL -); - - -ALTER TABLE public.auth_permission OWNER TO serveradmin; - --- --- Name: auth_permission_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.auth_permission_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.auth_permission_id_seq OWNER TO serveradmin; - --- --- Name: auth_permission_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.auth_permission_id_seq OWNED BY public.auth_permission.id; - - --- --- Name: auth_user; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.auth_user ( - id integer NOT NULL, - password character varying(128) NOT NULL, - last_login timestamp with time zone, - is_superuser boolean NOT NULL, - username character varying(150) NOT NULL, - first_name character varying(150) NOT NULL, - last_name character varying(150) NOT NULL, - email character varying(254) NOT NULL, - is_staff boolean NOT NULL, - is_active boolean NOT NULL, - date_joined timestamp with time zone NOT NULL -); - - -ALTER TABLE public.auth_user OWNER TO serveradmin; - --- --- Name: auth_user_groups; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.auth_user_groups ( - id integer NOT NULL, - user_id integer NOT NULL, - group_id integer NOT NULL -); - - -ALTER TABLE public.auth_user_groups OWNER TO serveradmin; - --- --- Name: auth_user_groups_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.auth_user_groups_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.auth_user_groups_id_seq OWNER TO serveradmin; - --- --- Name: auth_user_groups_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.auth_user_groups_id_seq OWNED BY public.auth_user_groups.id; - - --- --- Name: auth_user_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.auth_user_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.auth_user_id_seq OWNER TO serveradmin; - --- --- Name: auth_user_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.auth_user_id_seq OWNED BY public.auth_user.id; - - --- --- Name: auth_user_user_permissions; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.auth_user_user_permissions ( - id integer NOT NULL, - user_id integer NOT NULL, - permission_id integer NOT NULL -); - - -ALTER TABLE public.auth_user_user_permissions OWNER TO serveradmin; - --- --- Name: auth_user_user_permissions_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.auth_user_user_permissions_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.auth_user_user_permissions_id_seq OWNER TO serveradmin; - --- --- Name: auth_user_user_permissions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.auth_user_user_permissions_id_seq OWNED BY public.auth_user_user_permissions.id; - - --- --- Name: django_admin_log; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.django_admin_log ( - id integer NOT NULL, - action_time timestamp with time zone NOT NULL, - object_id text, - object_repr character varying(200) NOT NULL, - action_flag smallint NOT NULL, - change_message text NOT NULL, - content_type_id integer, - user_id integer NOT NULL, - CONSTRAINT django_admin_log_action_flag_check CHECK ((action_flag >= 0)) -); - - -ALTER TABLE public.django_admin_log OWNER TO serveradmin; - --- --- Name: django_admin_log_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.django_admin_log_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.django_admin_log_id_seq OWNER TO serveradmin; - --- --- Name: django_admin_log_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.django_admin_log_id_seq OWNED BY public.django_admin_log.id; - - --- --- Name: django_content_type; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.django_content_type ( - id integer NOT NULL, - app_label character varying(100) NOT NULL, - model character varying(100) NOT NULL -); - - -ALTER TABLE public.django_content_type OWNER TO serveradmin; - --- --- Name: django_content_type_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.django_content_type_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.django_content_type_id_seq OWNER TO serveradmin; - --- --- Name: django_content_type_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.django_content_type_id_seq OWNED BY public.django_content_type.id; - - --- --- Name: django_migrations; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.django_migrations ( - id integer NOT NULL, - app character varying(255) NOT NULL, - name character varying(255) NOT NULL, - applied timestamp with time zone NOT NULL -); - - -ALTER TABLE public.django_migrations OWNER TO serveradmin; - --- --- Name: django_migrations_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.django_migrations_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.django_migrations_id_seq OWNER TO serveradmin; - --- --- Name: django_migrations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.django_migrations_id_seq OWNED BY public.django_migrations.id; - - --- --- Name: django_session; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.django_session ( - session_key character varying(40) NOT NULL, - session_data text NOT NULL, - expire_date timestamp with time zone NOT NULL -); - - -ALTER TABLE public.django_session OWNER TO serveradmin; - --- --- Name: django_site; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.django_site ( - id integer NOT NULL, - domain character varying(100) NOT NULL, - name character varying(50) NOT NULL -); - - -ALTER TABLE public.django_site OWNER TO serveradmin; - --- --- Name: django_site_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.django_site_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.django_site_id_seq OWNER TO serveradmin; - --- --- Name: django_site_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.django_site_id_seq OWNED BY public.django_site.id; - - --- --- Name: graphite_collection; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.graphite_collection ( - id integer NOT NULL, - name character varying(255) NOT NULL, - params text NOT NULL, - sort_order double precision NOT NULL, - overview boolean NOT NULL, - created_at timestamp with time zone NOT NULL -); - - -ALTER TABLE public.graphite_collection OWNER TO serveradmin; - --- --- Name: graphite_collection_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.graphite_collection_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.graphite_collection_id_seq OWNER TO serveradmin; - --- --- Name: graphite_collection_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.graphite_collection_id_seq OWNED BY public.graphite_collection.id; - - --- --- Name: graphite_numeric; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.graphite_numeric ( - id integer NOT NULL, - params text NOT NULL, - sort_order double precision NOT NULL, - attribute_id character varying(32) NOT NULL, - collection_id integer NOT NULL -); - - -ALTER TABLE public.graphite_numeric OWNER TO serveradmin; - --- --- Name: graphite_numeric_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.graphite_numeric_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.graphite_numeric_id_seq OWNER TO serveradmin; - --- --- Name: graphite_numeric_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.graphite_numeric_id_seq OWNED BY public.graphite_numeric.id; - - --- --- Name: graphite_relation; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.graphite_relation ( - id integer NOT NULL, - sort_order double precision NOT NULL, - attribute_id character varying(32) NOT NULL, - collection_id integer NOT NULL -); - - -ALTER TABLE public.graphite_relation OWNER TO serveradmin; - --- --- Name: graphite_relation_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.graphite_relation_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.graphite_relation_id_seq OWNER TO serveradmin; - --- --- Name: graphite_relation_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.graphite_relation_id_seq OWNED BY public.graphite_relation.id; - - --- --- Name: graphite_template; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.graphite_template ( - id integer NOT NULL, - name character varying(255) NOT NULL, - params text NOT NULL, - sort_order double precision NOT NULL, - description text NOT NULL, - foreach_path character varying(256) NOT NULL, - collection_id integer NOT NULL -); - - -ALTER TABLE public.graphite_template OWNER TO serveradmin; - --- --- Name: graphite_template_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.graphite_template_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.graphite_template_id_seq OWNER TO serveradmin; - --- --- Name: graphite_template_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.graphite_template_id_seq OWNED BY public.graphite_template.id; - - --- --- Name: graphite_variation; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.graphite_variation ( - id integer NOT NULL, - name character varying(255) NOT NULL, - params text NOT NULL, - sort_order double precision NOT NULL, - summarize_interval character varying(255) NOT NULL, - collection_id integer NOT NULL -); - - -ALTER TABLE public.graphite_variation OWNER TO serveradmin; - --- --- Name: graphite_variation_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.graphite_variation_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.graphite_variation_id_seq OWNER TO serveradmin; - --- --- Name: graphite_variation_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.graphite_variation_id_seq OWNED BY public.graphite_variation.id; - - --- --- Name: server; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.server ( - server_id integer NOT NULL, - hostname character varying(254) NOT NULL, - intern_ip inet, - servertype_id character varying(32) NOT NULL, - CONSTRAINT server_hostname_check CHECK (((hostname)::text ~ '\A(\*\.)?([a-z0-9_]+(\.|-+))*[a-z0-9]+\Z'::text)) -); - - -ALTER TABLE public.server OWNER TO serveradmin; - --- --- Name: server_boolean_attribute; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.server_boolean_attribute ( - id integer NOT NULL, - attribute_id character varying(32) NOT NULL, - server_id integer NOT NULL -); - - -ALTER TABLE public.server_boolean_attribute OWNER TO serveradmin; - --- --- Name: server_boolean_attribute_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.server_boolean_attribute_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.server_boolean_attribute_id_seq OWNER TO serveradmin; - --- --- Name: server_boolean_attribute_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.server_boolean_attribute_id_seq OWNED BY public.server_boolean_attribute.id; - - --- --- Name: server_date_attribute; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.server_date_attribute ( - id integer NOT NULL, - value date NOT NULL, - attribute_id character varying(32) NOT NULL, - server_id integer NOT NULL -); - - -ALTER TABLE public.server_date_attribute OWNER TO serveradmin; - --- --- Name: server_date_attribute_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.server_date_attribute_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.server_date_attribute_id_seq OWNER TO serveradmin; - --- --- Name: server_date_attribute_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.server_date_attribute_id_seq OWNED BY public.server_date_attribute.id; - - --- --- Name: server_datetime_attribute; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.server_datetime_attribute ( - id integer NOT NULL, - value timestamp with time zone NOT NULL, - attribute_id character varying(32) NOT NULL, - server_id integer NOT NULL -); - - -ALTER TABLE public.server_datetime_attribute OWNER TO serveradmin; - --- --- Name: server_datetime_attribute_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.server_datetime_attribute_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.server_datetime_attribute_id_seq OWNER TO serveradmin; - --- --- Name: server_datetime_attribute_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.server_datetime_attribute_id_seq OWNED BY public.server_datetime_attribute.id; - - --- --- Name: server_inet_attribute; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.server_inet_attribute ( - id integer NOT NULL, - value inet NOT NULL, - attribute_id character varying(32) NOT NULL, - server_id integer NOT NULL -); - - -ALTER TABLE public.server_inet_attribute OWNER TO serveradmin; - --- --- Name: server_inet_attribute_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.server_inet_attribute_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.server_inet_attribute_id_seq OWNER TO serveradmin; - --- --- Name: server_inet_attribute_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.server_inet_attribute_id_seq OWNED BY public.server_inet_attribute.id; - - --- --- Name: server_macaddr_attribute; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.server_macaddr_attribute ( - id integer NOT NULL, - value macaddr NOT NULL, - attribute_id character varying(32) NOT NULL, - server_id integer NOT NULL -); - - -ALTER TABLE public.server_macaddr_attribute OWNER TO serveradmin; - --- --- Name: server_macaddr_attribute_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.server_macaddr_attribute_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.server_macaddr_attribute_id_seq OWNER TO serveradmin; - --- --- Name: server_macaddr_attribute_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.server_macaddr_attribute_id_seq OWNED BY public.server_macaddr_attribute.id; - - --- --- Name: server_number_attribute; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.server_number_attribute ( - id integer NOT NULL, - value numeric(65,0) NOT NULL, - attribute_id character varying(32) NOT NULL, - server_id integer NOT NULL -); - - -ALTER TABLE public.server_number_attribute OWNER TO serveradmin; - --- --- Name: server_number_attribute_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.server_number_attribute_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.server_number_attribute_id_seq OWNER TO serveradmin; - --- --- Name: server_number_attribute_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.server_number_attribute_id_seq OWNED BY public.server_number_attribute.id; - - --- --- Name: server_relation_attribute; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.server_relation_attribute ( - id integer NOT NULL, - attribute_id character varying(32) NOT NULL, - server_id integer NOT NULL, - value integer NOT NULL -); - - -ALTER TABLE public.server_relation_attribute OWNER TO serveradmin; - --- --- Name: server_relation_attribute_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.server_relation_attribute_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.server_relation_attribute_id_seq OWNER TO serveradmin; - --- --- Name: server_relation_attribute_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.server_relation_attribute_id_seq OWNED BY public.server_relation_attribute.id; - - --- --- Name: server_server_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.server_server_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.server_server_id_seq OWNER TO serveradmin; - --- --- Name: server_server_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.server_server_id_seq OWNED BY public.server.server_id; - - --- --- Name: server_string_attribute; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.server_string_attribute ( - id integer NOT NULL, - value character varying(1024) NOT NULL, - attribute_id character varying(32) NOT NULL, - server_id integer NOT NULL, - CONSTRAINT server_string_attribute_value_check CHECK (((value)::text <> ''::text)) -); - - -ALTER TABLE public.server_string_attribute OWNER TO serveradmin; - --- --- Name: server_string_attribute_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.server_string_attribute_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.server_string_attribute_id_seq OWNER TO serveradmin; - --- --- Name: server_string_attribute_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.server_string_attribute_id_seq OWNED BY public.server_string_attribute.id; - - --- --- Name: serverdb_change; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.serverdb_change ( - id integer NOT NULL, - change_on timestamp with time zone NOT NULL, - changes_json text NOT NULL, - app_id integer, - user_id integer -); - - -ALTER TABLE public.serverdb_change OWNER TO serveradmin; - --- --- Name: serverdb_change_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.serverdb_change_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.serverdb_change_id_seq OWNER TO serveradmin; - --- --- Name: serverdb_change_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.serverdb_change_id_seq OWNED BY public.serverdb_change.id; - - --- --- Name: serverdb_changeadd; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.serverdb_changeadd ( - id integer NOT NULL, - server_id integer NOT NULL, - attributes_json text NOT NULL, - commit_id integer NOT NULL -); - - -ALTER TABLE public.serverdb_changeadd OWNER TO serveradmin; - --- --- Name: serverdb_changeadd_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.serverdb_changeadd_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.serverdb_changeadd_id_seq OWNER TO serveradmin; - --- --- Name: serverdb_changeadd_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.serverdb_changeadd_id_seq OWNED BY public.serverdb_changeadd.id; - - --- --- Name: serverdb_changecommit; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.serverdb_changecommit ( - id integer NOT NULL, - change_on timestamp with time zone NOT NULL, - app_id integer, - user_id integer -); - - -ALTER TABLE public.serverdb_changecommit OWNER TO serveradmin; - --- --- Name: serverdb_changecommit_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.serverdb_changecommit_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.serverdb_changecommit_id_seq OWNER TO serveradmin; - --- --- Name: serverdb_changecommit_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.serverdb_changecommit_id_seq OWNED BY public.serverdb_changecommit.id; - - --- --- Name: serverdb_changedelete; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.serverdb_changedelete ( - id integer NOT NULL, - server_id integer NOT NULL, - attributes_json text NOT NULL, - commit_id integer NOT NULL -); - - -ALTER TABLE public.serverdb_changedelete OWNER TO serveradmin; - --- --- Name: serverdb_changedelete_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.serverdb_changedelete_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.serverdb_changedelete_id_seq OWNER TO serveradmin; - --- --- Name: serverdb_changedelete_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.serverdb_changedelete_id_seq OWNED BY public.serverdb_changedelete.id; - - --- --- Name: serverdb_changeupdate; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.serverdb_changeupdate ( - id integer NOT NULL, - server_id integer NOT NULL, - updates_json text NOT NULL, - commit_id integer NOT NULL -); - - -ALTER TABLE public.serverdb_changeupdate OWNER TO serveradmin; - --- --- Name: serverdb_changeupdate_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.serverdb_changeupdate_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.serverdb_changeupdate_id_seq OWNER TO serveradmin; - --- --- Name: serverdb_changeupdate_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.serverdb_changeupdate_id_seq OWNED BY public.serverdb_changeupdate.id; - - --- --- Name: servertype; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.servertype ( - servertype_id character varying(32) NOT NULL, - description character varying(1024) NOT NULL, - ip_addr_type character varying(32) NOT NULL, - CONSTRAINT servertype_servertype_id_check CHECK (((servertype_id)::text ~ '\A[a-z][a-z0-9_]+\Z'::text)) -); - - -ALTER TABLE public.servertype OWNER TO serveradmin; - --- --- Name: servertype_attribute; Type: TABLE; Schema: public; Owner: serveradmin --- - -CREATE TABLE public.servertype_attribute ( - id integer NOT NULL, - required boolean NOT NULL, - default_value character varying(255), - default_visible boolean NOT NULL, - attribute_id character varying(32) NOT NULL, - consistent_via_attribute_id character varying(32), - related_via_attribute_id character varying(32), - servertype_id character varying(32) NOT NULL, - CONSTRAINT servertype_attribute_default_value_check CHECK (((default_value)::text <> ''::text)) -); - - -ALTER TABLE public.servertype_attribute OWNER TO serveradmin; - --- --- Name: servertype_attribute_id_seq; Type: SEQUENCE; Schema: public; Owner: serveradmin --- - -CREATE SEQUENCE public.servertype_attribute_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.servertype_attribute_id_seq OWNER TO serveradmin; - --- --- Name: servertype_attribute_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: serveradmin --- - -ALTER SEQUENCE public.servertype_attribute_id_seq OWNED BY public.servertype_attribute.id; - - --- --- Name: access_control_group id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group ALTER COLUMN id SET DEFAULT nextval('public.access_control_group_id_seq'::regclass); - - --- --- Name: access_control_group_applications id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_applications ALTER COLUMN id SET DEFAULT nextval('public.access_control_group_applications_id_seq'::regclass); - - --- --- Name: access_control_group_attributes id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_attributes ALTER COLUMN id SET DEFAULT nextval('public.access_control_group_attributes_id_seq'::regclass); - - --- --- Name: access_control_group_members id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_members ALTER COLUMN id SET DEFAULT nextval('public.access_control_group_members_id_seq'::regclass); - - --- --- Name: api_lock id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.api_lock ALTER COLUMN id SET DEFAULT nextval('public.api_lock_id_seq'::regclass); - - --- --- Name: apps_application id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.apps_application ALTER COLUMN id SET DEFAULT nextval('public.apps_application_id_seq'::regclass); - - --- --- Name: auth_group id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_group ALTER COLUMN id SET DEFAULT nextval('public.auth_group_id_seq'::regclass); - - --- --- Name: auth_group_permissions id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_group_permissions ALTER COLUMN id SET DEFAULT nextval('public.auth_group_permissions_id_seq'::regclass); - - --- --- Name: auth_permission id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_permission ALTER COLUMN id SET DEFAULT nextval('public.auth_permission_id_seq'::regclass); - - --- --- Name: auth_user id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user ALTER COLUMN id SET DEFAULT nextval('public.auth_user_id_seq'::regclass); - - --- --- Name: auth_user_groups id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user_groups ALTER COLUMN id SET DEFAULT nextval('public.auth_user_groups_id_seq'::regclass); - - --- --- Name: auth_user_user_permissions id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user_user_permissions ALTER COLUMN id SET DEFAULT nextval('public.auth_user_user_permissions_id_seq'::regclass); - - --- --- Name: django_admin_log id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_admin_log ALTER COLUMN id SET DEFAULT nextval('public.django_admin_log_id_seq'::regclass); - - --- --- Name: django_content_type id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_content_type ALTER COLUMN id SET DEFAULT nextval('public.django_content_type_id_seq'::regclass); - - --- --- Name: django_migrations id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_migrations ALTER COLUMN id SET DEFAULT nextval('public.django_migrations_id_seq'::regclass); - - --- --- Name: django_site id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_site ALTER COLUMN id SET DEFAULT nextval('public.django_site_id_seq'::regclass); - - --- --- Name: graphite_collection id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_collection ALTER COLUMN id SET DEFAULT nextval('public.graphite_collection_id_seq'::regclass); - - --- --- Name: graphite_numeric id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_numeric ALTER COLUMN id SET DEFAULT nextval('public.graphite_numeric_id_seq'::regclass); - - --- --- Name: graphite_relation id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_relation ALTER COLUMN id SET DEFAULT nextval('public.graphite_relation_id_seq'::regclass); - - --- --- Name: graphite_template id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_template ALTER COLUMN id SET DEFAULT nextval('public.graphite_template_id_seq'::regclass); - - --- --- Name: graphite_variation id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_variation ALTER COLUMN id SET DEFAULT nextval('public.graphite_variation_id_seq'::regclass); - - --- --- Name: server server_id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server ALTER COLUMN server_id SET DEFAULT nextval('public.server_server_id_seq'::regclass); - - --- --- Name: server_boolean_attribute id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_boolean_attribute ALTER COLUMN id SET DEFAULT nextval('public.server_boolean_attribute_id_seq'::regclass); - - --- --- Name: server_date_attribute id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_date_attribute ALTER COLUMN id SET DEFAULT nextval('public.server_date_attribute_id_seq'::regclass); - - --- --- Name: server_datetime_attribute id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_datetime_attribute ALTER COLUMN id SET DEFAULT nextval('public.server_datetime_attribute_id_seq'::regclass); - - --- --- Name: server_inet_attribute id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_inet_attribute ALTER COLUMN id SET DEFAULT nextval('public.server_inet_attribute_id_seq'::regclass); - - --- --- Name: server_macaddr_attribute id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_macaddr_attribute ALTER COLUMN id SET DEFAULT nextval('public.server_macaddr_attribute_id_seq'::regclass); - - --- --- Name: server_number_attribute id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_number_attribute ALTER COLUMN id SET DEFAULT nextval('public.server_number_attribute_id_seq'::regclass); - - --- --- Name: server_relation_attribute id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_relation_attribute ALTER COLUMN id SET DEFAULT nextval('public.server_relation_attribute_id_seq'::regclass); - - --- --- Name: server_string_attribute id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_string_attribute ALTER COLUMN id SET DEFAULT nextval('public.server_string_attribute_id_seq'::regclass); - - --- --- Name: serverdb_change id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_change ALTER COLUMN id SET DEFAULT nextval('public.serverdb_change_id_seq'::regclass); - - --- --- Name: serverdb_changeadd id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changeadd ALTER COLUMN id SET DEFAULT nextval('public.serverdb_changeadd_id_seq'::regclass); - - --- --- Name: serverdb_changecommit id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changecommit ALTER COLUMN id SET DEFAULT nextval('public.serverdb_changecommit_id_seq'::regclass); - - --- --- Name: serverdb_changedelete id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changedelete ALTER COLUMN id SET DEFAULT nextval('public.serverdb_changedelete_id_seq'::regclass); - - --- --- Name: serverdb_changeupdate id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changeupdate ALTER COLUMN id SET DEFAULT nextval('public.serverdb_changeupdate_id_seq'::regclass); - - --- --- Name: servertype_attribute id; Type: DEFAULT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.servertype_attribute ALTER COLUMN id SET DEFAULT nextval('public.servertype_attribute_id_seq'::regclass); - - --- --- Data for Name: access_control_group; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.access_control_group (id, name, query, is_whitelist) FROM stdin; -\. - - --- --- Data for Name: access_control_group_applications; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.access_control_group_applications (id, accesscontrolgroup_id, application_id) FROM stdin; -\. - - --- --- Data for Name: access_control_group_attributes; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.access_control_group_attributes (id, accesscontrolgroup_id, attribute_id) FROM stdin; -\. - - --- --- Data for Name: access_control_group_members; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.access_control_group_members (id, accesscontrolgroup_id, user_id) FROM stdin; -\. - - --- --- Data for Name: api_lock; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.api_lock (id, hash_sum, until, duration) FROM stdin; -\. - - --- --- Data for Name: apps_application; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.apps_application (id, name, app_id, auth_token, location, disabled, superuser, allowed_methods, owner_id, last_login) FROM stdin; -1 default app for serveradmin 421cbe6b6e6044f785e77267f7f403dd8646be9f 8igR21kG0yspOm9KRwUwozlu f t 1 \N -\. - - --- --- Data for Name: apps_publickey; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.apps_publickey (key_algorithm, key_base64, key_comment, application_id) FROM stdin; -\. - - --- --- Data for Name: attribute; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.attribute (attribute_id, type, multi, hovertext, "group", help_link, readonly, clone, regexp, reversed_attribute_id, target_servertype_id) FROM stdin; -powerdns_domain relation f (Host)Name of the domain this record belongs to. PowerDNS \N f f \\A.*\\Z \N powerdns_domain -powerdns_domain_type string f PowerDNS domain type PowerDNS \N f f \\A(MASTER|SLAVE|NATIVE)\\Z \N \N -powerdns_record_aaaa inet t PowerDNS record type AAAA values. PowerDNS \N f f \\A.*\\Z \N \N -powerdns_record_a inet t PowerDNS record type A values. PowerDNS \N f f \\A.*\\Z \N \N -powerdns_record_cname string t PowerDNS record type CNAME values PowerDNS \N f f \\A.*\\Z \N \N -powerdns_record_mx string t PowerDNS record type MX values. PowerDNS \N f f \\A.*\\Z \N \N -powerdns_record_sshfp string t PowerDNS record type SSHFP values. PowerDNS \N f f \\A.*\\Z \N \N -powerdns_record_txt string t PowerDNS record type TXT values. PowerDNS \N f f \\A.*\\Z \N \N -powerdns_record relation t (Host)Name of the record this mapping belongs to. PowerDNS \N f f \\A.*\\Z \N powerdns_record -\. - - --- --- Data for Name: auth_group; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.auth_group (id, name) FROM stdin; -\. - - --- --- Data for Name: auth_group_permissions; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.auth_group_permissions (id, group_id, permission_id) FROM stdin; -\. - - --- --- Data for Name: auth_permission; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.auth_permission (id, name, content_type_id, codename) FROM stdin; -1 Can add log entry 1 add_logentry -2 Can change log entry 1 change_logentry -3 Can delete log entry 1 delete_logentry -4 Can view log entry 1 view_logentry -5 Can add permission 2 add_permission -6 Can change permission 2 change_permission -7 Can delete permission 2 delete_permission -8 Can view permission 2 view_permission -9 Can add group 3 add_group -10 Can change group 3 change_group -11 Can delete group 3 delete_group -12 Can view group 3 view_group -13 Can add user 4 add_user -14 Can change user 4 change_user -15 Can delete user 4 delete_user -16 Can view user 4 view_user -17 Can add content type 5 add_contenttype -18 Can change content type 5 change_contenttype -19 Can delete content type 5 delete_contenttype -20 Can view content type 5 view_contenttype -21 Can add session 6 add_session -22 Can change session 6 change_session -23 Can delete session 6 delete_session -24 Can view session 6 view_session -25 Can add site 7 add_site -26 Can change site 7 change_site -27 Can delete site 7 delete_site -28 Can view site 7 view_site -29 Can add access control group 8 add_accesscontrolgroup -30 Can change access control group 8 change_accesscontrolgroup -31 Can delete access control group 8 delete_accesscontrolgroup -32 Can view access control group 8 view_accesscontrolgroup -33 Can add lock 9 add_lock -34 Can change lock 9 change_lock -35 Can delete lock 9 delete_lock -36 Can view lock 9 view_lock -37 Can add application 10 add_application -38 Can change application 10 change_application -39 Can delete application 10 delete_application -40 Can view application 10 view_application -41 Can add public key 11 add_publickey -42 Can change public key 11 change_publickey -43 Can delete public key 11 delete_publickey -44 Can view public key 11 view_publickey -45 Can add collection 12 add_collection -46 Can change collection 12 change_collection -47 Can delete collection 12 delete_collection -48 Can view collection 12 view_collection -49 Can add numeric 13 add_numeric -50 Can change numeric 13 change_numeric -51 Can delete numeric 13 delete_numeric -52 Can view numeric 13 view_numeric -53 Can add relation 14 add_relation -54 Can change relation 14 change_relation -55 Can delete relation 14 delete_relation -56 Can view relation 14 view_relation -57 Can add template 15 add_template -58 Can change template 15 change_template -59 Can delete template 15 delete_template -60 Can view template 15 view_template -61 Can add variation 16 add_variation -62 Can change variation 16 change_variation -63 Can delete variation 16 delete_variation -64 Can view variation 16 view_variation -65 Can add attribute 17 add_attribute -66 Can change attribute 17 change_attribute -67 Can delete attribute 17 delete_attribute -68 Can view attribute 17 view_attribute -69 Can add change 18 add_change -70 Can change change 18 change_change -71 Can delete change 18 delete_change -72 Can view change 18 view_change -73 Can add change add 19 add_changeadd -74 Can change change add 19 change_changeadd -75 Can delete change add 19 delete_changeadd -76 Can view change add 19 view_changeadd -77 Can add change commit 20 add_changecommit -78 Can change change commit 20 change_changecommit -79 Can delete change commit 20 delete_changecommit -80 Can view change commit 20 view_changecommit -81 Can add change delete 21 add_changedelete -82 Can change change delete 21 change_changedelete -83 Can delete change delete 21 delete_changedelete -84 Can view change delete 21 view_changedelete -85 Can add change update 22 add_changeupdate -86 Can change change update 22 change_changeupdate -87 Can delete change update 22 delete_changeupdate -88 Can view change update 22 view_changeupdate -89 Can add server 23 add_server -90 Can change server 23 change_server -91 Can delete server 23 delete_server -92 Can view server 23 view_server -93 Can add server boolean attribute 24 add_serverbooleanattribute -94 Can change server boolean attribute 24 change_serverbooleanattribute -95 Can delete server boolean attribute 24 delete_serverbooleanattribute -96 Can view server boolean attribute 24 view_serverbooleanattribute -97 Can add server date attribute 25 add_serverdateattribute -98 Can change server date attribute 25 change_serverdateattribute -99 Can delete server date attribute 25 delete_serverdateattribute -100 Can view server date attribute 25 view_serverdateattribute -101 Can add server inet attribute 26 add_serverinetattribute -102 Can change server inet attribute 26 change_serverinetattribute -103 Can delete server inet attribute 26 delete_serverinetattribute -104 Can view server inet attribute 26 view_serverinetattribute -105 Can add server mac address attribute 27 add_servermacaddressattribute -106 Can change server mac address attribute 27 change_servermacaddressattribute -107 Can delete server mac address attribute 27 delete_servermacaddressattribute -108 Can view server mac address attribute 27 view_servermacaddressattribute -109 Can add server number attribute 28 add_servernumberattribute -110 Can change server number attribute 28 change_servernumberattribute -111 Can delete server number attribute 28 delete_servernumberattribute -112 Can view server number attribute 28 view_servernumberattribute -113 Can add server relation attribute 29 add_serverrelationattribute -114 Can change server relation attribute 29 change_serverrelationattribute -115 Can delete server relation attribute 29 delete_serverrelationattribute -116 Can view server relation attribute 29 view_serverrelationattribute -117 Can add server string attribute 30 add_serverstringattribute -118 Can change server string attribute 30 change_serverstringattribute -119 Can delete server string attribute 30 delete_serverstringattribute -120 Can view server string attribute 30 view_serverstringattribute -121 Can add servertype 31 add_servertype -122 Can change servertype 31 change_servertype -123 Can delete servertype 31 delete_servertype -124 Can view servertype 31 view_servertype -125 Can add servertype attribute 32 add_servertypeattribute -126 Can change servertype attribute 32 change_servertypeattribute -127 Can delete servertype attribute 32 delete_servertypeattribute -128 Can view servertype attribute 32 view_servertypeattribute -129 Can add server date time attribute 33 add_serverdatetimeattribute -130 Can change server date time attribute 33 change_serverdatetimeattribute -131 Can delete server date time attribute 33 delete_serverdatetimeattribute -132 Can view server date time attribute 33 view_serverdatetimeattribute -133 Can add domain 34 add_domain -134 Can change domain 34 change_domain -135 Can delete domain 34 delete_domain -136 Can view domain 34 view_domain -137 Can add record 35 add_record -138 Can change record 35 change_record -139 Can delete record 35 delete_record -140 Can view record 35 view_record -\. - - --- --- Data for Name: auth_user; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.auth_user (id, password, last_login, is_superuser, username, first_name, last_name, email, is_staff, is_active, date_joined) FROM stdin; -1 pbkdf2_sha256$260000$S8cpRd2tzrJ0ASuK2A5e0T$l8mFdBOJHRK9viRrIU7Ze7mSZl0NridmQ2J0PYpe4NI= 2022-05-17 06:35:28.055568+00 t serveradmin t t 2022-05-17 06:35:13.572801+00 -\. - - --- --- Data for Name: auth_user_groups; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.auth_user_groups (id, user_id, group_id) FROM stdin; -\. - - --- --- Data for Name: auth_user_user_permissions; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.auth_user_user_permissions (id, user_id, permission_id) FROM stdin; -\. - - --- --- Data for Name: django_admin_log; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.django_admin_log (id, action_time, object_id, object_repr, action_flag, change_message, content_type_id, user_id) FROM stdin; -1 2022-05-17 07:27:25.320719+00 domain domain 3 31 1 -2 2022-05-17 07:27:25.388206+00 record record 3 31 1 -3 2022-05-17 07:27:31.915892+00 content content 3 17 1 -4 2022-05-17 07:27:31.91997+00 record_type record_type 3 17 1 -5 2022-05-17 07:27:31.921707+00 ttl ttl 3 17 1 -6 2022-05-17 07:27:31.923474+00 type type 3 17 1 -7 2022-05-17 07:28:22.832836+00 powerdns_domain powerdns_domain 1 [{"added": {}}] 31 1 -8 2022-05-17 07:28:51.211721+00 powerdns_record powerdns_record 1 [{"added": {}}] 31 1 -9 2022-05-17 07:30:17.761095+00 powerdns_domain powerdns_domain 1 [{"added": {}}] 17 1 -10 2022-05-17 07:30:34.956898+00 powerdns_record powerdns_record 2 [{"added": {"name": "servertype attribute", "object": "powerdns_record - powerdns_domain"}}] 31 1 -11 2022-05-17 07:33:14.685549+00 powerdns_domain_type powerdns_domain_type 1 [{"added": {}}] 17 1 -12 2022-05-17 07:33:36.183346+00 powerdns_domain powerdns_domain 2 [{"added": {"name": "servertype attribute", "object": "powerdns_domain - powerdns_domain_type"}}] 31 1 -13 2022-05-17 07:36:28.061007+00 aaaa aaaa 1 [{"added": {}}] 17 1 -14 2022-05-17 07:36:35.567053+00 aaaa aaaa 3 17 1 -15 2022-05-17 07:37:27.218069+00 powerdns_record_a powerdns_record_a 1 [{"added": {}}] 17 1 -16 2022-05-17 07:37:54.851655+00 powerdns_record_aaaa powerdns_record_aaaa 1 [{"added": {}}] 17 1 -17 2022-05-17 07:38:24.399671+00 powerdns_record_cname powerdns_record_cname 1 [{"added": {}}] 17 1 -18 2022-05-17 07:39:05.772956+00 powerdns_record_txt powerdns_record_txt 1 [{"added": {}}] 17 1 -19 2022-05-17 07:39:16.042256+00 powerdns_record_aaaa powerdns_record_aaaa 2 [{"changed": {"fields": ["Multi"]}}] 17 1 -20 2022-05-17 07:40:02.769861+00 powerdns_record_sshfp powerdns_record_sshfp 1 [{"added": {}}] 17 1 -21 2022-05-17 07:40:33.943339+00 powerdns_record_mx powerdns_record_mx 1 [{"added": {}}] 17 1 -22 2022-05-17 07:48:02.335275+00 powerdns_record powerdns_record 2 [{"added": {"name": "servertype attribute", "object": "powerdns_record - powerdns_record_cname"}}, {"added": {"name": "servertype attribute", "object": "powerdns_record - powerdns_record_mx"}}, {"added": {"name": "servertype attribute", "object": "powerdns_record - powerdns_record_sshfp"}}, {"added": {"name": "servertype attribute", "object": "powerdns_record - powerdns_record_txt"}}] 31 1 -23 2022-05-17 07:53:40.032845+00 localbalancer localbalancer 1 [{"added": {}}] 31 1 -24 2022-05-17 07:54:31.191731+00 vm vm 1 [{"added": {}}] 31 1 -25 2022-05-17 07:55:33.82657+00 localbalancer localbalancer 3 31 1 -26 2022-05-17 07:55:44.694069+00 loadbalancer loadbalancer 1 [{"added": {}}] 31 1 -27 2022-05-17 07:57:42.306717+00 vm vm 2 [{"added": {"name": "servertype attribute", "object": "vm - powerdns_domain"}}] 31 1 -28 2022-05-17 07:57:47.0651+00 vm vm 2 [] 31 1 -29 2022-05-17 07:57:51.936241+00 loadbalancer loadbalancer 2 [{"added": {"name": "servertype attribute", "object": "loadbalancer - powerdns_domain"}}] 31 1 -30 2022-05-17 08:00:25.962015+00 powerdns_record powerdns_record 1 [{"added": {}}] 17 1 -31 2022-05-17 08:00:43.948638+00 vm vm 2 [{"added": {"name": "servertype attribute", "object": "vm - powerdns_record"}}] 31 1 -32 2022-05-17 08:00:50.37534+00 loadbalancer loadbalancer 2 [{"added": {"name": "servertype attribute", "object": "loadbalancer - powerdns_record"}}] 31 1 -33 2022-05-17 08:01:24.646347+00 loadbalancer loadbalancer 2 [{"deleted": {"name": "servertype attribute", "object": "loadbalancer - powerdns_record"}}] 31 1 -34 2022-05-17 08:01:29.288594+00 vm vm 2 [{"deleted": {"name": "servertype attribute", "object": "vm - powerdns_record"}}] 31 1 -35 2022-05-17 08:01:39.501894+00 powerdns_record powerdns_record 3 17 1 -36 2022-05-17 08:02:08.578078+00 powerdns_record_a powerdns_record_a 3 17 1 -37 2022-05-17 08:02:13.087703+00 powerdns_record_aaaa powerdns_record_aaaa 3 17 1 -38 2022-05-17 08:04:32.061+00 powerdns_record powerdns_record 1 [{"added": {}}] 17 1 -39 2022-05-17 08:04:47.650048+00 loadbalancer loadbalancer 2 [{"added": {"name": "servertype attribute", "object": "loadbalancer - powerdns_record"}}] 31 1 -40 2022-05-17 08:04:55.894222+00 vm vm 2 [{"added": {"name": "servertype attribute", "object": "vm - powerdns_record"}}] 31 1 -41 2022-05-17 08:05:44.883393+00 powerdns_record_a powerdns_record_a 1 [{"added": {}}] 17 1 -42 2022-05-17 08:05:55.941769+00 powerdns_record powerdns_record 2 [{"added": {"name": "servertype attribute", "object": "powerdns_record - powerdns_record_a"}}] 31 1 -43 2022-05-17 09:45:56.474128+00 powerdns_record_a powerdns_record_a 3 17 1 -44 2022-05-17 09:46:32.334165+00 powerdns_record_a powerdns_record_a 1 [{"added": {}}] 17 1 -45 2022-05-17 09:47:04.556342+00 powerdns_record_aaaa powerdns_record_aaaa 1 [{"added": {}}] 17 1 -46 2022-05-17 09:47:18.232375+00 powerdns_record_a powerdns_record_a 2 [{"changed": {"fields": ["Hovertext"]}}] 17 1 -47 2022-05-17 09:47:23.702347+00 powerdns_record_cname powerdns_record_cname 2 [{"changed": {"fields": ["Hovertext"]}}] 17 1 -48 2022-05-17 09:47:29.628822+00 powerdns_record_mx powerdns_record_mx 2 [{"changed": {"fields": ["Hovertext"]}}] 17 1 -49 2022-05-17 09:47:34.945482+00 powerdns_record_sshfp powerdns_record_sshfp 2 [{"changed": {"fields": ["Hovertext"]}}] 17 1 -50 2022-05-17 09:47:40.663727+00 powerdns_record_txt powerdns_record_txt 2 [{"changed": {"fields": ["Hovertext"]}}] 17 1 -51 2022-05-17 09:48:01.355664+00 powerdns_record powerdns_record 2 [{"changed": {"fields": ["Hovertext"]}}] 17 1 -52 2022-05-17 09:48:46.685533+00 powerdns_record powerdns_record 2 [{"changed": {"fields": ["Hovertext"]}}] 17 1 -53 2022-05-17 09:48:56.520812+00 powerdns_record powerdns_record 2 [{"changed": {"fields": ["Hovertext"]}}] 17 1 -\. - - --- --- Data for Name: django_content_type; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.django_content_type (id, app_label, model) FROM stdin; -1 admin logentry -2 auth permission -3 auth group -4 auth user -5 contenttypes contenttype -6 sessions session -7 sites site -8 access_control accesscontrolgroup -9 api lock -10 apps application -11 apps publickey -12 graphite collection -13 graphite numeric -14 graphite relation -15 graphite template -16 graphite variation -17 serverdb attribute -18 serverdb change -19 serverdb changeadd -20 serverdb changecommit -21 serverdb changedelete -22 serverdb changeupdate -23 serverdb server -24 serverdb serverbooleanattribute -25 serverdb serverdateattribute -26 serverdb serverinetattribute -27 serverdb servermacaddressattribute -28 serverdb servernumberattribute -29 serverdb serverrelationattribute -30 serverdb serverstringattribute -31 serverdb servertype -32 serverdb servertypeattribute -33 serverdb serverdatetimeattribute -34 powerdns domain -35 powerdns record -\. - - --- --- Data for Name: django_migrations; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.django_migrations (id, app, name, applied) FROM stdin; -1 contenttypes 0001_initial 2022-05-17 06:34:57.845554+00 -2 auth 0001_initial 2022-05-17 06:34:57.918879+00 -3 apps 0001_initial 2022-05-17 06:34:58.204762+00 -4 serverdb 0001_initial 2022-05-17 06:34:58.971276+00 -5 access_control 0001_initial 2022-05-17 06:34:59.317345+00 -6 access_control 0002_whitelist_blacklist_toggle 2022-05-17 06:34:59.383488+00 -7 admin 0001_initial 2022-05-17 06:34:59.416129+00 -8 admin 0002_logentry_remove_auto_add 2022-05-17 06:34:59.42916+00 -9 admin 0003_logentry_add_action_flag_choices 2022-05-17 06:34:59.441726+00 -10 api 0001_api_lock 2022-05-17 06:34:59.452164+00 -11 apps 0002_public_key_support 2022-05-17 06:34:59.481763+00 -12 apps 0003_public_key_length 2022-05-17 06:34:59.493769+00 -13 apps 0004_application_last_login 2022-05-17 06:34:59.507093+00 -14 contenttypes 0002_remove_content_type_name 2022-05-17 06:34:59.539501+00 -15 auth 0002_alter_permission_name_max_length 2022-05-17 06:34:59.560884+00 -16 auth 0003_alter_user_email_max_length 2022-05-17 06:34:59.583112+00 -17 auth 0004_alter_user_username_opts 2022-05-17 06:34:59.604316+00 -18 auth 0005_alter_user_last_login_null 2022-05-17 06:34:59.626532+00 -19 auth 0006_require_contenttypes_0002 2022-05-17 06:34:59.628807+00 -20 auth 0007_alter_validators_add_error_messages 2022-05-17 06:34:59.650554+00 -21 auth 0008_alter_user_username_max_length 2022-05-17 06:34:59.676628+00 -22 auth 0009_alter_user_last_name_max_length 2022-05-17 06:34:59.698207+00 -23 auth 0010_alter_group_name_max_length 2022-05-17 06:34:59.721159+00 -24 auth 0011_update_proxy_permissions 2022-05-17 06:34:59.74182+00 -25 auth 0012_alter_user_first_name_max_length 2022-05-17 06:34:59.764702+00 -26 graphite 0001_initial 2022-05-17 06:34:59.992088+00 -27 graphite 0002_template_and_variation_name_validation 2022-05-17 06:35:00.003385+00 -28 powerdns 0001_initial 2022-05-17 06:35:00.008709+00 -29 powerdns 0002_powerdns_schema 2022-05-17 06:35:00.011773+00 -30 serverdb 0002_lookup_constraints 2022-05-17 06:35:00.018437+00 -31 serverdb 0003_server_indexing 2022-05-17 06:35:00.07827+00 -32 serverdb 0004_attribute_value_constraints 2022-05-17 06:35:00.086567+00 -33 serverdb 0005_attribute_clone 2022-05-17 06:35:00.09092+00 -34 serverdb 0006_datetime_datatype 2022-05-17 06:35:00.18544+00 -35 serverdb 0007_hostname_regex_hyphens 2022-05-17 06:35:00.196393+00 -36 serverdb 0008_hostname_length_254 2022-05-17 06:35:00.209346+00 -37 serverdb 0009_servertype_and_attribute_definitions 2022-05-17 06:35:00.255978+00 -38 sessions 0001_initial 2022-05-17 06:35:00.267282+00 -39 sites 0001_initial 2022-05-17 06:35:00.273416+00 -40 sites 0002_alter_domain_unique 2022-05-17 06:35:00.281149+00 -\. - - --- --- Data for Name: django_session; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.django_session (session_key, session_data, expire_date) FROM stdin; -ib3c7lk0xyp44s8pg75ghmb8ikrs279j .eJxtkNFOwzAMRf8lTyBNJWm7dqvEy3jmCxCK3NilGW1SJemmCvHvuGKgDfESxffeHNv5EBrm1Os5UtAWRSOU2FxrLZh3cquBR3BvPjPepWDbbI1kFzdmzx5pOFyyN4AeYs-vu7yTXYdo9oWSivjAqtrVpt0iQFHmrSpLqqXaF1uuOsJ6RyWgVFVNdbsrGMpMb_w4DZRINCnMdKtpHgEWHQmC4Zb5Vv7rczkCzywadQlEGsgk0XQwRGZGOJGGtG45J4o_rQY72rRiNyJRGHkn6_jitJ0en_hTwDrCw3KXg5RN86Cqe5459v7sbmAvovcxORiJ7V_CGqVwopCWaTUmf6aALupAxge8VtCP3Er_DX7L4vXzCxFbomg:1nt6Jr:euR414nBWtWH6bUvwtcFCaY0EwRXRvIRkPaxpGz_XTI 2022-06-06 11:33:51.251431+00 -\. - - --- --- Data for Name: django_site; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.django_site (id, domain, name) FROM stdin; -1 example.com example.com -\. - - --- --- Data for Name: graphite_collection; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.graphite_collection (id, name, params, sort_order, overview, created_at) FROM stdin; -\. - - --- --- Data for Name: graphite_numeric; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.graphite_numeric (id, params, sort_order, attribute_id, collection_id) FROM stdin; -\. - - --- --- Data for Name: graphite_relation; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.graphite_relation (id, sort_order, attribute_id, collection_id) FROM stdin; -\. - - --- --- Data for Name: graphite_template; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.graphite_template (id, name, params, sort_order, description, foreach_path, collection_id) FROM stdin; -\. - - --- --- Data for Name: graphite_variation; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.graphite_variation (id, name, params, sort_order, summarize_interval, collection_id) FROM stdin; -\. - - --- --- Data for Name: server; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.server (server_id, hostname, intern_ip, servertype_id) FROM stdin; -7 sunrisevillage.de \N powerdns_domain -8 de1.sunrisevillage.de \N powerdns_record -9 host-1.ig.local 10.0.0.1 vm -10 hostlb.innogames.net 212.48.98.12 loadbalancer -11 ig.local \N powerdns_domain -12 innogames.net \N powerdns_domain -13 *.sunrisevillage.de \N powerdns_record -14 hostlb2.innogames.net 212.32.32.10 loadbalancer -\. - - --- --- Data for Name: server_boolean_attribute; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.server_boolean_attribute (id, attribute_id, server_id) FROM stdin; -\. - - --- --- Data for Name: server_date_attribute; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.server_date_attribute (id, value, attribute_id, server_id) FROM stdin; -\. - - --- --- Data for Name: server_datetime_attribute; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.server_datetime_attribute (id, value, attribute_id, server_id) FROM stdin; -\. - - --- --- Data for Name: server_inet_attribute; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.server_inet_attribute (id, value, attribute_id, server_id) FROM stdin; -\. - - --- --- Data for Name: server_macaddr_attribute; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.server_macaddr_attribute (id, value, attribute_id, server_id) FROM stdin; -\. - - --- --- Data for Name: server_number_attribute; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.server_number_attribute (id, value, attribute_id, server_id) FROM stdin; -\. - - --- --- Data for Name: server_relation_attribute; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.server_relation_attribute (id, attribute_id, server_id, value) FROM stdin; -4 powerdns_domain 8 7 -5 powerdns_domain 9 11 -6 powerdns_domain 10 12 -7 powerdns_record 10 8 -8 powerdns_domain 13 7 -9 powerdns_record 10 13 -10 powerdns_record 14 8 -\. - - --- --- Data for Name: server_string_attribute; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.server_string_attribute (id, value, attribute_id, server_id) FROM stdin; -8 NATIVE powerdns_domain_type 7 -9 foo powerdns_record_txt 8 -10 NATIVE powerdns_domain_type 11 -11 NATIVE powerdns_domain_type 12 -13 10 a powerdns_record_mx 13 -14 20 b powerdns_record_mx 13 -15 30 c powerdns_record_mx 13 -\. - - --- --- Data for Name: serverdb_change; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.serverdb_change (id, change_on, changes_json, app_id, user_id) FROM stdin; -\. - - --- --- Data for Name: serverdb_changeadd; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.serverdb_changeadd (id, server_id, attributes_json, commit_id) FROM stdin; -1 1 {"object_id": 1, "hostname": "ig.local", "intern_ip": null, "servertype": "domain", "type": "NATIVE"} 1 -2 2 {"object_id": 2, "hostname": "ns1", "intern_ip": null, "servertype": "record", "content": "localhost", "domain": "ig.local", "record_type": "NS", "ttl": 300} 2 -3 3 {"object_id": 3, "hostname": "soa", "intern_ip": null, "servertype": "record", "content": "localhost hostmaster.ig.local", "domain": "ig.local", "record_type": "SOA", "ttl": 300} 3 -4 5 {"object_id": 5, "hostname": "host.ig.local", "intern_ip": null, "servertype": "record", "content": "bingo", "domain": "ig.local", "record_type": "TXT", "ttl": 300} 5 -5 7 {"object_id": 7, "hostname": "sunrisevillage.de", "intern_ip": null, "servertype": "powerdns_domain", "powerdns_domain_type": "NATIVE"} 9 -6 8 {"object_id": 8, "hostname": "de1.sunrisevillage.de", "intern_ip": null, "servertype": "powerdns_record", "powerdns_domain": "sunrisevillage.de", "powerdns_record_cname": [], "powerdns_record_mx": [], "powerdns_record_sshfp": [], "powerdns_record_txt": ["foo"]} 10 -7 9 {"object_id": 9, "hostname": "host-1.ig.local", "intern_ip": "10.0.0.1", "servertype": "vm"} 11 -8 10 {"object_id": 10, "hostname": "hostlb.innogames.net", "intern_ip": "212.48.98.12", "servertype": "loadbalancer"} 12 -9 11 {"object_id": 11, "hostname": "ig.local", "intern_ip": null, "servertype": "powerdns_domain", "powerdns_domain_type": "NATIVE"} 13 -10 12 {"object_id": 12, "hostname": "innogames.net", "intern_ip": null, "servertype": "powerdns_domain", "powerdns_domain_type": "NATIVE"} 14 -11 13 {"object_id": 13, "hostname": "*.sunrisevillage.de", "intern_ip": null, "servertype": "powerdns_record", "powerdns_domain": "sunrisevillage.de", "powerdns_record_a": null, "powerdns_record_cname": [], "powerdns_record_mx": ["lololol"], "powerdns_record_sshfp": [], "powerdns_record_txt": []} 17 -12 14 {"object_id": 14, "hostname": "hostlb2.innogames.net", "intern_ip": "212.32.32.10", "servertype": "loadbalancer", "powerdns_domain": null, "powerdns_record": []} 20 -\. - - --- --- Data for Name: serverdb_changecommit; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.serverdb_changecommit (id, change_on, app_id, user_id) FROM stdin; -1 2022-05-17 06:37:14.641181+00 \N 1 -2 2022-05-17 06:37:56.046079+00 \N 1 -3 2022-05-17 06:40:04.022441+00 \N 1 -5 2022-05-17 06:43:01.063153+00 \N 1 -8 2022-05-17 07:27:17.050319+00 \N 1 -9 2022-05-17 07:48:30.383152+00 \N 1 -10 2022-05-17 07:51:51.747652+00 \N 1 -11 2022-05-17 07:55:09.042663+00 \N 1 -12 2022-05-17 07:56:11.468567+00 \N 1 -13 2022-05-17 07:56:56.495335+00 \N 1 -14 2022-05-17 07:57:07.869845+00 \N 1 -15 2022-05-17 07:58:06.909091+00 \N 1 -16 2022-05-17 08:06:39.892294+00 \N 1 -17 2022-05-17 08:09:19.949481+00 \N 1 -18 2022-05-17 08:09:42.724251+00 \N 1 -19 2022-05-19 14:29:51.731899+00 \N 1 -20 2022-05-19 14:40:23.74718+00 \N 1 -21 2022-05-19 14:41:02.421843+00 \N 1 -\. - - --- --- Data for Name: serverdb_changedelete; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.serverdb_changedelete (id, server_id, attributes_json, commit_id) FROM stdin; -1 1 {"object_id": 1, "hostname": "ig.local", "intern_ip": null, "servertype": "domain", "type": "NATIVE"} 8 -2 2 {"object_id": 2, "hostname": "ns1", "intern_ip": null, "servertype": "record", "content": "localhost", "domain": "ig.local", "record_type": "NS", "ttl": 300} 8 -3 3 {"object_id": 3, "hostname": "soa", "intern_ip": null, "servertype": "record", "content": "localhost hostmaster.ig.local", "domain": "ig.local", "record_type": "SOA", "ttl": 300} 8 -4 5 {"object_id": 5, "hostname": "host.ig.local", "intern_ip": null, "servertype": "record", "content": "bingo", "domain": "ig.local", "record_type": "TXT", "ttl": 300} 8 -\. - - --- --- Data for Name: serverdb_changeupdate; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.serverdb_changeupdate (id, server_id, updates_json, commit_id) FROM stdin; -1 9 {"powerdns_domain": {"action": "update", "new": "ig.local", "old": null}, "object_id": 9} 15 -2 10 {"powerdns_domain": {"action": "update", "new": "innogames.net", "old": null}, "object_id": 10} 15 -3 10 {"powerdns_record": {"action": "multi", "add": ["de1.sunrisevillage.de"], "remove": []}, "object_id": 10} 16 -4 10 {"powerdns_record": {"action": "multi", "add": ["*.sunrisevillage.de"], "remove": []}, "object_id": 10} 18 -5 13 {"powerdns_record_mx": {"action": "multi", "add": ["10 a", "20 b", "30 c"], "remove": ["lololol"]}, "object_id": 13} 19 -6 14 {"powerdns_record": {"action": "multi", "add": ["de1.sunrisevillage.de"], "remove": []}, "object_id": 14} 21 -\. - - --- --- Data for Name: servertype; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.servertype (servertype_id, description, ip_addr_type) FROM stdin; -powerdns_domain PowerDNS Domain null -loadbalancer LB-Pool loadbalancer -vm Linux Kernel-based Virtual Machine host -powerdns_record PowerDNS Record null -\. - - --- --- Data for Name: servertype_attribute; Type: TABLE DATA; Schema: public; Owner: serveradmin --- - -COPY public.servertype_attribute (id, required, default_value, default_visible, attribute_id, consistent_via_attribute_id, related_via_attribute_id, servertype_id) FROM stdin; -7 t \N f powerdns_domain \N \N powerdns_record -8 t NATIVE f powerdns_domain_type \N \N powerdns_domain -9 f \N f powerdns_record_cname \N \N powerdns_record -10 f \N f powerdns_record_mx \N \N powerdns_record -11 f \N f powerdns_record_sshfp \N \N powerdns_record -12 f \N f powerdns_record_txt \N \N powerdns_record -13 f \N f powerdns_domain \N \N vm -14 f \N f powerdns_domain \N \N loadbalancer -17 f \N f powerdns_record \N \N loadbalancer -18 f \N f powerdns_record \N \N vm -\. - - --- --- Name: access_control_group_applications_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.access_control_group_applications_id_seq', 1, false); - - --- --- Name: access_control_group_attributes_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.access_control_group_attributes_id_seq', 1, false); - - --- --- Name: access_control_group_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.access_control_group_id_seq', 1, false); - - --- --- Name: access_control_group_members_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.access_control_group_members_id_seq', 1, false); - - --- --- Name: api_lock_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.api_lock_id_seq', 1, false); - - --- --- Name: apps_application_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.apps_application_id_seq', 1, true); - - --- --- Name: auth_group_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.auth_group_id_seq', 1, false); - - --- --- Name: auth_group_permissions_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.auth_group_permissions_id_seq', 1, false); - - --- --- Name: auth_permission_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.auth_permission_id_seq', 140, true); - - --- --- Name: auth_user_groups_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.auth_user_groups_id_seq', 1, false); - - --- --- Name: auth_user_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.auth_user_id_seq', 1, true); - - --- --- Name: auth_user_user_permissions_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.auth_user_user_permissions_id_seq', 1, false); - - --- --- Name: django_admin_log_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.django_admin_log_id_seq', 53, true); - - --- --- Name: django_content_type_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.django_content_type_id_seq', 35, true); - - --- --- Name: django_migrations_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.django_migrations_id_seq', 40, true); - - --- --- Name: django_site_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.django_site_id_seq', 1, true); - - --- --- Name: graphite_collection_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.graphite_collection_id_seq', 1, false); - - --- --- Name: graphite_numeric_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.graphite_numeric_id_seq', 1, false); - - --- --- Name: graphite_relation_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.graphite_relation_id_seq', 1, false); - - --- --- Name: graphite_template_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.graphite_template_id_seq', 1, false); - - --- --- Name: graphite_variation_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.graphite_variation_id_seq', 1, false); - - --- --- Name: server_boolean_attribute_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.server_boolean_attribute_id_seq', 1, false); - - --- --- Name: server_date_attribute_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.server_date_attribute_id_seq', 1, false); - - --- --- Name: server_datetime_attribute_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.server_datetime_attribute_id_seq', 1, false); - - --- --- Name: server_inet_attribute_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.server_inet_attribute_id_seq', 1, false); - - --- --- Name: server_macaddr_attribute_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.server_macaddr_attribute_id_seq', 1, false); - - --- --- Name: server_number_attribute_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.server_number_attribute_id_seq', 3, true); - - --- --- Name: server_relation_attribute_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.server_relation_attribute_id_seq', 10, true); - - --- --- Name: server_server_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.server_server_id_seq', 14, true); - - --- --- Name: server_string_attribute_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.server_string_attribute_id_seq', 15, true); - - --- --- Name: serverdb_change_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.serverdb_change_id_seq', 1, false); - - --- --- Name: serverdb_changeadd_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.serverdb_changeadd_id_seq', 12, true); - - --- --- Name: serverdb_changecommit_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.serverdb_changecommit_id_seq', 21, true); - - --- --- Name: serverdb_changedelete_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.serverdb_changedelete_id_seq', 4, true); - - --- --- Name: serverdb_changeupdate_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.serverdb_changeupdate_id_seq', 6, true); - - --- --- Name: servertype_attribute_id_seq; Type: SEQUENCE SET; Schema: public; Owner: serveradmin --- - -SELECT pg_catalog.setval('public.servertype_attribute_id_seq', 19, true); - - --- --- Name: access_control_group_applications access_control_group_app_accesscontrolgroup_id_ap_ad625f80_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_applications - ADD CONSTRAINT access_control_group_app_accesscontrolgroup_id_ap_ad625f80_uniq UNIQUE (accesscontrolgroup_id, application_id); - - --- --- Name: access_control_group_applications access_control_group_applications_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_applications - ADD CONSTRAINT access_control_group_applications_pkey PRIMARY KEY (id); - - --- --- Name: access_control_group_attributes access_control_group_att_accesscontrolgroup_id_at_5c9b3a4c_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_attributes - ADD CONSTRAINT access_control_group_att_accesscontrolgroup_id_at_5c9b3a4c_uniq UNIQUE (accesscontrolgroup_id, attribute_id); - - --- --- Name: access_control_group_attributes access_control_group_attributes_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_attributes - ADD CONSTRAINT access_control_group_attributes_pkey PRIMARY KEY (id); - - --- --- Name: access_control_group_members access_control_group_mem_accesscontrolgroup_id_us_3acba33e_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_members - ADD CONSTRAINT access_control_group_mem_accesscontrolgroup_id_us_3acba33e_uniq UNIQUE (accesscontrolgroup_id, user_id); - - --- --- Name: access_control_group_members access_control_group_members_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_members - ADD CONSTRAINT access_control_group_members_pkey PRIMARY KEY (id); - - --- --- Name: access_control_group access_control_group_name_key; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group - ADD CONSTRAINT access_control_group_name_key UNIQUE (name); - - --- --- Name: access_control_group access_control_group_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group - ADD CONSTRAINT access_control_group_pkey PRIMARY KEY (id); - - --- --- Name: api_lock api_lock_hash_sum_key; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.api_lock - ADD CONSTRAINT api_lock_hash_sum_key UNIQUE (hash_sum); - - --- --- Name: api_lock api_lock_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.api_lock - ADD CONSTRAINT api_lock_pkey PRIMARY KEY (id); - - --- --- Name: apps_application apps_application_app_id_key; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.apps_application - ADD CONSTRAINT apps_application_app_id_key UNIQUE (app_id); - - --- --- Name: apps_application apps_application_auth_token_key; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.apps_application - ADD CONSTRAINT apps_application_auth_token_key UNIQUE (auth_token); - - --- --- Name: apps_application apps_application_name_key; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.apps_application - ADD CONSTRAINT apps_application_name_key UNIQUE (name); - - --- --- Name: apps_application apps_application_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.apps_application - ADD CONSTRAINT apps_application_pkey PRIMARY KEY (id); - - --- --- Name: apps_publickey apps_publickey_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.apps_publickey - ADD CONSTRAINT apps_publickey_pkey PRIMARY KEY (key_base64); - - --- --- Name: attribute attribute_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.attribute - ADD CONSTRAINT attribute_pkey PRIMARY KEY (attribute_id); - - --- --- Name: auth_group auth_group_name_key; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_group - ADD CONSTRAINT auth_group_name_key UNIQUE (name); - - --- --- Name: auth_group_permissions auth_group_permissions_group_id_permission_id_0cd325b0_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_group_permissions - ADD CONSTRAINT auth_group_permissions_group_id_permission_id_0cd325b0_uniq UNIQUE (group_id, permission_id); - - --- --- Name: auth_group_permissions auth_group_permissions_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_group_permissions - ADD CONSTRAINT auth_group_permissions_pkey PRIMARY KEY (id); - - --- --- Name: auth_group auth_group_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_group - ADD CONSTRAINT auth_group_pkey PRIMARY KEY (id); - - --- --- Name: auth_permission auth_permission_content_type_id_codename_01ab375a_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_permission - ADD CONSTRAINT auth_permission_content_type_id_codename_01ab375a_uniq UNIQUE (content_type_id, codename); - - --- --- Name: auth_permission auth_permission_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_permission - ADD CONSTRAINT auth_permission_pkey PRIMARY KEY (id); - - --- --- Name: auth_user_groups auth_user_groups_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user_groups - ADD CONSTRAINT auth_user_groups_pkey PRIMARY KEY (id); - - --- --- Name: auth_user_groups auth_user_groups_user_id_group_id_94350c0c_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user_groups - ADD CONSTRAINT auth_user_groups_user_id_group_id_94350c0c_uniq UNIQUE (user_id, group_id); - - --- --- Name: auth_user auth_user_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user - ADD CONSTRAINT auth_user_pkey PRIMARY KEY (id); - - --- --- Name: auth_user_user_permissions auth_user_user_permissions_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user_user_permissions - ADD CONSTRAINT auth_user_user_permissions_pkey PRIMARY KEY (id); - - --- --- Name: auth_user_user_permissions auth_user_user_permissions_user_id_permission_id_14a6b632_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user_user_permissions - ADD CONSTRAINT auth_user_user_permissions_user_id_permission_id_14a6b632_uniq UNIQUE (user_id, permission_id); - - --- --- Name: auth_user auth_user_username_key; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user - ADD CONSTRAINT auth_user_username_key UNIQUE (username); - - --- --- Name: django_admin_log django_admin_log_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_admin_log - ADD CONSTRAINT django_admin_log_pkey PRIMARY KEY (id); - - --- --- Name: django_content_type django_content_type_app_label_model_76bd3d3b_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_content_type - ADD CONSTRAINT django_content_type_app_label_model_76bd3d3b_uniq UNIQUE (app_label, model); - - --- --- Name: django_content_type django_content_type_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_content_type - ADD CONSTRAINT django_content_type_pkey PRIMARY KEY (id); - - --- --- Name: django_migrations django_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_migrations - ADD CONSTRAINT django_migrations_pkey PRIMARY KEY (id); - - --- --- Name: django_session django_session_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_session - ADD CONSTRAINT django_session_pkey PRIMARY KEY (session_key); - - --- --- Name: django_site django_site_domain_a2e37b91_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_site - ADD CONSTRAINT django_site_domain_a2e37b91_uniq UNIQUE (domain); - - --- --- Name: django_site django_site_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_site - ADD CONSTRAINT django_site_pkey PRIMARY KEY (id); - - --- --- Name: graphite_collection graphite_collection_name_overview_a8093ed9_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_collection - ADD CONSTRAINT graphite_collection_name_overview_a8093ed9_uniq UNIQUE (name, overview); - - --- --- Name: graphite_collection graphite_collection_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_collection - ADD CONSTRAINT graphite_collection_pkey PRIMARY KEY (id); - - --- --- Name: graphite_numeric graphite_numeric_collection_id_attribute_id_602e9b10_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_numeric - ADD CONSTRAINT graphite_numeric_collection_id_attribute_id_602e9b10_uniq UNIQUE (collection_id, attribute_id); - - --- --- Name: graphite_numeric graphite_numeric_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_numeric - ADD CONSTRAINT graphite_numeric_pkey PRIMARY KEY (id); - - --- --- Name: graphite_relation graphite_relation_collection_id_attribute_id_cd8f6803_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_relation - ADD CONSTRAINT graphite_relation_collection_id_attribute_id_cd8f6803_uniq UNIQUE (collection_id, attribute_id); - - --- --- Name: graphite_relation graphite_relation_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_relation - ADD CONSTRAINT graphite_relation_pkey PRIMARY KEY (id); - - --- --- Name: graphite_template graphite_template_collection_id_name_d94c6b17_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_template - ADD CONSTRAINT graphite_template_collection_id_name_d94c6b17_uniq UNIQUE (collection_id, name); - - --- --- Name: graphite_template graphite_template_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_template - ADD CONSTRAINT graphite_template_pkey PRIMARY KEY (id); - - --- --- Name: graphite_variation graphite_variation_collection_id_name_9ba36e62_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_variation - ADD CONSTRAINT graphite_variation_collection_id_name_9ba36e62_uniq UNIQUE (collection_id, name); - - --- --- Name: graphite_variation graphite_variation_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_variation - ADD CONSTRAINT graphite_variation_pkey PRIMARY KEY (id); - - --- --- Name: server_boolean_attribute server_boolean_attribute_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_boolean_attribute - ADD CONSTRAINT server_boolean_attribute_pkey PRIMARY KEY (id); - - --- --- Name: server_boolean_attribute server_boolean_attribute_server_id_attribute_id_6bbd8242_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_boolean_attribute - ADD CONSTRAINT server_boolean_attribute_server_id_attribute_id_6bbd8242_uniq UNIQUE (server_id, attribute_id); - - --- --- Name: server_date_attribute server_date_attribute_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_date_attribute - ADD CONSTRAINT server_date_attribute_pkey PRIMARY KEY (id); - - --- --- Name: server_date_attribute server_date_attribute_server_id_attribute_id_v_6dbed874_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_date_attribute - ADD CONSTRAINT server_date_attribute_server_id_attribute_id_v_6dbed874_uniq UNIQUE (server_id, attribute_id, value); - - --- --- Name: server_datetime_attribute server_datetime_attribut_server_id_attribute_id_v_01f2547b_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_datetime_attribute - ADD CONSTRAINT server_datetime_attribut_server_id_attribute_id_v_01f2547b_uniq UNIQUE (server_id, attribute_id, value); - - --- --- Name: server_datetime_attribute server_datetime_attribute_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_datetime_attribute - ADD CONSTRAINT server_datetime_attribute_pkey PRIMARY KEY (id); - - --- --- Name: server server_hostname_key; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server - ADD CONSTRAINT server_hostname_key UNIQUE (hostname); - - --- --- Name: server_inet_attribute server_inet_attribute_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_inet_attribute - ADD CONSTRAINT server_inet_attribute_pkey PRIMARY KEY (id); - - --- --- Name: server_inet_attribute server_inet_attribute_server_id_attribute_id_v_99a96b34_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_inet_attribute - ADD CONSTRAINT server_inet_attribute_server_id_attribute_id_v_99a96b34_uniq UNIQUE (server_id, attribute_id, value); - - --- --- Name: server server_inter_ip_exclude; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server - ADD CONSTRAINT server_inter_ip_exclude EXCLUDE USING gist (intern_ip inet_ops WITH &&, servertype_id WITH =) WHERE (((servertype_id)::text <> 'loadbalancer'::text)); - - --- --- Name: server_macaddr_attribute server_macaddr_attribute_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_macaddr_attribute - ADD CONSTRAINT server_macaddr_attribute_pkey PRIMARY KEY (id); - - --- --- Name: server_macaddr_attribute server_macaddr_attribute_server_id_attribute_id_v_1f33a2ee_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_macaddr_attribute - ADD CONSTRAINT server_macaddr_attribute_server_id_attribute_id_v_1f33a2ee_uniq UNIQUE (server_id, attribute_id, value); - - --- --- Name: server_number_attribute server_number_attribute_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_number_attribute - ADD CONSTRAINT server_number_attribute_pkey PRIMARY KEY (id); - - --- --- Name: server_number_attribute server_number_attribute_server_id_attribute_id_v_ddd40781_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_number_attribute - ADD CONSTRAINT server_number_attribute_server_id_attribute_id_v_ddd40781_uniq UNIQUE (server_id, attribute_id, value); - - --- --- Name: server server_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server - ADD CONSTRAINT server_pkey PRIMARY KEY (server_id); - - --- --- Name: server_relation_attribute server_relation_attribut_server_id_attribute_id_v_ab4d9995_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_relation_attribute - ADD CONSTRAINT server_relation_attribut_server_id_attribute_id_v_ab4d9995_uniq UNIQUE (server_id, attribute_id, value); - - --- --- Name: server_relation_attribute server_relation_attribute_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_relation_attribute - ADD CONSTRAINT server_relation_attribute_pkey PRIMARY KEY (id); - - --- --- Name: server_string_attribute server_string_attribute_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_string_attribute - ADD CONSTRAINT server_string_attribute_pkey PRIMARY KEY (id); - - --- --- Name: server_string_attribute server_string_attribute_server_id_attribute_id_v_690ce414_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_string_attribute - ADD CONSTRAINT server_string_attribute_server_id_attribute_id_v_690ce414_uniq UNIQUE (server_id, attribute_id, value); - - --- --- Name: serverdb_change serverdb_change_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_change - ADD CONSTRAINT serverdb_change_pkey PRIMARY KEY (id); - - --- --- Name: serverdb_changeadd serverdb_changeadd_commit_id_server_id_faff3d42_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changeadd - ADD CONSTRAINT serverdb_changeadd_commit_id_server_id_faff3d42_uniq UNIQUE (commit_id, server_id); - - --- --- Name: serverdb_changeadd serverdb_changeadd_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changeadd - ADD CONSTRAINT serverdb_changeadd_pkey PRIMARY KEY (id); - - --- --- Name: serverdb_changecommit serverdb_changecommit_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changecommit - ADD CONSTRAINT serverdb_changecommit_pkey PRIMARY KEY (id); - - --- --- Name: serverdb_changedelete serverdb_changedelete_commit_id_server_id_1c635883_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changedelete - ADD CONSTRAINT serverdb_changedelete_commit_id_server_id_1c635883_uniq UNIQUE (commit_id, server_id); - - --- --- Name: serverdb_changedelete serverdb_changedelete_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changedelete - ADD CONSTRAINT serverdb_changedelete_pkey PRIMARY KEY (id); - - --- --- Name: serverdb_changeupdate serverdb_changeupdate_commit_id_server_id_28f207ac_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changeupdate - ADD CONSTRAINT serverdb_changeupdate_commit_id_server_id_28f207ac_uniq UNIQUE (commit_id, server_id); - - --- --- Name: serverdb_changeupdate serverdb_changeupdate_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changeupdate - ADD CONSTRAINT serverdb_changeupdate_pkey PRIMARY KEY (id); - - --- --- Name: servertype_attribute servertype_attribute_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.servertype_attribute - ADD CONSTRAINT servertype_attribute_pkey PRIMARY KEY (id); - - --- --- Name: servertype_attribute servertype_attribute_servertype_id_attribute_id_eb89174e_uniq; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.servertype_attribute - ADD CONSTRAINT servertype_attribute_servertype_id_attribute_id_eb89174e_uniq UNIQUE (servertype_id, attribute_id); - - --- --- Name: servertype servertype_pkey; Type: CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.servertype - ADD CONSTRAINT servertype_pkey PRIMARY KEY (servertype_id); - - --- --- Name: access_control_group_appli_accesscontrolgroup_id_fc0d0a71; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX access_control_group_appli_accesscontrolgroup_id_fc0d0a71 ON public.access_control_group_applications USING btree (accesscontrolgroup_id); - - --- --- Name: access_control_group_applications_application_id_c9303431; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX access_control_group_applications_application_id_c9303431 ON public.access_control_group_applications USING btree (application_id); - - --- --- Name: access_control_group_attributes_accesscontrolgroup_id_5ee69ddd; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX access_control_group_attributes_accesscontrolgroup_id_5ee69ddd ON public.access_control_group_attributes USING btree (accesscontrolgroup_id); - - --- --- Name: access_control_group_attributes_attribute_id_90fae58c; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX access_control_group_attributes_attribute_id_90fae58c ON public.access_control_group_attributes USING btree (attribute_id); - - --- --- Name: access_control_group_attributes_attribute_id_90fae58c_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX access_control_group_attributes_attribute_id_90fae58c_like ON public.access_control_group_attributes USING btree (attribute_id varchar_pattern_ops); - - --- --- Name: access_control_group_members_accesscontrolgroup_id_c540d0de; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX access_control_group_members_accesscontrolgroup_id_c540d0de ON public.access_control_group_members USING btree (accesscontrolgroup_id); - - --- --- Name: access_control_group_members_user_id_121f20f4; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX access_control_group_members_user_id_121f20f4 ON public.access_control_group_members USING btree (user_id); - - --- --- Name: access_control_group_name_d458b0e4_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX access_control_group_name_d458b0e4_like ON public.access_control_group USING btree (name varchar_pattern_ops); - - --- --- Name: api_lock_hash_sum_bff8800e_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX api_lock_hash_sum_bff8800e_like ON public.api_lock USING btree (hash_sum varchar_pattern_ops); - - --- --- Name: apps_application_app_id_b598654e_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX apps_application_app_id_b598654e_like ON public.apps_application USING btree (app_id varchar_pattern_ops); - - --- --- Name: apps_application_auth_token_89f63725_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX apps_application_auth_token_89f63725_like ON public.apps_application USING btree (auth_token varchar_pattern_ops); - - --- --- Name: apps_application_name_d7571844_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX apps_application_name_d7571844_like ON public.apps_application USING btree (name varchar_pattern_ops); - - --- --- Name: apps_application_owner_id_0baec2b3; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX apps_application_owner_id_0baec2b3 ON public.apps_application USING btree (owner_id); - - --- --- Name: apps_publickey_application_id_52eb9110; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX apps_publickey_application_id_52eb9110 ON public.apps_publickey USING btree (application_id); - - --- --- Name: apps_publickey_key_base64_35f0def6_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX apps_publickey_key_base64_35f0def6_like ON public.apps_publickey USING btree (key_base64 varchar_pattern_ops); - - --- --- Name: attribute_attribute_id_7d9244d0_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX attribute_attribute_id_7d9244d0_like ON public.attribute USING btree (attribute_id varchar_pattern_ops); - - --- --- Name: auth_group_name_a6ea08ec_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX auth_group_name_a6ea08ec_like ON public.auth_group USING btree (name varchar_pattern_ops); - - --- --- Name: auth_group_permissions_group_id_b120cbf9; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX auth_group_permissions_group_id_b120cbf9 ON public.auth_group_permissions USING btree (group_id); - - --- --- Name: auth_group_permissions_permission_id_84c5c92e; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX auth_group_permissions_permission_id_84c5c92e ON public.auth_group_permissions USING btree (permission_id); - - --- --- Name: auth_permission_content_type_id_2f476e4b; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX auth_permission_content_type_id_2f476e4b ON public.auth_permission USING btree (content_type_id); - - --- --- Name: auth_user_groups_group_id_97559544; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX auth_user_groups_group_id_97559544 ON public.auth_user_groups USING btree (group_id); - - --- --- Name: auth_user_groups_user_id_6a12ed8b; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX auth_user_groups_user_id_6a12ed8b ON public.auth_user_groups USING btree (user_id); - - --- --- Name: auth_user_user_permissions_permission_id_1fbb5f2c; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX auth_user_user_permissions_permission_id_1fbb5f2c ON public.auth_user_user_permissions USING btree (permission_id); - - --- --- Name: auth_user_user_permissions_user_id_a95ead1b; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX auth_user_user_permissions_user_id_a95ead1b ON public.auth_user_user_permissions USING btree (user_id); - - --- --- Name: auth_user_username_6821ab7c_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX auth_user_username_6821ab7c_like ON public.auth_user USING btree (username varchar_pattern_ops); - - --- --- Name: django_admin_log_content_type_id_c4bce8eb; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX django_admin_log_content_type_id_c4bce8eb ON public.django_admin_log USING btree (content_type_id); - - --- --- Name: django_admin_log_user_id_c564eba6; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX django_admin_log_user_id_c564eba6 ON public.django_admin_log USING btree (user_id); - - --- --- Name: django_session_expire_date_a5c62663; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX django_session_expire_date_a5c62663 ON public.django_session USING btree (expire_date); - - --- --- Name: django_session_session_key_c0390e0f_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX django_session_session_key_c0390e0f_like ON public.django_session USING btree (session_key varchar_pattern_ops); - - --- --- Name: django_site_domain_a2e37b91_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX django_site_domain_a2e37b91_like ON public.django_site USING btree (domain varchar_pattern_ops); - - --- --- Name: graphite_numeric_attribute_id_88244c59; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX graphite_numeric_attribute_id_88244c59 ON public.graphite_numeric USING btree (attribute_id); - - --- --- Name: graphite_numeric_attribute_id_88244c59_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX graphite_numeric_attribute_id_88244c59_like ON public.graphite_numeric USING btree (attribute_id varchar_pattern_ops); - - --- --- Name: graphite_numeric_collection_id_df34a1f3; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX graphite_numeric_collection_id_df34a1f3 ON public.graphite_numeric USING btree (collection_id); - - --- --- Name: graphite_relation_attribute_id_2f352462; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX graphite_relation_attribute_id_2f352462 ON public.graphite_relation USING btree (attribute_id); - - --- --- Name: graphite_relation_attribute_id_2f352462_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX graphite_relation_attribute_id_2f352462_like ON public.graphite_relation USING btree (attribute_id varchar_pattern_ops); - - --- --- Name: graphite_relation_collection_id_7d3b0dcb; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX graphite_relation_collection_id_7d3b0dcb ON public.graphite_relation USING btree (collection_id); - - --- --- Name: graphite_template_collection_id_96835e82; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX graphite_template_collection_id_96835e82 ON public.graphite_template USING btree (collection_id); - - --- --- Name: graphite_variation_collection_id_bb3f8a11; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX graphite_variation_collection_id_bb3f8a11 ON public.graphite_variation USING btree (collection_id); - - --- --- Name: server_boolean_attribute_attribute_id_b1ad575f; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_boolean_attribute_attribute_id_b1ad575f ON public.server_boolean_attribute USING btree (attribute_id); - - --- --- Name: server_boolean_attribute_attribute_id_b1ad575f_idx; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_boolean_attribute_attribute_id_b1ad575f_idx ON public.server_boolean_attribute USING btree (attribute_id); - - --- --- Name: server_boolean_attribute_attribute_id_b1ad575f_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_boolean_attribute_attribute_id_b1ad575f_like ON public.server_boolean_attribute USING btree (attribute_id varchar_pattern_ops); - - --- --- Name: server_date_attribute_attribute_id_value_92c2e130_idx; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_date_attribute_attribute_id_value_92c2e130_idx ON public.server_date_attribute USING btree (attribute_id, value); - - --- --- Name: server_datetime_attribute_attribute_id_value_0dde96d5_idx; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_datetime_attribute_attribute_id_value_0dde96d5_idx ON public.server_datetime_attribute USING btree (attribute_id, value); - - --- --- Name: server_hostname_b385a781_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_hostname_b385a781_like ON public.server USING btree (hostname varchar_pattern_ops); - - --- --- Name: server_hostname_trgm; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_hostname_trgm ON public.server USING gin (hostname public.gin_trgm_ops); - - --- --- Name: server_inet_attribute_attribute_id_value_5fb6797b_idx; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_inet_attribute_attribute_id_value_5fb6797b_idx ON public.server_inet_attribute USING btree (attribute_id, value); - - --- --- Name: server_macaddr_attribute_attribute_id_value_49d23836_idx; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_macaddr_attribute_attribute_id_value_49d23836_idx ON public.server_macaddr_attribute USING btree (attribute_id, value); - - --- --- Name: server_number_attribute_attribute_id_value_0b02c803_idx; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_number_attribute_attribute_id_value_0b02c803_idx ON public.server_number_attribute USING btree (attribute_id, value); - - --- --- Name: server_relation_attribute_attribute_id_value_5c4dfd1c_idx; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_relation_attribute_attribute_id_value_5c4dfd1c_idx ON public.server_relation_attribute USING btree (attribute_id, value); - - --- --- Name: server_servertype_id_7a1f440f; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_servertype_id_7a1f440f ON public.server USING btree (servertype_id); - - --- --- Name: server_servertype_id_7a1f440f_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_servertype_id_7a1f440f_like ON public.server USING btree (servertype_id varchar_pattern_ops); - - --- --- Name: server_string_attribute_attribute_id_value_d6e99d79_idx; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX server_string_attribute_attribute_id_value_d6e99d79_idx ON public.server_string_attribute USING btree (attribute_id, value); - - --- --- Name: serverdb_change_app_id_1b798c85; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX serverdb_change_app_id_1b798c85 ON public.serverdb_change USING btree (app_id); - - --- --- Name: serverdb_change_change_on_7ad85427; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX serverdb_change_change_on_7ad85427 ON public.serverdb_change USING btree (change_on); - - --- --- Name: serverdb_change_user_id_0e8cce5b; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX serverdb_change_user_id_0e8cce5b ON public.serverdb_change USING btree (user_id); - - --- --- Name: serverdb_changeadd_commit_id_b6661243; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX serverdb_changeadd_commit_id_b6661243 ON public.serverdb_changeadd USING btree (commit_id); - - --- --- Name: serverdb_changeadd_server_id_6b6c8c19; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX serverdb_changeadd_server_id_6b6c8c19 ON public.serverdb_changeadd USING btree (server_id); - - --- --- Name: serverdb_changecommit_app_id_73cb4baf; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX serverdb_changecommit_app_id_73cb4baf ON public.serverdb_changecommit USING btree (app_id); - - --- --- Name: serverdb_changecommit_change_on_4ea3b2a0; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX serverdb_changecommit_change_on_4ea3b2a0 ON public.serverdb_changecommit USING btree (change_on); - - --- --- Name: serverdb_changecommit_user_id_4822c638; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX serverdb_changecommit_user_id_4822c638 ON public.serverdb_changecommit USING btree (user_id); - - --- --- Name: serverdb_changedelete_commit_id_ed67b6f2; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX serverdb_changedelete_commit_id_ed67b6f2 ON public.serverdb_changedelete USING btree (commit_id); - - --- --- Name: serverdb_changedelete_server_id_1ab30147; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX serverdb_changedelete_server_id_1ab30147 ON public.serverdb_changedelete USING btree (server_id); - - --- --- Name: serverdb_changeupdate_commit_id_691c30ca; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX serverdb_changeupdate_commit_id_691c30ca ON public.serverdb_changeupdate USING btree (commit_id); - - --- --- Name: serverdb_changeupdate_server_id_31332993; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX serverdb_changeupdate_server_id_31332993 ON public.serverdb_changeupdate USING btree (server_id); - - --- --- Name: servertype_servertype_id_95831609_like; Type: INDEX; Schema: public; Owner: serveradmin --- - -CREATE INDEX servertype_servertype_id_95831609_like ON public.servertype USING btree (servertype_id varchar_pattern_ops); - - --- --- Name: access_control_group_attributes access_control_group_accesscontrolgroup_i_5ee69ddd_fk_access_co; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_attributes - ADD CONSTRAINT access_control_group_accesscontrolgroup_i_5ee69ddd_fk_access_co FOREIGN KEY (accesscontrolgroup_id) REFERENCES public.access_control_group(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: access_control_group_members access_control_group_accesscontrolgroup_i_c540d0de_fk_access_co; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_members - ADD CONSTRAINT access_control_group_accesscontrolgroup_i_c540d0de_fk_access_co FOREIGN KEY (accesscontrolgroup_id) REFERENCES public.access_control_group(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: access_control_group_applications access_control_group_accesscontrolgroup_i_fc0d0a71_fk_access_co; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_applications - ADD CONSTRAINT access_control_group_accesscontrolgroup_i_fc0d0a71_fk_access_co FOREIGN KEY (accesscontrolgroup_id) REFERENCES public.access_control_group(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: access_control_group_applications access_control_group_application_id_c9303431_fk_apps_appl; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_applications - ADD CONSTRAINT access_control_group_application_id_c9303431_fk_apps_appl FOREIGN KEY (application_id) REFERENCES public.apps_application(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: access_control_group_attributes access_control_group_attribute_id_90fae58c_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_attributes - ADD CONSTRAINT access_control_group_attribute_id_90fae58c_fk_attribute FOREIGN KEY (attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: access_control_group_members access_control_group_members_user_id_121f20f4_fk_auth_user_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.access_control_group_members - ADD CONSTRAINT access_control_group_members_user_id_121f20f4_fk_auth_user_id FOREIGN KEY (user_id) REFERENCES public.auth_user(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: apps_application apps_application_owner_id_0baec2b3_fk_auth_user_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.apps_application - ADD CONSTRAINT apps_application_owner_id_0baec2b3_fk_auth_user_id FOREIGN KEY (owner_id) REFERENCES public.auth_user(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: apps_publickey apps_publickey_application_id_52eb9110_fk_apps_application_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.apps_publickey - ADD CONSTRAINT apps_publickey_application_id_52eb9110_fk_apps_application_id FOREIGN KEY (application_id) REFERENCES public.apps_application(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: attribute attribute_reversed_attribute_i_0dfb83ac_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.attribute - ADD CONSTRAINT attribute_reversed_attribute_i_0dfb83ac_fk_attribute FOREIGN KEY (reversed_attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: attribute attribute_target_servertype_id_0eab2dcc_fk_servertyp; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.attribute - ADD CONSTRAINT attribute_target_servertype_id_0eab2dcc_fk_servertyp FOREIGN KEY (target_servertype_id) REFERENCES public.servertype(servertype_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: auth_group_permissions auth_group_permissio_permission_id_84c5c92e_fk_auth_perm; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_group_permissions - ADD CONSTRAINT auth_group_permissio_permission_id_84c5c92e_fk_auth_perm FOREIGN KEY (permission_id) REFERENCES public.auth_permission(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: auth_group_permissions auth_group_permissions_group_id_b120cbf9_fk_auth_group_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_group_permissions - ADD CONSTRAINT auth_group_permissions_group_id_b120cbf9_fk_auth_group_id FOREIGN KEY (group_id) REFERENCES public.auth_group(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: auth_permission auth_permission_content_type_id_2f476e4b_fk_django_co; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_permission - ADD CONSTRAINT auth_permission_content_type_id_2f476e4b_fk_django_co FOREIGN KEY (content_type_id) REFERENCES public.django_content_type(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: auth_user_groups auth_user_groups_group_id_97559544_fk_auth_group_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user_groups - ADD CONSTRAINT auth_user_groups_group_id_97559544_fk_auth_group_id FOREIGN KEY (group_id) REFERENCES public.auth_group(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: auth_user_groups auth_user_groups_user_id_6a12ed8b_fk_auth_user_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user_groups - ADD CONSTRAINT auth_user_groups_user_id_6a12ed8b_fk_auth_user_id FOREIGN KEY (user_id) REFERENCES public.auth_user(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: auth_user_user_permissions auth_user_user_permi_permission_id_1fbb5f2c_fk_auth_perm; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user_user_permissions - ADD CONSTRAINT auth_user_user_permi_permission_id_1fbb5f2c_fk_auth_perm FOREIGN KEY (permission_id) REFERENCES public.auth_permission(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: auth_user_user_permissions auth_user_user_permissions_user_id_a95ead1b_fk_auth_user_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.auth_user_user_permissions - ADD CONSTRAINT auth_user_user_permissions_user_id_a95ead1b_fk_auth_user_id FOREIGN KEY (user_id) REFERENCES public.auth_user(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: django_admin_log django_admin_log_content_type_id_c4bce8eb_fk_django_co; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_admin_log - ADD CONSTRAINT django_admin_log_content_type_id_c4bce8eb_fk_django_co FOREIGN KEY (content_type_id) REFERENCES public.django_content_type(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: django_admin_log django_admin_log_user_id_c564eba6_fk_auth_user_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.django_admin_log - ADD CONSTRAINT django_admin_log_user_id_c564eba6_fk_auth_user_id FOREIGN KEY (user_id) REFERENCES public.auth_user(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: graphite_numeric graphite_numeric_attribute_id_88244c59_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_numeric - ADD CONSTRAINT graphite_numeric_attribute_id_88244c59_fk_attribute FOREIGN KEY (attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: graphite_numeric graphite_numeric_collection_id_df34a1f3_fk_graphite_; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_numeric - ADD CONSTRAINT graphite_numeric_collection_id_df34a1f3_fk_graphite_ FOREIGN KEY (collection_id) REFERENCES public.graphite_collection(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: graphite_relation graphite_relation_attribute_id_2f352462_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_relation - ADD CONSTRAINT graphite_relation_attribute_id_2f352462_fk_attribute FOREIGN KEY (attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: graphite_relation graphite_relation_collection_id_7d3b0dcb_fk_graphite_; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_relation - ADD CONSTRAINT graphite_relation_collection_id_7d3b0dcb_fk_graphite_ FOREIGN KEY (collection_id) REFERENCES public.graphite_collection(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: graphite_template graphite_template_collection_id_96835e82_fk_graphite_; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_template - ADD CONSTRAINT graphite_template_collection_id_96835e82_fk_graphite_ FOREIGN KEY (collection_id) REFERENCES public.graphite_collection(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: graphite_variation graphite_variation_collection_id_bb3f8a11_fk_graphite_; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.graphite_variation - ADD CONSTRAINT graphite_variation_collection_id_bb3f8a11_fk_graphite_ FOREIGN KEY (collection_id) REFERENCES public.graphite_collection(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_boolean_attribute server_boolean_attri_attribute_id_b1ad575f_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_boolean_attribute - ADD CONSTRAINT server_boolean_attri_attribute_id_b1ad575f_fk_attribute FOREIGN KEY (attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_boolean_attribute server_boolean_attribute_server_id_f298dd92_fk_server_server_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_boolean_attribute - ADD CONSTRAINT server_boolean_attribute_server_id_f298dd92_fk_server_server_id FOREIGN KEY (server_id) REFERENCES public.server(server_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_date_attribute server_date_attribut_attribute_id_da524b5f_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_date_attribute - ADD CONSTRAINT server_date_attribut_attribute_id_da524b5f_fk_attribute FOREIGN KEY (attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_date_attribute server_date_attribute_server_id_6b0a5f23_fk_server_server_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_date_attribute - ADD CONSTRAINT server_date_attribute_server_id_6b0a5f23_fk_server_server_id FOREIGN KEY (server_id) REFERENCES public.server(server_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_datetime_attribute server_datetime_attr_attribute_id_267c546f_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_datetime_attribute - ADD CONSTRAINT server_datetime_attr_attribute_id_267c546f_fk_attribute FOREIGN KEY (attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_datetime_attribute server_datetime_attr_server_id_7e99ffa9_fk_server_se; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_datetime_attribute - ADD CONSTRAINT server_datetime_attr_server_id_7e99ffa9_fk_server_se FOREIGN KEY (server_id) REFERENCES public.server(server_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_inet_attribute server_inet_attribut_attribute_id_d3ffd83b_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_inet_attribute - ADD CONSTRAINT server_inet_attribut_attribute_id_d3ffd83b_fk_attribute FOREIGN KEY (attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_inet_attribute server_inet_attribute_server_id_971d8988_fk_server_server_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_inet_attribute - ADD CONSTRAINT server_inet_attribute_server_id_971d8988_fk_server_server_id FOREIGN KEY (server_id) REFERENCES public.server(server_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_macaddr_attribute server_macaddr_attri_attribute_id_3592cef5_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_macaddr_attribute - ADD CONSTRAINT server_macaddr_attri_attribute_id_3592cef5_fk_attribute FOREIGN KEY (attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_macaddr_attribute server_macaddr_attribute_server_id_e76c6ad1_fk_server_server_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_macaddr_attribute - ADD CONSTRAINT server_macaddr_attribute_server_id_e76c6ad1_fk_server_server_id FOREIGN KEY (server_id) REFERENCES public.server(server_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_number_attribute server_number_attrib_attribute_id_a7c8738c_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_number_attribute - ADD CONSTRAINT server_number_attrib_attribute_id_a7c8738c_fk_attribute FOREIGN KEY (attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_number_attribute server_number_attribute_server_id_0131ae8e_fk_server_server_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_number_attribute - ADD CONSTRAINT server_number_attribute_server_id_0131ae8e_fk_server_server_id FOREIGN KEY (server_id) REFERENCES public.server(server_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_relation_attribute server_relation_attr_attribute_id_f971ac6d_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_relation_attribute - ADD CONSTRAINT server_relation_attr_attribute_id_f971ac6d_fk_attribute FOREIGN KEY (attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_relation_attribute server_relation_attr_server_id_7367ee06_fk_server_se; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_relation_attribute - ADD CONSTRAINT server_relation_attr_server_id_7367ee06_fk_server_se FOREIGN KEY (server_id) REFERENCES public.server(server_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_relation_attribute server_relation_attribute_value_563c1ba4_fk_server_server_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_relation_attribute - ADD CONSTRAINT server_relation_attribute_value_563c1ba4_fk_server_server_id FOREIGN KEY (value) REFERENCES public.server(server_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server server_servertype_id_7a1f440f_fk_servertype_servertype_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server - ADD CONSTRAINT server_servertype_id_7a1f440f_fk_servertype_servertype_id FOREIGN KEY (servertype_id) REFERENCES public.servertype(servertype_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_string_attribute server_string_attrib_attribute_id_8116442b_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_string_attribute - ADD CONSTRAINT server_string_attrib_attribute_id_8116442b_fk_attribute FOREIGN KEY (attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: server_string_attribute server_string_attribute_server_id_a126825b_fk_server_server_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.server_string_attribute - ADD CONSTRAINT server_string_attribute_server_id_a126825b_fk_server_server_id FOREIGN KEY (server_id) REFERENCES public.server(server_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: serverdb_change serverdb_change_app_id_1b798c85_fk_apps_application_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_change - ADD CONSTRAINT serverdb_change_app_id_1b798c85_fk_apps_application_id FOREIGN KEY (app_id) REFERENCES public.apps_application(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: serverdb_change serverdb_change_user_id_0e8cce5b_fk_auth_user_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_change - ADD CONSTRAINT serverdb_change_user_id_0e8cce5b_fk_auth_user_id FOREIGN KEY (user_id) REFERENCES public.auth_user(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: serverdb_changeadd serverdb_changeadd_commit_id_b6661243_fk_serverdb_; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changeadd - ADD CONSTRAINT serverdb_changeadd_commit_id_b6661243_fk_serverdb_ FOREIGN KEY (commit_id) REFERENCES public.serverdb_changecommit(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: serverdb_changecommit serverdb_changecommit_app_id_73cb4baf_fk_apps_application_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changecommit - ADD CONSTRAINT serverdb_changecommit_app_id_73cb4baf_fk_apps_application_id FOREIGN KEY (app_id) REFERENCES public.apps_application(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: serverdb_changecommit serverdb_changecommit_user_id_4822c638_fk_auth_user_id; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changecommit - ADD CONSTRAINT serverdb_changecommit_user_id_4822c638_fk_auth_user_id FOREIGN KEY (user_id) REFERENCES public.auth_user(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: serverdb_changedelete serverdb_changedelet_commit_id_ed67b6f2_fk_serverdb_; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changedelete - ADD CONSTRAINT serverdb_changedelet_commit_id_ed67b6f2_fk_serverdb_ FOREIGN KEY (commit_id) REFERENCES public.serverdb_changecommit(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: serverdb_changeupdate serverdb_changeupdat_commit_id_691c30ca_fk_serverdb_; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.serverdb_changeupdate - ADD CONSTRAINT serverdb_changeupdat_commit_id_691c30ca_fk_serverdb_ FOREIGN KEY (commit_id) REFERENCES public.serverdb_changecommit(id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: servertype_attribute servertype_attribute_attribute_id_7178d5a3_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.servertype_attribute - ADD CONSTRAINT servertype_attribute_attribute_id_7178d5a3_fk_attribute FOREIGN KEY (attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: servertype_attribute servertype_attribute_consistent_via_attri_7de73045_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.servertype_attribute - ADD CONSTRAINT servertype_attribute_consistent_via_attri_7de73045_fk_attribute FOREIGN KEY (consistent_via_attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: servertype_attribute servertype_attribute_related_via_attribut_09fcc314_fk_attribute; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.servertype_attribute - ADD CONSTRAINT servertype_attribute_related_via_attribut_09fcc314_fk_attribute FOREIGN KEY (related_via_attribute_id) REFERENCES public.attribute(attribute_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- Name: servertype_attribute servertype_attribute_servertype_id_861fa7c8_fk_servertyp; Type: FK CONSTRAINT; Schema: public; Owner: serveradmin --- - -ALTER TABLE ONLY public.servertype_attribute - ADD CONSTRAINT servertype_attribute_servertype_id_861fa7c8_fk_servertyp FOREIGN KEY (servertype_id) REFERENCES public.servertype(servertype_id) DEFERRABLE INITIALLY DEFERRED; - - --- --- PostgreSQL database dump complete --- - From e80b2d6a57ca28b4315e93abc936a0d6d3404a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kr=C3=B6ger?= Date: Wed, 19 Mar 2025 13:19:38 +0100 Subject: [PATCH 09/11] Fix linting issues --- adminapi/dataset.py | 6 +++--- adminapi/datatype.py | 6 +++--- adminapi/filters.py | 13 +++++-------- adminapi/request.py | 22 ++++++++++------------ serveradmin/serverdb/models.py | 8 ++++---- serveradmin/serverdb/query_committer.py | 8 ++++---- serveradmin/serverdb/sql_generator.py | 4 ++-- serveradmin/serverdb/tests/test_acls.py | 2 +- serveradmin/serverdb/views.py | 6 +++--- serveradmin/servershell/views.py | 19 ++++++++++--------- 10 files changed, 45 insertions(+), 49 deletions(-) diff --git a/adminapi/dataset.py b/adminapi/dataset.py index 7385d097..269b03a6 100644 --- a/adminapi/dataset.py +++ b/adminapi/dataset.py @@ -8,10 +8,10 @@ from types import GeneratorType from adminapi import api -from adminapi.datatype import validate_value, json_to_datatype +from adminapi.datatype import json_to_datatype, validate_value +from adminapi.exceptions import AdminapiException, DatasetError from adminapi.filters import Any, BaseFilter, ContainedOnlyBy -from adminapi.request import send_request, json_encode_extra -from adminapi.exceptions import DatasetError, AdminapiException +from adminapi.request import json_encode_extra, send_request NEW_OBJECT_ENDPOINT = '/dataset/new_object' COMMIT_ENDPOINT = '/dataset/commit' diff --git a/adminapi/datatype.py b/adminapi/datatype.py index a23aba4d..dd004507 100644 --- a/adminapi/datatype.py +++ b/adminapi/datatype.py @@ -89,8 +89,8 @@ def validate_value(value, datatype=None): if isinstance(value, special_datatypes): raise DatatypeError('Value cannot be from {}'.format(type(value))) - assert datatype != object - if type(value) == object: + assert datatype is not object + if type(value) is object: raise DatatypeError('Value cannot be a generic object') newtype = type(value) @@ -98,7 +98,7 @@ def validate_value(value, datatype=None): return newtype for supertype in datatype.mro(): - if issubclass(newtype, supertype) and supertype != object: + if issubclass(newtype, supertype) and supertype is not object: return supertype raise DatatypeError('Value from {} is not compatible with existing value from {}'.format(type(value), datatype)) diff --git a/adminapi/filters.py b/adminapi/filters.py index e85bc231..db725851 100644 --- a/adminapi/filters.py +++ b/adminapi/filters.py @@ -12,11 +12,8 @@ class BaseFilter(object): def __init__(self, value): - if type(self) == BaseFilter and isinstance(value, bool): - pass - elif isinstance(value, (int, float)): - pass - elif isinstance(value, tuple(s[0] for s in STR_BASED_DATATYPES)): + ok_datatypes = tuple([bool, int, float] + [s[0] for s in STR_BASED_DATATYPES]) + if type(self) is BaseFilter and isinstance(value, ok_datatypes): pass elif isinstance(value, str): for char in '\'"': @@ -34,12 +31,12 @@ def __or__(self, other): return Any(self, other) def __repr__(self): - if type(self) == BaseFilter: + if type(self) is BaseFilter: return repr(self.value) return '{}({!r})'.format(type(self).__name__, self.value) def serialize(self): - if type(self) == BaseFilter: + if type(self) is BaseFilter: return self.value return {type(self).__name__: self.value} @@ -243,4 +240,4 @@ def matches(self, value): # Collect all classes that are subclass of BaseFilter (exclusive) -filter_classes = [v for v in globals().values() if type(v) == type and BaseFilter in v.mro()[1:]] +filter_classes = [v for v in globals().values() if type(v) is type and BaseFilter in v.mro()[1:]] \ No newline at end of file diff --git a/adminapi/request.py b/adminapi/request.py index 4e90ed81..73cb901c 100644 --- a/adminapi/request.py +++ b/adminapi/request.py @@ -4,46 +4,44 @@ """ import gzip +import hmac +import json import logging import os +import time +from base64 import b64encode +from datetime import datetime, timezone from hashlib import sha1 -import hmac from http.client import IncompleteRead from socket import timeout from ssl import SSLError -import time -import json -from base64 import b64encode -from datetime import datetime, timezone - from urllib.error import HTTPError, URLError from urllib.parse import urlencode -from urllib.request import urlopen, Request +from urllib.request import Request, urlopen from paramiko.agent import Agent from paramiko.message import Message -from paramiko.ssh_exception import SSHException, PasswordRequiredException +from paramiko.ssh_exception import PasswordRequiredException, SSHException from adminapi import VERSION try: - from paramiko import RSAKey, ECDSAKey, Ed25519Key + from paramiko import ECDSAKey, Ed25519Key, RSAKey key_classes = (RSAKey, ECDSAKey, Ed25519Key) except ImportError: # Ed25519Key requires paramiko >= 2.2 - from paramiko import RSAKey, ECDSAKey + from paramiko import ECDSAKey, RSAKey key_classes = (RSAKey, ECDSAKey) from adminapi.cmduser import get_auth_token -from adminapi.filters import BaseFilter from adminapi.exceptions import ( ApiError, AuthenticationError, ConfigurationError, ) - +from adminapi.filters import BaseFilter logger = logging.getLogger(__name__) diff --git a/serveradmin/serverdb/models.py b/serveradmin/serverdb/models.py index 33fcb72b..013f0efc 100644 --- a/serveradmin/serverdb/models.py +++ b/serveradmin/serverdb/models.py @@ -7,13 +7,13 @@ from distutils.util import strtobool from ipaddress import ( IPv4Address, - IPv6Address, - ip_interface, IPv4Interface, - IPv6Interface, - ip_network, IPv4Network, + IPv6Address, + IPv6Interface, IPv6Network, + ip_interface, + ip_network, ) from typing import Optional, Union diff --git a/serveradmin/serverdb/query_committer.py b/serveradmin/serverdb/query_committer.py index a3e33f94..d32f1475 100644 --- a/serveradmin/serverdb/query_committer.py +++ b/serveradmin/serverdb/query_committer.py @@ -15,20 +15,20 @@ from adminapi.request import json_encode_extra from serveradmin.apps.models import Application from serveradmin.serverdb.models import ( - Servertype, Attribute, + Change, + ChangeCommit, Server, ServerAttribute, ServerRelationAttribute, - ChangeCommit, - Change, + Servertype, ServertypeAttribute, ) from serveradmin.serverdb.query_materializer import ( QueryMaterializer, get_default_attribute_values, ) -from serveradmin.serverdb.signals import pre_commit, post_commit +from serveradmin.serverdb.signals import post_commit, pre_commit logger = logging.getLogger(__name__) diff --git a/serveradmin/serverdb/sql_generator.py b/serveradmin/serverdb/sql_generator.py index f440b42e..1e72edfe 100644 --- a/serveradmin/serverdb/sql_generator.py +++ b/serveradmin/serverdb/sql_generator.py @@ -66,7 +66,7 @@ def _get_sql_condition(attribute, filt, related_vias): if attribute.type == 'boolean': # We have already dealt with the logical filters. Other # complicated filters don't make any sense on booleans. - if type(filt) != BaseFilter: + if type(filt) is not BaseFilter: raise FilterValueError( 'Boolean attribute "{}" cannot be used with {}() filter' .format(attribute, type(filt).__name__) @@ -128,7 +128,7 @@ def _logical_filter_sql_condition(attribute, filt, related_vias): simple_values = [] templates = [] for value in filt.values: - if type(filt) == Any and type(value) == BaseFilter: + if type(filt) is Any and type(value) is BaseFilter: simple_values.append(value) else: templates.append( diff --git a/serveradmin/serverdb/tests/test_acls.py b/serveradmin/serverdb/tests/test_acls.py index f8aea065..9d052ac3 100644 --- a/serveradmin/serverdb/tests/test_acls.py +++ b/serveradmin/serverdb/tests/test_acls.py @@ -416,5 +416,5 @@ def test_hijack_objects_not_possible(self): changed_object['servertype'] = 'test0' # Attacker attempts to hijack object changed_objects = {changed_object['object_id']: changed_object} - with self.assertRaises(PermissionDenied) as error: + with self.assertRaises(PermissionDenied): query_committer._access_control(user, None, unchanged_objects, {}, changed_objects, {}) diff --git a/serveradmin/serverdb/views.py b/serveradmin/serverdb/views.py index 2d6c480f..59a64d2c 100644 --- a/serveradmin/serverdb/views.py +++ b/serveradmin/serverdb/views.py @@ -8,9 +8,9 @@ from django.contrib.auth.decorators import login_required from django.core.exceptions import ValidationError from django.core.paginator import Paginator -from django.db.models import Q, Subquery, OuterRef, Prefetch, CharField +from django.db.models import CharField, OuterRef, Prefetch, Q, Subquery from django.db.models.fields.json import KeyTextTransform -from django.db.models.functions import Coalesce, Cast +from django.db.models.functions import Cast, Coalesce from django.http import HttpResponseBadRequest from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse @@ -19,10 +19,10 @@ from serveradmin import settings from serveradmin.serverdb.models import ( + Change, ChangeCommit, Server, ServertypeAttribute, - Change, ) from serveradmin.serverdb.query_committer import CommitError, commit_query diff --git a/serveradmin/servershell/views.py b/serveradmin/servershell/views.py index 33a2dbc7..6e6a642a 100644 --- a/serveradmin/servershell/views.py +++ b/serveradmin/servershell/views.py @@ -5,34 +5,35 @@ import json from distutils.util import strtobool -from ipaddress import IPv6Address, IPv4Address, ip_interface -from itertools import islice, chain +from ipaddress import IPv4Address, IPv6Address, ip_interface +from itertools import chain, islice from django.contrib import messages from django.contrib.auth.decorators import login_required from django.core.exceptions import ObjectDoesNotExist, PermissionDenied, ValidationError from django.http import ( - HttpResponse, - HttpResponseRedirect, Http404, - JsonResponse, + HttpRequest, + HttpResponse, HttpResponseBadRequest, HttpResponseNotFound, - HttpRequest, + HttpResponseRedirect, + JsonResponse, ) from django.shortcuts import redirect, render from django.template.response import TemplateResponse from django.urls import reverse -from django.utils.html import mark_safe, escape as escape_html +from django.utils.html import escape as escape_html +from django.utils.html import mark_safe from django.views.decorators.http import require_http_methods from django.views.defaults import bad_request from adminapi.datatype import DatatypeError -from adminapi.filters import Any, ContainedOnlyBy, filter_classes, Not +from adminapi.filters import Any, ContainedOnlyBy, Not, filter_classes from adminapi.parse import parse_query from adminapi.request import json_encode_extra from serveradmin.dataset import Query -from serveradmin.serverdb.models import Servertype, Attribute, ServertypeAttribute, Server +from serveradmin.serverdb.models import Attribute, Server, Servertype, ServertypeAttribute from serveradmin.serverdb.query_committer import commit_query from serveradmin.servershell.helper import get_default_shown_attributes from serveradmin.servershell.merged_query_iterator import MergedQuery From 60ba128bc7bf7b61c9cc9f0dda2282b2ec82b7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kr=C3=B6ger?= Date: Wed, 26 Mar 2025 11:03:36 +0100 Subject: [PATCH 10/11] Fix FilterValueError Fix bug introduced during refactoring where we assumed all filters but be of instance BaseFilter which is of course wrong. --- adminapi/filters.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/adminapi/filters.py b/adminapi/filters.py index db725851..a546ec76 100644 --- a/adminapi/filters.py +++ b/adminapi/filters.py @@ -12,8 +12,10 @@ class BaseFilter(object): def __init__(self, value): - ok_datatypes = tuple([bool, int, float] + [s[0] for s in STR_BASED_DATATYPES]) - if type(self) is BaseFilter and isinstance(value, ok_datatypes): + ok_datatypes = tuple([int, float] + [s[0] for s in STR_BASED_DATATYPES]) + if type(self) is BaseFilter and isinstance(value, bool): + pass + elif isinstance(value, ok_datatypes): pass elif isinstance(value, str): for char in '\'"': From 376704a8e3b90475d3b121cb0d92435bbfb1a742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kr=C3=B6ger?= Date: Thu, 10 Apr 2025 11:48:03 +0200 Subject: [PATCH 11/11] Reformat files --- serveradmin/serverdb/query_materializer.py | 108 +-- serveradmin/serverdb/sql_generator.py | 200 +++-- .../serverdb/tests/test_ip_addr_type.py | 770 +++++++++--------- 3 files changed, 527 insertions(+), 551 deletions(-) diff --git a/serveradmin/serverdb/query_materializer.py b/serveradmin/serverdb/query_materializer.py index b4fafd5f..53e74b63 100644 --- a/serveradmin/serverdb/query_materializer.py +++ b/serveradmin/serverdb/query_materializer.py @@ -18,7 +18,8 @@ ServertypeAttribute, Server, ServerAttribute, - ServerRelationAttribute, ServerInetAttribute, + ServerRelationAttribute, + ServerInetAttribute, ) logger = logging.getLogger(__package__) @@ -30,19 +31,16 @@ def __init__(self, servers, joined_attributes, order_by_attributes=[]): self._joined_attributes = joined_attributes self._order_by_attributes = order_by_attributes # XXX: Optimize this query out - self._servertype_lookup = { - servertype.servertype_id: servertype - for servertype in Servertype.objects.all() - } + self._servertype_lookup = {servertype.servertype_id: servertype for servertype in Servertype.objects.all()} self._server_attributes = {} servers_by_type = {} for server in self._servers: self._server_attributes[server] = { - Attribute.specials["object_id"]: server.server_id, - Attribute.specials["hostname"]: server.hostname, - Attribute.specials["intern_ip"]: server.intern_ip, - Attribute.specials["servertype"]: server.servertype_id, + Attribute.specials['object_id']: server.server_id, + Attribute.specials['hostname']: server.hostname, + Attribute.specials['intern_ip']: server.intern_ip, + Attribute.specials['servertype']: server.servertype_id, } servers_by_type.setdefault(server.servertype_id, []).append(server) @@ -56,18 +54,12 @@ def __iter__(self): if self._order_by_attributes: def order_by_key(key): - return tuple( - self._get_order_by_attribute(key, a) - for a in self._order_by_attributes - ) + return tuple(self._get_order_by_attribute(key, a) for a in self._order_by_attributes) servers = sorted(servers, key=order_by_key) join_results = self._get_join_results() - return ( - DatasetObject(self._get_attributes(s, join_results), s.server_id) - for s in servers - ) + return (DatasetObject(self._get_attributes(s, join_results), s.server_id) for s in servers) def _select_attributes(self, servertype_ids): self._attributes_by_type = {} @@ -83,9 +75,7 @@ def _select_attributes(self, servertype_ids): def _select_servertype_attribute(self, attribute, sa): self._attributes_by_type.setdefault(attribute.type, set()).add(attribute) - self._servertype_ids_by_attribute.setdefault(attribute, []).append( - sa.servertype_id - ) + self._servertype_ids_by_attribute.setdefault(attribute, []).append(sa.servertype_id) related_via_attribute_id = sa.related_via_attribute_id if related_via_attribute_id: @@ -103,7 +93,7 @@ def _select_servertype_attribute(self, attribute, sa): servertype_id=sa.servertype_id, attribute_id=related_via_attribute_id, ) - .prefetch_related("attribute") + .prefetch_related('attribute') .get() ) self._select_servertype_attribute(sa.attribute, sa) @@ -118,37 +108,29 @@ def _initialize_attributes(self, servers_by_type): def _add_attributes(self, servers_by_type): """Add the attributes to the results""" for key, attributes in self._attributes_by_type.items(): - if key == "supernet": + if key == 'supernet': for attribute in attributes: self._add_supernet_attribute( attribute, - ( - s - for st in self._servertype_ids_by_attribute[attribute] - for s in servers_by_type[st] - ), + (s for st in self._servertype_ids_by_attribute[attribute] for s in servers_by_type[st]), ) - elif key == "domain": + elif key == 'domain': for attribute in attributes: self._add_domain_attribute( attribute, - [ - s - for st in self._servertype_ids_by_attribute[attribute] - for s in servers_by_type[st] - ], + [s for st in self._servertype_ids_by_attribute[attribute] for s in servers_by_type[st]], ) - elif key == "reverse": + elif key == 'reverse': reversed_attributes = {a.reversed_attribute_id: a for a in attributes} for sa in ( ServerRelationAttribute.objects.filter( value_id__in=self._server_attributes.keys(), attribute_id__in=reversed_attributes.keys(), ) - .prefetch_related("server") + .prefetch_related('server') .defer( - "server__intern_ip", - "server__servertype", + 'server__intern_ip', + 'server__servertype', ) ): self._add_attribute_value( @@ -164,10 +146,10 @@ def _add_attributes(self, servers_by_type): server__in=self._server_attributes.keys(), attribute__in=attributes, ) - .prefetch_related("server") + .prefetch_related('server') .defer( - "server__intern_ip", - "server__servertype", + 'server__intern_ip', + 'server__servertype', ) ): self._add_attribute_value( @@ -181,7 +163,7 @@ def _add_related_attributes(self, servers_by_type): self._add_related_attribute(attribute, sa, servers_by_type) def _add_domain_attribute(self, attribute, servers): - domain_names = {s.hostname.split(".", 1)[-1] for s in servers} + domain_names = {s.hostname.split('.', 1)[-1] for s in servers} domain_lookup = { domain.hostname: domain for domain in Server.objects.filter( @@ -191,9 +173,7 @@ def _add_domain_attribute(self, attribute, servers): } for server in servers: - self._server_attributes[server][attribute] = domain_lookup.get( - server.hostname.split(".", 1)[-1] - ) + self._server_attributes[server][attribute] = domain_lookup.get(server.hostname.split('.', 1)[-1]) def _add_supernet_attribute(self, attribute: Attribute, servers_in): """Calculate the supernet attribute of given servers @@ -236,15 +216,15 @@ def _add_supernet_attribute(self, attribute: Attribute, servers_in): supernets = Server.objects.raw( q, { - "target_servertype": attribute.target_servertype_id, - "address_family": attribute.inet_address_family, - "hosts": list(servers_by_id.keys()), + 'target_servertype': attribute.target_servertype_id, + 'address_family': attribute.inet_address_family, + 'hosts': list(servers_by_id.keys()), }, translations={ - "net.server_id": "server_id", - "net.hostname": "hostname", - "net.intern_ip": "intern_ip", - "net.servertype_id": "servertype_id", + 'net.server_id': 'server_id', + 'net.hostname': 'hostname', + 'net.intern_ip': 'intern_ip', + 'net.servertype_id': 'servertype_id', }, ) for cur_supernet in supernets: @@ -254,8 +234,8 @@ def _add_supernet_attribute(self, attribute: Attribute, servers_in): # TODO: Raise an exception once all data is cleaned up and conflicting # AF-unaware attributes are removed. logger.warning( - f"Conflicting supernet {attribute} for {cur_server.hostname}: " - f"{prev_supernet.host_attr_name}->{prev_supernet} vs {cur_supernet.host_attr_name}->{cur_supernet}" + f'Conflicting supernet {attribute} for {cur_server.hostname}: ' + f'{prev_supernet.host_attr_name}->{prev_supernet} vs {cur_supernet.host_attr_name}->{cur_supernet}' ) self._server_attributes[cur_server][attribute] = cur_supernet @@ -281,10 +261,10 @@ def _add_related_attribute(self, attribute, servertype_attribute, servers_by_typ server__hostname__in=servers_by_related.keys(), attribute=attribute, ) - .prefetch_related("server") + .prefetch_related('server') .defer( - "server__intern_ip", - "server__servertype", + 'server__intern_ip', + 'server__servertype', ) ): for target in servers_by_related[sa.server]: @@ -327,28 +307,24 @@ def _get_attributes(self, server, join_results): # NOQA: C901 if attribute not in self._joined_attributes: continue - if attribute.type == "inet": + if attribute.type == 'inet': if value is None: yield attribute.attribute_id, None else: - if servertype.ip_addr_type in ("host", "loadbalancer"): + if servertype.ip_addr_type in ('host', 'loadbalancer'): yield attribute.attribute_id, value.ip else: - assert servertype.ip_addr_type == "network" + assert servertype.ip_addr_type == 'network' yield attribute.attribute_id, value.network elif value is None: yield attribute.attribute_id, None elif attribute in join_results: if attribute.multi: - yield attribute.attribute_id, [ - join_results[attribute][v] for v in value - ] + yield attribute.attribute_id, [join_results[attribute][v] for v in value] else: yield (attribute.attribute_id, join_results[attribute][value]) elif attribute.multi: - yield attribute.attribute_id, { - v.hostname if isinstance(v, Server) else v for v in value - } + yield attribute.attribute_id, {v.hostname if isinstance(v, Server) else v for v in value} elif isinstance(value, Server): yield attribute.attribute_id, value.hostname else: @@ -396,7 +372,7 @@ def get_default_attribute_values(servertype_id): attribute_values = {} for attribute_id in Attribute.specials: - if attribute_id == "servertype": + if attribute_id == 'servertype': value = servertype_id else: value = None diff --git a/serveradmin/serverdb/sql_generator.py b/serveradmin/serverdb/sql_generator.py index 1e72edfe..f5007087 100644 --- a/serveradmin/serverdb/sql_generator.py +++ b/serveradmin/serverdb/sql_generator.py @@ -28,7 +28,9 @@ from serveradmin.serverdb.models import ( Server, ServerAttribute, - ServerRelationAttribute, ServerInetAttribute, Attribute, + ServerRelationAttribute, + ServerInetAttribute, + Attribute, ) @@ -36,19 +38,9 @@ # the functions to optimize related_via_attribute selection. We should find # a nicer way to achieve this. def get_server_query(attribute_filters, related_vias): - sql = ( - 'SELECT' - ' server.server_id,' - ' server.hostname,' - ' server.intern_ip,' - ' server.servertype_id' - ' FROM server' - ) + sql = 'SELECT' ' server.server_id,' ' server.hostname,' ' server.intern_ip,' ' server.servertype_id' ' FROM server' if attribute_filters: - sql += ' WHERE ' + ' AND '.join( - _get_sql_condition(a, f, related_vias) - for a, f in attribute_filters - ) + sql += ' WHERE ' + ' AND '.join(_get_sql_condition(a, f, related_vias) for a, f in attribute_filters) sql += ' ORDER BY server.hostname' return sql @@ -68,13 +60,11 @@ def _get_sql_condition(attribute, filt, related_vias): # complicated filters don't make any sense on booleans. if type(filt) is not BaseFilter: raise FilterValueError( - 'Boolean attribute "{}" cannot be used with {}() filter' - .format(attribute, type(filt).__name__) + 'Boolean attribute "{}" cannot be used with {}() filter'.format(attribute, type(filt).__name__) ) if not isinstance(filt.value, bool): raise FilterValueError( - 'Boolean attribute "{}" cannot be checked against {}' - .format(attribute, type(filt.value).__name__) + 'Boolean attribute "{}" cannot be checked against {}'.format(attribute, type(filt.value).__name__) ) negate = not filt.value @@ -96,26 +86,16 @@ def _get_sql_condition(attribute, filt, related_vias): def _covered_sql_condition(attribute, template, negate, related_vias): if attribute.type in ['relation', 'reverse', 'supernet', 'domain']: - template = ( - '{{0}} IN (' - ' SELECT server_id' - ' FROM server' - ' WHERE {}' - ')' - .format(template.format('hostname')) + template = '{{0}} IN (' ' SELECT server_id' ' FROM server' ' WHERE {}' ')'.format( + template.format('hostname') ) - return ( - ('NOT ' if negate else '') + - _condition_sql(attribute, template, related_vias) - ) + return ('NOT ' if negate else '') + _condition_sql(attribute, template, related_vias) def _logical_filter_sql_condition(attribute, filt, related_vias): if isinstance(filt, Not): - return 'NOT ({0})'.format( - _get_sql_condition(attribute, filt.value, related_vias) - ) + return 'NOT ({0})'.format(_get_sql_condition(attribute, filt.value, related_vias)) if isinstance(filt, All): joiner = ' AND ' @@ -131,21 +111,15 @@ def _logical_filter_sql_condition(attribute, filt, related_vias): if type(filt) is Any and type(value) is BaseFilter: simple_values.append(value) else: - templates.append( - _get_sql_condition(attribute, value, related_vias) - ) + templates.append(_get_sql_condition(attribute, value, related_vias)) if simple_values: if len(simple_values) == 1: - template = _get_sql_condition( - attribute, simple_values[0], related_vias - ) + template = _get_sql_condition(attribute, simple_values[0], related_vias) else: template = _covered_sql_condition( attribute, - '{{0}} IN ({0})'.format(', '.join( - _raw_sql_escape(v.value) for v in simple_values - )), + '{{0}} IN ({0})'.format(', '.join(_raw_sql_escape(v.value) for v in simple_values)), False, related_vias, ) @@ -164,45 +138,39 @@ def _basic_comparison_filter_template(attribute, filt): else: operator = '<=' - return '{{}} {} {}'.format( - operator, _raw_sql_escape(filt.value) - ) + return '{{}} {} {}'.format(operator, _raw_sql_escape(filt.value)) def _containment_filter_template(attribute, filt): - template = None # To be formatted 2 times + template = None # To be formatted 2 times value = filt.value if attribute.type == 'inet': if isinstance(filt, StartsWith): - template = "{{0}} >>= {0} AND host({{0}}) = host(0{})" + template = '{{0}} >>= {0} AND host({{0}}) = host(0{})' elif isinstance(filt, Contains): - template = "{{0}} >>= {0}" + template = '{{0}} >>= {0}' elif isinstance(filt, ContainedOnlyBy): - template = "{{0}} << {0} AND NOT " + _supernet_exists_sql( - attribute, 'supernet', + template = '{{0}} << {0} AND NOT ' + _supernet_exists_sql( + attribute, + 'supernet', '<< {0}', ('{{0}} << supernet.intern_ip',), ) elif isinstance(filt, ContainedBy): - template = "{{0}} <<= {0}" + template = '{{0}} <<= {0}' else: - template = "{{0}} && {0}" + template = '{{0}} && {0}' elif attribute.type == 'string': if isinstance(filt, Contains): - template = "{{0}} LIKE {0}" - value = '{}{}{}'.format( - '' if isinstance(filt, StartsWith) else '%', value, '%' - ) + template = '{{0}} LIKE {0}' + value = '{}{}{}'.format('' if isinstance(filt, StartsWith) else '%', value, '%') elif isinstance(filt, ContainedBy): template = "{0} LIKE '%%' || {{0}} || '%%'" if not template: - raise FilterValueError( - 'Cannot use {} filter on "{}"' - .format(type(filt).__name__, attribute) - ) + raise FilterValueError('Cannot use {} filter on "{}"'.format(type(filt).__name__, attribute)) return template.format(_raw_sql_escape(value)) @@ -213,26 +181,35 @@ def _condition_sql(attribute, template, related_vias): if attribute.type == 'supernet': return _supernet_exists_sql( - attribute, 'supernet', + attribute, + 'supernet', '>>= server_addr.value', ( f"supernet.servertype_id = '{attribute.target_servertype_id}'", template.format('supernet.server_id'), - ) + ), ) if attribute.type == 'domain': - return _exists_sql(Server, 'sub', ( - "sub.servertype_id = '{0}'".format(attribute.target_servertype_id), - "server.hostname ~ ('\\A[^\.]+\.' || regexp_replace(" - "sub.hostname, '(\*|\-|\.)', '\\\1', 'g') || '\\Z')", - template.format('sub.server_id'), - )) + return _exists_sql( + Server, + 'sub', + ( + "sub.servertype_id = '{0}'".format(attribute.target_servertype_id), + "server.hostname ~ ('\\A[^\.]+\.' || regexp_replace(" + "sub.hostname, '(\*|\-|\.)', '\\\1', 'g') || '\\Z')", + template.format('sub.server_id'), + ), + ) if attribute.type == 'reverse': - return _exists_sql(ServerRelationAttribute, 'sub', ( - "sub.attribute_id = '{0}'".format(attribute.reversed_attribute_id), - 'sub.value = server.server_id', - template.format('sub.server_id'), - )) + return _exists_sql( + ServerRelationAttribute, + 'sub', + ( + "sub.attribute_id = '{0}'".format(attribute.reversed_attribute_id), + 'sub.value = server.server_id', + template.format('sub.server_id'), + ), + ) return _real_condition_sql(attribute, template, related_vias) @@ -261,47 +238,58 @@ def _real_condition_sql(attribute, template, related_vias): relation_condition = 'server.server_id = sub.server_id' elif related_via_attribute.type == 'supernet': relation_condition = _supernet_exists_sql( - related_via_attribute, 'supernet', + related_via_attribute, + 'supernet', '>>= server_addr.value', ( f"supernet.servertype_id = '{related_via_attribute.target_servertype_id}'", - 'supernet.server_id = sub.server_id' + 'supernet.server_id = sub.server_id', ), ) elif related_via_attribute.type == 'reverse': - relation_condition = _exists_sql(ServerRelationAttribute, 'rel1', ( - "rel1.attribute_id = '{0}'".format( - related_via_attribute.reversed_attribute_id + relation_condition = _exists_sql( + ServerRelationAttribute, + 'rel1', + ( + "rel1.attribute_id = '{0}'".format(related_via_attribute.reversed_attribute_id), + 'rel1.value = server.server_id', + 'rel1.server_id = sub.server_id', ), - 'rel1.value = server.server_id', - 'rel1.server_id = sub.server_id', - )) + ) else: assert related_via_attribute.type == 'relation' - relation_condition = _exists_sql(ServerRelationAttribute, 'rel1', ( - "rel1.attribute_id = '{0}'" - .format(related_via_attribute.attribute_id), - 'rel1.server_id = server.server_id', - 'rel1.value = sub.server_id', - )) + relation_condition = _exists_sql( + ServerRelationAttribute, + 'rel1', + ( + "rel1.attribute_id = '{0}'".format(related_via_attribute.attribute_id), + 'rel1.server_id = server.server_id', + 'rel1.value = sub.server_id', + ), + ) relation_conditions.append((relation_condition, servertype_ids)) if len(relation_conditions) == 1: mixed_relation_condition = relation_conditions[0][0] else: - mixed_relation_condition = '({0})'.format(' OR '.join( - '({0} AND server.servertype_id IN ({1}))' - .format(relation_condition, ', '.join( - "'{0}'".format(s) for s in servertype_ids) + mixed_relation_condition = '({0})'.format( + ' OR '.join( + '({0} AND server.servertype_id IN ({1}))'.format( + relation_condition, ', '.join("'{0}'".format(s) for s in servertype_ids) + ) + for relation_condition, servertype_ids in relation_conditions ) - for relation_condition, servertype_ids in relation_conditions - )) + ) - return _exists_sql(model, 'sub', ( - mixed_relation_condition, - "sub.attribute_id = '{0}'".format(attribute.attribute_id), - template.format('sub.value'), - )) + return _exists_sql( + model, + 'sub', + ( + mixed_relation_condition, + "sub.attribute_id = '{0}'".format(attribute.attribute_id), + template.format('sub.value'), + ), + ) def _exists_sql(model, alias, conditions): @@ -326,11 +314,15 @@ def _supernet_exists_sql(attribute: Attribute, supernet_alias: str, addr_match: joins = ( (ServerInetAttribute._meta.db_table, 'server_addr', ('server_addr.server_id = server.server_id',)), - (ServerInetAttribute._meta.db_table, 'net_addr', ( - 'net_addr.value ' + addr_match, - 'net_addr.attribute_id = server_addr.attribute_id', - f'net_addr.server_id = {supernet_alias}.server_id', - )), + ( + ServerInetAttribute._meta.db_table, + 'net_addr', + ( + 'net_addr.value ' + addr_match, + 'net_addr.attribute_id = server_addr.attribute_id', + f'net_addr.server_id = {supernet_alias}.server_id', + ), + ), ) + af_join wheres = where + af_where @@ -339,7 +331,7 @@ def _supernet_exists_sql(attribute: Attribute, supernet_alias: str, addr_match: Server._meta.db_table, supernet_alias, ' '.join(f'JOIN {x[0]} AS {x[1]} ON ({" AND ".join(x[2])})' for x in joins), - ' AND '.join(c for c in wheres) + ' AND '.join(c for c in wheres), ) @@ -353,9 +345,7 @@ def _raw_sql_escape(value): raise FilterValueError('Single quote cannot be used') if value.endswith('\\'): - raise FilterValueError( - 'Escape character cannot be used in the end' - ) + raise FilterValueError('Escape character cannot be used in the end') value = value.replace('{', '{{').replace('}', '}}').replace('%', '%%') diff --git a/serveradmin/serverdb/tests/test_ip_addr_type.py b/serveradmin/serverdb/tests/test_ip_addr_type.py index 856cda92..59f015e2 100644 --- a/serveradmin/serverdb/tests/test_ip_addr_type.py +++ b/serveradmin/serverdb/tests/test_ip_addr_type.py @@ -25,12 +25,12 @@ class TestIpAddrType(TransactionTestCase): - fixtures = ["auth_user.json", "ip_addr_type.json"] + fixtures = ['auth_user.json', 'ip_addr_type.json'] @classmethod def setUpClass(cls): super().setUpClass() - logging.getLogger("faker").setLevel(logging.ERROR) + logging.getLogger('faker').setLevel(logging.ERROR) def setUp(self): super().setUp() @@ -39,7 +39,7 @@ def setUp(self): def _get_server(self, servertype: str) -> DatasetObject: server = Query().new_object(servertype) - server["hostname"] = self.faker.hostname() + server['hostname'] = self.faker.hostname() return server @@ -48,12 +48,12 @@ class TestIpAddrTypeNullForInternIp(TestIpAddrType): """Most important tests for ip_addr_type null and intern_ip""" def test_server_without_intern_ip(self): - server = self._get_server("null") + server = self._get_server('null') self.assertIsNone(server.commit(user=User.objects.first())) def test_server_with_intern_ip(self): - server = self._get_server("null") - server["intern_ip"] = "10.0.0.1" + server = self._get_server('null') + server['intern_ip'] = '10.0.0.1' with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) @@ -63,11 +63,11 @@ class TestIpAddrTypeNullForInetAttributes(TestIpAddrType): """Most important tests for ip_addr_type null and inet attributes""" def test_add_inet_attribute_in_admin_panel(self): - attr = ServertypeAttribute(attribute_id="ip_config_ipv4", servertype_id="null") + attr = ServertypeAttribute(attribute_id='ip_config_ipv4', servertype_id='null') form = ServertypeAttributeAdminForm( data={ - "attribute": "ip_config_ipv4", - "servertype": "null", + 'attribute': 'ip_config_ipv4', + 'servertype': 'null', }, instance=attr, ) @@ -80,57 +80,57 @@ class TestIpAddrTypeHostForInternIp(TestIpAddrType): """Most important tests for ip_addr_type host and intern_ip""" def test_server_without_value(self): - server = self._get_server("host") + server = self._get_server('host') with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_value(self): - server = self._get_server("host") - server["intern_ip"] = "10.0.0.1/32" + server = self._get_server('host') + server['intern_ip'] = '10.0.0.1/32' self.assertIsNone(server.commit(user=User.objects.first())) def test_server_with_invalid_value(self): - server = self._get_server("host") - server["intern_ip"] = "nonsense" + server = self._get_server('host') + server['intern_ip'] = 'nonsense' with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_ip_network(self): - server = self._get_server("host") - server["intern_ip"] = "10.0.0.0/16" + server = self._get_server('host') + server['intern_ip'] = '10.0.0.0/16' with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_duplicate_intern_ip(self): - first = self._get_server("host") - first["intern_ip"] = "10.0.0.1/32" + first = self._get_server('host') + first['intern_ip'] = '10.0.0.1/32' first.commit(user=User.objects.first()) - second = self._get_server("host") - second["intern_ip"] = "10.0.0.1" + second = self._get_server('host') + second['intern_ip'] = '10.0.0.1' with self.assertRaises(ValidationError): second.commit(user=User.objects.first()) def test_server_with_duplicate_inet_ip(self): - first = self._get_server("host") - first["intern_ip"] = "10.0.0.1/32" - first["ip_config_ipv4"] = "10.0.0.2/32" + first = self._get_server('host') + first['intern_ip'] = '10.0.0.1/32' + first['ip_config_ipv4'] = '10.0.0.2/32' first.commit(user=User.objects.first()) # Test "cross" duplicate attribute denial - duplicate = self._get_server("host") - duplicate["intern_ip"] = "10.0.0.2/32" + duplicate = self._get_server('host') + duplicate['intern_ip'] = '10.0.0.2/32' with self.assertRaises(ValidationError): duplicate.commit(user=User.objects.first()) def test_change_server_hostname(self): - server = self._get_server("host") - server["intern_ip"] = "10.0.0.1/32" + server = self._get_server('host') + server['intern_ip'] = '10.0.0.1/32' server.commit(user=User.objects.first()) - to_rename = Query({"hostname": server["hostname"]}, ["hostname"]) + to_rename = Query({'hostname': server['hostname']}, ['hostname']) to_rename.update(hostname=self.faker.hostname()) self.assertIsNone(to_rename.commit(user=User.objects.first())) @@ -139,99 +139,99 @@ class TestIpAddrTypeHostForInetAttributes(TestIpAddrType): """Most important tests for ip_addr_type host and inet attributes""" def test_server_without_value(self): - server = self._get_server("host") - server["intern_ip"] = "10.0.0.1/32" + server = self._get_server('host') + server['intern_ip'] = '10.0.0.1/32' self.assertIsNone(server.commit(user=User.objects.first())) def test_server_with_value(self): - server = self._get_server("host") - server["intern_ip"] = "10.0.0.1/32" - server["ip_config_ipv4"] = "10.0.0.2/32" + server = self._get_server('host') + server['intern_ip'] = '10.0.0.1/32' + server['ip_config_ipv4'] = '10.0.0.2/32' self.assertIsNone(server.commit(user=User.objects.first())) def test_server_with_invalid_value(self): - server = self._get_server("host") - server["intern_ip"] = "10.0.0.1/32" - server["ip_config_ipv4"] = "nonsense" + server = self._get_server('host') + server['intern_ip'] = '10.0.0.1/32' + server['ip_config_ipv4'] = 'nonsense' with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_ip_network(self): - server = self._get_server("host") - server["intern_ip"] = "10.0.0.1/32" - server["ip_config_ipv4"] = "10.0.0.0/16" + server = self._get_server('host') + server['intern_ip'] = '10.0.0.1/32' + server['ip_config_ipv4'] = '10.0.0.0/16' with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_duplicate_inet_attribute(self): - first = self._get_server("host") - first["intern_ip"] = "10.0.0.1/32" - first["ip_config_ipv4"] = "10.0.0.2/32" + first = self._get_server('host') + first['intern_ip'] = '10.0.0.1/32' + first['ip_config_ipv4'] = '10.0.0.2/32' first.commit(user=User.objects.first()) - second = self._get_server("host") - second["intern_ip"] = "10.0.0.3/32" - second["ip_config_ipv4"] = "10.0.0.2/32" + second = self._get_server('host') + second['intern_ip'] = '10.0.0.3/32' + second['ip_config_ipv4'] = '10.0.0.2/32' with self.assertRaises(ValidationError): second.commit(user=User.objects.first()) def test_server_overlaps_with_network(self): - network = self._get_server("route_network") - network["intern_ip"] = "10.0.0.5/32" - network["ip_config_ipv4"] = "10.0.1.5/32" + network = self._get_server('route_network') + network['intern_ip'] = '10.0.0.5/32' + network['ip_config_ipv4'] = '10.0.1.5/32' network.commit(user=User.objects.first()) # An ip_address must not collide with the smallest possible network - server = self._get_server("host") - server["intern_ip"] = "10.0.0.1/32" - server["ip_config_ipv4"] = "10.0.1.5/32" + server = self._get_server('host') + server['intern_ip'] = '10.0.0.1/32' + server['ip_config_ipv4'] = '10.0.1.5/32' self.assertIsNone(server.commit(user=User.objects.first())) def test_server_with_duplicate_intern_ip(self): - first = self._get_server("host") - first["intern_ip"] = "10.0.0.1/32" - first["ip_config_ipv4"] = "10.0.0.2/32" + first = self._get_server('host') + first['intern_ip'] = '10.0.0.1/32' + first['ip_config_ipv4'] = '10.0.0.2/32' first.commit(user=User.objects.first()) # Test "cross" duplicate attribute denial - duplicate = self._get_server("host") - duplicate["intern_ip"] = "10.0.0.3/32" - duplicate["ip_config_ipv4"] = "10.0.0.1/32" + duplicate = self._get_server('host') + duplicate['intern_ip'] = '10.0.0.3/32' + duplicate['ip_config_ipv4'] = '10.0.0.1/32' with self.assertRaises(ValidationError): duplicate.commit(user=User.objects.first()) def test_server_with_duplicate_inet_different_attrs(self): - server = self._get_server("host") - server["intern_ip"] = "10.0.0.1/32" - server["ip_config_ipv4"] = "10.0.0.2/32" + server = self._get_server('host') + server['intern_ip'] = '10.0.0.1/32' + server['ip_config_ipv4'] = '10.0.0.2/32' server.commit(user=User.objects.first()) - other_attribute = self._get_server("host") - other_attribute["intern_ip"] = "10.0.0.3/32" - other_attribute["ip_config_new"] = "10.0.0.2/32" + other_attribute = self._get_server('host') + other_attribute['intern_ip'] = '10.0.0.3/32' + other_attribute['ip_config_new'] = '10.0.0.2/32' self.assertIsNone(other_attribute.commit(user=User.objects.first())) def test_server_with_duplicate_inet_ip(self): - server = self._get_server("host") - server["intern_ip"] = "10.0.0.1/32" - server["ip_config_ipv4"] = "10.0.0.2/32" + server = self._get_server('host') + server['intern_ip'] = '10.0.0.1/32' + server['ip_config_ipv4'] = '10.0.0.2/32' server.commit(user=User.objects.first()) # Duplicate attribute is allowed because of different inet attribute type - duplicate = self._get_server("loadbalancer") - duplicate["intern_ip"] = "10.0.0.2/32" - duplicate["ip_config_ipv4"] = "10.0.0.1/32" + duplicate = self._get_server('loadbalancer') + duplicate['intern_ip'] = '10.0.0.2/32' + duplicate['ip_config_ipv4'] = '10.0.0.1/32' self.assertIsNone(duplicate.commit(user=User.objects.first())) def test_change_server_hostname(self): - server = self._get_server("host") - server["intern_ip"] = "10.0.0.1/32" - server["ip_config_ipv4"] = "10.0.0.2/32" + server = self._get_server('host') + server['intern_ip'] = '10.0.0.1/32' + server['ip_config_ipv4'] = '10.0.0.2/32' server.commit(user=User.objects.first()) - to_rename = Query({"hostname": server["hostname"]}, ["hostname"]) + to_rename = Query({'hostname': server['hostname']}, ['hostname']) to_rename.update(hostname=self.faker.hostname()) self.assertIsNone(to_rename.commit(user=User.objects.first())) @@ -240,36 +240,36 @@ class TestIpAddrTypeLoadbalancerForInternIp(TestIpAddrType): """Most important tests for ip_addr_type loadbalancer and intern_ip""" def test_server_without_value(self): - server = self._get_server("loadbalancer") + server = self._get_server('loadbalancer') with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_value(self): - server = self._get_server("loadbalancer") - server["intern_ip"] = "10.0.0.1/32" + server = self._get_server('loadbalancer') + server['intern_ip'] = '10.0.0.1/32' self.assertIsNone(server.commit(user=User.objects.first())) def test_server_with_ip_network(self): - server = self._get_server("loadbalancer") - server["intern_ip"] = "10.0.0.0/16" + server = self._get_server('loadbalancer') + server['intern_ip'] = '10.0.0.0/16' with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_duplicate_intern_ip(self): - first = self._get_server("loadbalancer") - first["intern_ip"] = "10.0.0.1/32" + first = self._get_server('loadbalancer') + first['intern_ip'] = '10.0.0.1/32' first.commit(user=User.objects.first()) - second = self._get_server("loadbalancer") - second["intern_ip"] = "10.0.0.1/32" + second = self._get_server('loadbalancer') + second['intern_ip'] = '10.0.0.1/32' self.assertIsNone(second.commit(user=User.objects.first())) def test_change_server_hostname(self): - server = self._get_server("loadbalancer") - server["intern_ip"] = "10.0.0.1/32" + server = self._get_server('loadbalancer') + server['intern_ip'] = '10.0.0.1/32' server.commit(user=User.objects.first()) - to_rename = Query({"hostname": server["hostname"]}, ["hostname"]) + to_rename = Query({'hostname': server['hostname']}, ['hostname']) to_rename.update(hostname=self.faker.hostname()) self.assertIsNone(to_rename.commit(user=User.objects.first())) @@ -278,64 +278,64 @@ class TestIpAddrTypeLoadbalancerForInetAttributes(TestIpAddrType): """Most important tests for ip_addr_type loadbalancer and inet attrs""" def test_server_without_value(self): - server = self._get_server("loadbalancer") - server["intern_ip"] = "10.0.0.1/32" + server = self._get_server('loadbalancer') + server['intern_ip'] = '10.0.0.1/32' self.assertIsNone(server.commit(user=User.objects.first())) def test_server_with_value(self): - server = self._get_server("loadbalancer") - server["intern_ip"] = "10.0.0.1/32" - server["ip_config_ipv4"] = "10.0.0.2/32" + server = self._get_server('loadbalancer') + server['intern_ip'] = '10.0.0.1/32' + server['ip_config_ipv4'] = '10.0.0.2/32' self.assertIsNone(server.commit(user=User.objects.first())) def test_server_with_ip_network(self): - server = self._get_server("loadbalancer") - server["intern_ip"] = "10.0.0.1/32" - server["ip_config_ipv4"] = "10.0.0.0/16" + server = self._get_server('loadbalancer') + server['intern_ip'] = '10.0.0.1/32' + server['ip_config_ipv4'] = '10.0.0.0/16' with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_duplicate_inet_attribute(self): - first = self._get_server("loadbalancer") - first["intern_ip"] = "10.0.0.1/32" - first["ip_config_ipv4"] = "10.0.0.2/32" + first = self._get_server('loadbalancer') + first['intern_ip'] = '10.0.0.1/32' + first['ip_config_ipv4'] = '10.0.0.2/32' first.commit(user=User.objects.first()) - second = self._get_server("loadbalancer") - second["intern_ip"] = "10.0.0.1/32" - second["ip_config_ipv4"] = "10.0.0.2/32" + second = self._get_server('loadbalancer') + second['intern_ip'] = '10.0.0.1/32' + second['ip_config_ipv4'] = '10.0.0.2/32' self.assertIsNone(second.commit(user=User.objects.first())) def test_server_with_duplicate_inet_ip(self): - first = self._get_server("loadbalancer") - first["intern_ip"] = "10.0.0.1/32" - first["ip_config_ipv4"] = "10.0.0.2/32" + first = self._get_server('loadbalancer') + first['intern_ip'] = '10.0.0.1/32' + first['ip_config_ipv4'] = '10.0.0.2/32' first.commit(user=User.objects.first()) # Duplicate attribute is allowed because of different inet attribute type - duplicate = self._get_server("host") - duplicate["intern_ip"] = "10.0.0.2/32" - duplicate["ip_config_ipv4"] = "10.0.0.1/32" + duplicate = self._get_server('host') + duplicate['intern_ip'] = '10.0.0.2/32' + duplicate['ip_config_ipv4'] = '10.0.0.1/32' self.assertIsNone(duplicate.commit(user=User.objects.first())) def test_server_with_duplicate_inet_different_attrs(self): - server = self._get_server("loadbalancer") - server["intern_ip"] = "10.0.0.1/32" - server["ip_config_ipv4"] = "10.0.0.2/32" + server = self._get_server('loadbalancer') + server['intern_ip'] = '10.0.0.1/32' + server['ip_config_ipv4'] = '10.0.0.2/32' server.commit(user=User.objects.first()) - duplicate = self._get_server("loadbalancer") - duplicate["intern_ip"] = "10.0.0.3/32" - duplicate["ip_config_new"] = "10.0.0.2/32" + duplicate = self._get_server('loadbalancer') + duplicate['intern_ip'] = '10.0.0.3/32' + duplicate['ip_config_new'] = '10.0.0.2/32' self.assertIsNone(duplicate.commit(user=User.objects.first())) def test_change_server_hostname(self): - server = self._get_server("loadbalancer") - server["intern_ip"] = "10.0.0.1/32" - server["ip_config_ipv4"] = "10.0.0.2/32" + server = self._get_server('loadbalancer') + server['intern_ip'] = '10.0.0.1/32' + server['ip_config_ipv4'] = '10.0.0.2/32' server.commit(user=User.objects.first()) - to_rename = Query({"hostname": server["hostname"]}, ["hostname"]) + to_rename = Query({'hostname': server['hostname']}, ['hostname']) to_rename.update(hostname=self.faker.hostname()) self.assertIsNone(to_rename.commit(user=User.objects.first())) @@ -344,80 +344,80 @@ class TestIpAddrTypeNetworkForInternIp(TestIpAddrType): """Most important tests for ip_addr_type network and intern_ip""" def test_server_without_value(self): - server = self._get_server("route_network") + server = self._get_server('route_network') with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_value(self): - server = self._get_server("route_network") - server["intern_ip"] = "10.0.0.0/16" + server = self._get_server('route_network') + server['intern_ip'] = '10.0.0.0/16' self.assertIsNone(server.commit(user=User.objects.first())) def test_server_with_invalid_value(self): - server = self._get_server("host") - server["intern_ip"] = "nonsense" + server = self._get_server('host') + server['intern_ip'] = 'nonsense' with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_invalid_network(self): - server = self._get_server("route_network") - server["intern_ip"] = "10.0.0.5/16" # Invalid: Has host bits set + server = self._get_server('route_network') + server['intern_ip'] = '10.0.0.5/16' # Invalid: Has host bits set with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_ip_address(self): - server = self._get_server("route_network") - server["intern_ip"] = "10.0.0.1/32" # Just a very small network + server = self._get_server('route_network') + server['intern_ip'] = '10.0.0.1/32' # Just a very small network self.assertIsNone(server.commit(user=User.objects.first())) def test_server_network_overlaps(self): - first = self._get_server("route_network") - first["intern_ip"] = "10.0.0.0/30" + first = self._get_server('route_network') + first['intern_ip'] = '10.0.0.0/30' first.commit(user=User.objects.first()) - overlaps = self._get_server("route_network") - overlaps["intern_ip"] = "10.0.0.0/28" + overlaps = self._get_server('route_network') + overlaps['intern_ip'] = '10.0.0.0/28' with self.assertRaises(ValidationError): overlaps.commit(user=User.objects.first()) def test_change_server_network_overlaps(self): - first = self._get_server("route_network") - first["intern_ip"] = "10.0.0.0/30" - first["ip_config_ipv4"] = "10.0.1.0/30" + first = self._get_server('route_network') + first['intern_ip'] = '10.0.0.0/30' + first['ip_config_ipv4'] = '10.0.1.0/30' first.commit(user=User.objects.first()) - host = Query({"hostname": first["hostname"]}, ["intern_ip"]) - host.update(intern_ip=IPv4Network("10.0.0.0/28")) + host = Query({'hostname': first['hostname']}, ['intern_ip']) + host.update(intern_ip=IPv4Network('10.0.0.0/28')) self.assertIsNone(host.commit(user=User.objects.first())) def test_server_network_overlaps_inet(self): - first = self._get_server("route_network") - first["intern_ip"] = "10.0.0.0/30" - first["ip_config_ipv4"] = "10.0.1.0/30" + first = self._get_server('route_network') + first['intern_ip'] = '10.0.0.0/30' + first['ip_config_ipv4'] = '10.0.1.0/30' first.commit(user=User.objects.first()) - overlaps = self._get_server("route_network") - overlaps["intern_ip"] = "10.0.1.0/28" + overlaps = self._get_server('route_network') + overlaps['intern_ip'] = '10.0.1.0/28' with self.assertRaises(ValidationError): overlaps.commit(user=User.objects.first()) def test_server_network_overlaps_other_servertype(self): - first = self._get_server("route_network") - first["intern_ip"] = "10.0.0.0/30" + first = self._get_server('route_network') + first['intern_ip'] = '10.0.0.0/30' first.commit(user=User.objects.first()) # A network can overlap with networks of other servertypes - overlaps = self._get_server("provider_network") - overlaps["intern_ip"] = "10.0.0.0/28" + overlaps = self._get_server('provider_network') + overlaps['intern_ip'] = '10.0.0.0/28' self.assertIsNone(overlaps.commit(user=User.objects.first())) def test_change_server_hostname(self): - server = self._get_server("route_network") - server["intern_ip"] = "10.0.0.0/30" + server = self._get_server('route_network') + server['intern_ip'] = '10.0.0.0/30' server.commit(user=User.objects.first()) - to_rename = Query({"hostname": server["hostname"]}, ["hostname"]) + to_rename = Query({'hostname': server['hostname']}, ['hostname']) to_rename.update(hostname=self.faker.hostname()) self.assertIsNone(to_rename.commit(user=User.objects.first())) @@ -426,101 +426,101 @@ class TestIpAddrTypeNetworkForInetAttributes(TestIpAddrType): """Most important tests for ip_addr_type network and inet attrs""" def test_server_without_value(self): - server = self._get_server("route_network") - server["intern_ip"] = "10.0.0.0/16" + server = self._get_server('route_network') + server['intern_ip'] = '10.0.0.0/16' self.assertIsNone(server.commit(user=User.objects.first())) def test_server_with_value(self): - server = self._get_server("route_network") - server["intern_ip"] = "10.0.0.0/30" - server["ip_config_ipv4"] = "10.0.1.0/30" + server = self._get_server('route_network') + server['intern_ip'] = '10.0.0.0/30' + server['ip_config_ipv4'] = '10.0.1.0/30' self.assertIsNone(server.commit(user=User.objects.first())) def test_server_with_invalid_value(self): - server = self._get_server("host") - server["intern_ip"] = "10.0.0.0/30" - server["ip_config_ipv4"] = "nonsense" + server = self._get_server('host') + server['intern_ip'] = '10.0.0.0/30' + server['ip_config_ipv4'] = 'nonsense' with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_invalid_network(self): - server = self._get_server("route_network") - server["intern_ip"] = "10.0.0.0/16" - server["ip_config_ipv4"] = "10.0.1.5/28" # Invalid: Has host bits set + server = self._get_server('route_network') + server['intern_ip'] = '10.0.0.0/16' + server['ip_config_ipv4'] = '10.0.1.5/28' # Invalid: Has host bits set with self.assertRaises(ValidationError): server.commit(user=User.objects.first()) def test_server_with_ip_address(self): - server = self._get_server("route_network") - server["intern_ip"] = "10.0.0.1/32" # Just a very small network - server["ip_config_ipv4"] = "10.0.1.0/32" # Just a very small network + server = self._get_server('route_network') + server['intern_ip'] = '10.0.0.1/32' # Just a very small network + server['ip_config_ipv4'] = '10.0.1.0/32' # Just a very small network self.assertIsNone(server.commit(user=User.objects.first())) def test_server_network_overlaps(self): - first = self._get_server("route_network") - first["intern_ip"] = "10.0.0.0/30" - first["ip_config_ipv4"] = "10.0.1.0/30" + first = self._get_server('route_network') + first['intern_ip'] = '10.0.0.0/30' + first['ip_config_ipv4'] = '10.0.1.0/30' first.commit(user=User.objects.first()) - overlaps = self._get_server("route_network") - overlaps["intern_ip"] = "10.0.3.0/30" - overlaps["ip_config_ipv4"] = "10.0.1.0/28" + overlaps = self._get_server('route_network') + overlaps['intern_ip'] = '10.0.3.0/30' + overlaps['ip_config_ipv4'] = '10.0.1.0/28' with self.assertRaises(ValidationError): overlaps.commit(user=User.objects.first()) def test_change_server_network_overlaps(self): - first = self._get_server("route_network") - first["intern_ip"] = "10.0.0.0/30" - first["ip_config_ipv4"] = "10.0.1.0/30" + first = self._get_server('route_network') + first['intern_ip'] = '10.0.0.0/30' + first['ip_config_ipv4'] = '10.0.1.0/30' first.commit(user=User.objects.first()) - host = Query({"hostname": first["hostname"]}, ["ip_config_ipv4"]) - host.update(ip_config_ipv4=IPv4Network("10.0.1.0/28")) + host = Query({'hostname': first['hostname']}, ['ip_config_ipv4']) + host.update(ip_config_ipv4=IPv4Network('10.0.1.0/28')) self.assertIsNone(host.commit(user=User.objects.first())) def test_server_network_overlaps_intern_ip(self): - first = self._get_server("route_network") - first["intern_ip"] = "10.0.0.0/30" + first = self._get_server('route_network') + first['intern_ip'] = '10.0.0.0/30' first.commit(user=User.objects.first()) - overlaps = self._get_server("route_network") - overlaps["intern_ip"] = "10.0.1.0/28" - overlaps["ip_config_ipv4"] = "10.0.0.0/28" + overlaps = self._get_server('route_network') + overlaps['intern_ip'] = '10.0.1.0/28' + overlaps['ip_config_ipv4'] = '10.0.0.0/28' with self.assertRaises(ValidationError): overlaps.commit(user=User.objects.first()) def test_server_network_is_equal(self): - first = self._get_server("route_network") - first["intern_ip"] = "10.0.0.0/30" - first["ip_config_ipv4"] = "10.0.1.0/30" + first = self._get_server('route_network') + first['intern_ip'] = '10.0.0.0/30' + first['ip_config_ipv4'] = '10.0.1.0/30' first.commit(user=User.objects.first()) - equal = self._get_server("route_network") - equal["intern_ip"] = "10.0.2.0/30" - equal["ip_config_ipv4"] = "10.0.1.0/30" + equal = self._get_server('route_network') + equal['intern_ip'] = '10.0.2.0/30' + equal['ip_config_ipv4'] = '10.0.1.0/30' with self.assertRaises(ValidationError): equal.commit(user=User.objects.first()) def test_server_network_overlaps_other_servertype(self): - first = self._get_server("route_network") - first["intern_ip"] = "10.0.0.0/30" - first["ip_config_ipv4"] = "10.0.1.0/30" + first = self._get_server('route_network') + first['intern_ip'] = '10.0.0.0/30' + first['ip_config_ipv4'] = '10.0.1.0/30' first.commit(user=User.objects.first()) # A network can overlap with networks of other servertypes - overlaps = self._get_server("provider_network") - overlaps["intern_ip"] = "10.0.0.0/28" - overlaps["ip_config_ipv4"] = "10.0.1.0/30" + overlaps = self._get_server('provider_network') + overlaps['intern_ip'] = '10.0.0.0/28' + overlaps['ip_config_ipv4'] = '10.0.1.0/30' self.assertIsNone(overlaps.commit(user=User.objects.first())) def test_change_server_hostname(self): - server = self._get_server("route_network") - server["intern_ip"] = "10.0.0.0/30" - server["ip_config_ipv4"] = "10.0.1.0/30" + server = self._get_server('route_network') + server['intern_ip'] = '10.0.0.0/30' + server['ip_config_ipv4'] = '10.0.1.0/30' server.commit(user=User.objects.first()) - to_rename = Query({"hostname": server["hostname"]}, ["hostname"]) + to_rename = Query({'hostname': server['hostname']}, ['hostname']) to_rename.update(hostname=self.faker.hostname()) self.assertIsNone(to_rename.commit(user=User.objects.first())) @@ -530,91 +530,91 @@ def test_af_unaware_supernet_consistent(self): # AF-unaware supernet attribute will be properly calculated when # both IPv4 and IPv6 addresses belong to the same supernet. - network = self._get_server("route_network") - network["intern_ip"] = "192.0.2.0/24" - network["ip_config_ipv4"] = "192.0.2.0/24" - network["ip_config_ipv6"] = "2001:db8::/64" + network = self._get_server('route_network') + network['intern_ip'] = '192.0.2.0/24' + network['ip_config_ipv4'] = '192.0.2.0/24' + network['ip_config_ipv6'] = '2001:db8::/64' network.commit(user=User.objects.first()) - server = self._get_server("host") - server["intern_ip"] = "192.0.2.1" - server["ip_config_ipv4"] = "192.0.2.1" - server["ip_config_ipv6"] = "2001:db8::1" + server = self._get_server('host') + server['intern_ip'] = '192.0.2.1' + server['ip_config_ipv4'] = '192.0.2.1' + server['ip_config_ipv6'] = '2001:db8::1' server.commit(user=User.objects.first()) server_q = Query( - {"hostname": server["hostname"]}, - ["supernet_no_af"], + {'hostname': server['hostname']}, + ['supernet_no_af'], ).get() - self.assertEqual(server_q["supernet_no_af"], network["hostname"]) + self.assertEqual(server_q['supernet_no_af'], network['hostname']) def test_af_unaware_supernet_missing_ipv6(self): # AF-unaware supernet attribute will be properly calculated when # the IPv6 address does not belong to a supernet, even if it's present. - network = self._get_server("route_network") - network["intern_ip"] = "192.0.2.0/24" - network["ip_config_ipv4"] = "192.0.2.0/24" - network["ip_config_ipv6"] = "2001:db8::/64" + network = self._get_server('route_network') + network['intern_ip'] = '192.0.2.0/24' + network['ip_config_ipv4'] = '192.0.2.0/24' + network['ip_config_ipv6'] = '2001:db8::/64' network.commit(user=User.objects.first()) - server = self._get_server("host") - server["intern_ip"] = "192.0.2.1" - server["ip_config_ipv4"] = "192.0.2.1" - server["ip_config_ipv6"] = "2001:db8:2::1" + server = self._get_server('host') + server['intern_ip'] = '192.0.2.1' + server['ip_config_ipv4'] = '192.0.2.1' + server['ip_config_ipv6'] = '2001:db8:2::1' server.commit(user=User.objects.first()) server_q = Query( - {"hostname": server["hostname"]}, - ["supernet_no_af"], + {'hostname': server['hostname']}, + ['supernet_no_af'], ).get() - self.assertEqual(server_q["supernet_no_af"], network["hostname"]) + self.assertEqual(server_q['supernet_no_af'], network['hostname']) def test_af_unaware_supernet_missing_ipv4(self): # AF-unaware supernet attribute will be properly calculated when # the IPv4 address does not belong to a supernet, even if it's present. - network = self._get_server("route_network") - network["intern_ip"] = "192.0.2.0/24" - network["ip_config_ipv4"] = "192.0.2.0/24" - network["ip_config_ipv6"] = "2001:db8::/64" + network = self._get_server('route_network') + network['intern_ip'] = '192.0.2.0/24' + network['ip_config_ipv4'] = '192.0.2.0/24' + network['ip_config_ipv6'] = '2001:db8::/64' network.commit(user=User.objects.first()) - server = self._get_server("host") - server["intern_ip"] = "198.51.100.1" - server["ip_config_ipv4"] = "198.51.100.1" - server["ip_config_ipv6"] = "2001:db8::1" + server = self._get_server('host') + server['intern_ip'] = '198.51.100.1' + server['ip_config_ipv4'] = '198.51.100.1' + server['ip_config_ipv6'] = '2001:db8::1' server.commit(user=User.objects.first()) server_q = Query( - {"hostname": server["hostname"]}, - ["supernet_no_af"], + {'hostname': server['hostname']}, + ['supernet_no_af'], ).get() - self.assertEqual(server_q["supernet_no_af"], network["hostname"]) + self.assertEqual(server_q['supernet_no_af'], network['hostname']) def test_af_unaware_supernet_conflicting(self): # AF-unaware supernet attribute will fail when # IPv4 and IPv6 addresses belongs to different subnets. - network1 = self._get_server("route_network") - network1["intern_ip"] = "192.0.2.0/24" - network1["ip_config_ipv4"] = "192.0.2.0/24" - network1["ip_config_ipv6"] = "2001:db8:1::/64" + network1 = self._get_server('route_network') + network1['intern_ip'] = '192.0.2.0/24' + network1['ip_config_ipv4'] = '192.0.2.0/24' + network1['ip_config_ipv6'] = '2001:db8:1::/64' network1.commit(user=User.objects.first()) - network2 = self._get_server("route_network") - network2["intern_ip"] = "198.51.100.0/24" - network2["ip_config_ipv4"] = "198.51.100.0/24" - network2["ip_config_ipv6"] = "2001:db8:2::/64" + network2 = self._get_server('route_network') + network2['intern_ip'] = '198.51.100.0/24' + network2['ip_config_ipv4'] = '198.51.100.0/24' + network2['ip_config_ipv6'] = '2001:db8:2::/64' network2.commit(user=User.objects.first()) - server = self._get_server("host") - server["intern_ip"] = "192.0.2.1" - server["ip_config_ipv4"] = "192.0.2.1" - server["ip_config_ipv6"] = "2001:db8:2::1" + server = self._get_server('host') + server['intern_ip'] = '192.0.2.1' + server['ip_config_ipv4'] = '192.0.2.1' + server['ip_config_ipv6'] = '2001:db8:2::1' # TODO: Raise an exception once all data is cleaned up and conflicting # AF-unaware attributes are removed. @@ -622,14 +622,14 @@ def test_af_unaware_supernet_conflicting(self): server.commit(user=User.objects.first()) server_q = Query( - {"hostname": server["hostname"]}, - ["supernet_no_af"], + {'hostname': server['hostname']}, + ['supernet_no_af'], ).get() self.assertIn( - server_q["supernet_no_af"], + server_q['supernet_no_af'], [ - network1["hostname"], - network2["hostname"], + network1['hostname'], + network2['hostname'], ], ) @@ -637,105 +637,104 @@ def test_af_aware_supernet(self): # AF-aware supernet attributes can be calculated when # IPv4 and IPv6 addresses belong to different subnets. - network_ipv4 = self._get_server("provider_network") - network_ipv4["intern_ip"] = "192.0.2.0/24" - network_ipv4["ip_config_ipv4"] = "192.0.2.0/24" + network_ipv4 = self._get_server('provider_network') + network_ipv4['intern_ip'] = '192.0.2.0/24' + network_ipv4['ip_config_ipv4'] = '192.0.2.0/24' network_ipv4.commit(user=User.objects.first()) - network_ipv6 = self._get_server("provider_network") - network_ipv6["intern_ip"] = "2001:db8::/64" - network_ipv6["ip_config_ipv6"] = "2001:db8::/64" + network_ipv6 = self._get_server('provider_network') + network_ipv6['intern_ip'] = '2001:db8::/64' + network_ipv6['ip_config_ipv6'] = '2001:db8::/64' network_ipv6.commit(user=User.objects.first()) - server = self._get_server("host") - server["intern_ip"] = "192.0.2.1" - server["ip_config_ipv4"] = "192.0.2.1" - server["ip_config_ipv6"] = "2001:db8::1" + server = self._get_server('host') + server['intern_ip'] = '192.0.2.1' + server['ip_config_ipv4'] = '192.0.2.1' + server['ip_config_ipv6'] = '2001:db8::1' server.commit(user=User.objects.first()) server_q = Query( - {"hostname": server["hostname"]}, - ["supernet_ipv4", "supernet_ipv6"], + {'hostname': server['hostname']}, + ['supernet_ipv4', 'supernet_ipv6'], ).get() - self.assertEqual(server_q["supernet_ipv4"], network_ipv4["hostname"]) - self.assertEqual(server_q["supernet_ipv6"], network_ipv6["hostname"]) + self.assertEqual(server_q['supernet_ipv4'], network_ipv4['hostname']) + self.assertEqual(server_q['supernet_ipv6'], network_ipv6['hostname']) def test_af_aware_unaware_supernet(self): # AF-aware and unaware supernets can be used together. - rn = self._get_server("route_network") - rn["intern_ip"] = "192.0.2.0/24" - rn["ip_config_ipv4"] = "192.0.2.0/24" - rn["ip_config_ipv6"] = "2001:db8::/64" + rn = self._get_server('route_network') + rn['intern_ip'] = '192.0.2.0/24' + rn['ip_config_ipv4'] = '192.0.2.0/24' + rn['ip_config_ipv6'] = '2001:db8::/64' rn.commit(user=User.objects.first()) - pn_ipv4 = self._get_server("provider_network") - pn_ipv4["intern_ip"] = "192.0.2.0/24" - pn_ipv4["ip_config_ipv4"] = "192.0.2.0/24" + pn_ipv4 = self._get_server('provider_network') + pn_ipv4['intern_ip'] = '192.0.2.0/24' + pn_ipv4['ip_config_ipv4'] = '192.0.2.0/24' pn_ipv4.commit(user=User.objects.first()) - pn_ipv6 = self._get_server("provider_network") - pn_ipv6["intern_ip"] = "2001:db8::/64" - pn_ipv6["ip_config_ipv6"] = "2001:db8::/64" + pn_ipv6 = self._get_server('provider_network') + pn_ipv6['intern_ip'] = '2001:db8::/64' + pn_ipv6['ip_config_ipv6'] = '2001:db8::/64' pn_ipv6.commit(user=User.objects.first()) - server = self._get_server("host") - server["intern_ip"] = "192.0.2.1" - server["ip_config_ipv4"] = "192.0.2.1" - server["ip_config_ipv6"] = "2001:db8::1" + server = self._get_server('host') + server['intern_ip'] = '192.0.2.1' + server['ip_config_ipv4'] = '192.0.2.1' + server['ip_config_ipv6'] = '2001:db8::1' server.commit(user=User.objects.first()) server_q = Query( - {"hostname": server["hostname"]}, - ["supernet_no_af", "supernet_ipv4", "supernet_ipv6"], + {'hostname': server['hostname']}, + ['supernet_no_af', 'supernet_ipv4', 'supernet_ipv6'], ).get() - self.assertEqual(server_q["supernet_no_af"], rn["hostname"]) - self.assertEqual(server_q["supernet_ipv4"], pn_ipv4["hostname"]) - self.assertEqual(server_q["supernet_ipv6"], pn_ipv6["hostname"]) + self.assertEqual(server_q['supernet_no_af'], rn['hostname']) + self.assertEqual(server_q['supernet_ipv4'], pn_ipv4['hostname']) + self.assertEqual(server_q['supernet_ipv6'], pn_ipv6['hostname']) class TestIpAddrTypeHostForSupernetQuery(TestIpAddrType): def setUp(self): super().setUp() - self.pn_ipv4 = self._get_server("provider_network") - self.pn_ipv4["intern_ip"] = "192.0.2.0/24" - self.pn_ipv4["ip_config_ipv4"] = "192.0.2.0/24" - self.pn_ipv4["network_type_ipv4"] = "public_ipv4" + self.pn_ipv4 = self._get_server('provider_network') + self.pn_ipv4['intern_ip'] = '192.0.2.0/24' + self.pn_ipv4['ip_config_ipv4'] = '192.0.2.0/24' + self.pn_ipv4['network_type_ipv4'] = 'public_ipv4' self.pn_ipv4.commit(user=User.objects.first()) - - self.rn_ipv4 = self._get_server("route_network") - self.rn_ipv4["intern_ip"] = "192.0.2.0/28" - self.rn_ipv4["ip_config_ipv4"] = "192.0.2.0/28" - self.rn_ipv4["network_type"] = "internal_ipv4" + + self.rn_ipv4 = self._get_server('route_network') + self.rn_ipv4['intern_ip'] = '192.0.2.0/28' + self.rn_ipv4['ip_config_ipv4'] = '192.0.2.0/28' + self.rn_ipv4['network_type'] = 'internal_ipv4' self.rn_ipv4.commit(user=User.objects.first()) - self.pn_ipv6 = self._get_server("provider_network") - self.pn_ipv6["intern_ip"] = "2001:db8::/64" - self.pn_ipv6["ip_config_ipv6"] = "2001:db8::/64" - self.pn_ipv6["network_type_ipv6"] = "internal_ipv6" + self.pn_ipv6 = self._get_server('provider_network') + self.pn_ipv6['intern_ip'] = '2001:db8::/64' + self.pn_ipv6['ip_config_ipv6'] = '2001:db8::/64' + self.pn_ipv6['network_type_ipv6'] = 'internal_ipv6' self.pn_ipv6.commit(user=User.objects.first()) - self.rn_ipv6 = self._get_server("route_network") - self.rn_ipv6["intern_ip"] = "2001:db8::0010/124" - self.rn_ipv6["ip_config_ipv6"] = "2001:db8::0010/124" - self.rn_ipv6["network_type"] = "internal_ipv6" + self.rn_ipv6 = self._get_server('route_network') + self.rn_ipv6['intern_ip'] = '2001:db8::0010/124' + self.rn_ipv6['ip_config_ipv6'] = '2001:db8::0010/124' + self.rn_ipv6['network_type'] = 'internal_ipv6' self.rn_ipv6.commit(user=User.objects.first()) - self.server_pn = self._get_server("host") - self.server_pn["intern_ip"] = "192.0.2.17" - self.server_pn["ip_config_ipv4"] = "192.0.2.17" - self.server_pn["ip_config_ipv6"] = "2001:db8::0021" + self.server_pn = self._get_server('host') + self.server_pn['intern_ip'] = '192.0.2.17' + self.server_pn['ip_config_ipv4'] = '192.0.2.17' + self.server_pn['ip_config_ipv6'] = '2001:db8::0021' self.server_pn.commit(user=User.objects.first()) - self.server_rn = self._get_server("host") - self.server_rn["intern_ip"] = "192.0.2.1" - self.server_rn["ip_config_ipv4"] = "192.0.2.1" - self.server_rn["ip_config_ipv6"] = "2001:db8::0011" + self.server_rn = self._get_server('host') + self.server_rn['intern_ip'] = '192.0.2.1' + self.server_rn['ip_config_ipv4'] = '192.0.2.1' + self.server_rn['ip_config_ipv6'] = '2001:db8::0011' self.server_rn.commit(user=User.objects.first()) - def test_af_unaware_supernet(self): # Query a related attribute over an AF-unaware supernet # @@ -745,21 +744,21 @@ def test_af_unaware_supernet(self): # is a single-attribute, only one of those networks is returned. server_q = Query( - {"supernet_no_af": self.rn_ipv4["hostname"], "servertype": "host"}, - ["hostname", "supernet_no_af"], + {'supernet_no_af': self.rn_ipv4['hostname'], 'servertype': 'host'}, + ['hostname', 'supernet_no_af'], ).get() self.assertIn( - server_q["supernet_no_af"], - (self.rn_ipv4["hostname"], self.rn_ipv6["hostname"]), + server_q['supernet_no_af'], + (self.rn_ipv4['hostname'], self.rn_ipv6['hostname']), ) server_q = Query( - {"supernet_no_af": self.rn_ipv6["hostname"], "servertype": "host"}, - ["hostname", "supernet_no_af"], + {'supernet_no_af': self.rn_ipv6['hostname'], 'servertype': 'host'}, + ['hostname', 'supernet_no_af'], ).get() self.assertIn( - server_q["supernet_no_af"], - (self.rn_ipv4["hostname"], self.rn_ipv6["hostname"]), + server_q['supernet_no_af'], + (self.rn_ipv4['hostname'], self.rn_ipv6['hostname']), ) def test_af_unaware_supernet_related(self): @@ -771,139 +770,150 @@ def test_af_unaware_supernet_related(self): # is a single-attribute, only one of those networks is returned. server_q = Query( - {"network_type": "internal_ipv4", "servertype": "host"}, - ["hostname", "supernet_no_af"], + {'network_type': 'internal_ipv4', 'servertype': 'host'}, + ['hostname', 'supernet_no_af'], ).get() self.assertIn( - server_q["supernet_no_af"], - (self.rn_ipv4["hostname"], self.rn_ipv6["hostname"]), + server_q['supernet_no_af'], + (self.rn_ipv4['hostname'], self.rn_ipv6['hostname']), ) server_q = Query( - {"network_type": "internal_ipv6", "servertype": "host"}, - ["hostname", "supernet_no_af"], + {'network_type': 'internal_ipv6', 'servertype': 'host'}, + ['hostname', 'supernet_no_af'], ).get() self.assertIn( - server_q["supernet_no_af"], - (self.rn_ipv4["hostname"], self.rn_ipv6["hostname"]), + server_q['supernet_no_af'], + (self.rn_ipv4['hostname'], self.rn_ipv6['hostname']), ) def test_af_aware_supernet(self): # Querying for AF-aware supernet attribute will find only objects # matching the given address family. - server_q = list(Query( - {"supernet_ipv4": self.pn_ipv4["hostname"], "servertype": "host"}, - ["hostname", "supernet_ipv4", "ip_config_ipv4"], - ["ip_config_ipv4"] - )) + server_q = list( + Query( + {'supernet_ipv4': self.pn_ipv4['hostname'], 'servertype': 'host'}, + ['hostname', 'supernet_ipv4', 'ip_config_ipv4'], + ['ip_config_ipv4'], + ) + ) self.assertEqual(len(server_q), 2) - self.assertEqual(server_q[0]["hostname"], self.server_rn["hostname"]) - self.assertEqual(server_q[0]["supernet_ipv4"], self.pn_ipv4["hostname"]) - self.assertEqual(server_q[1]["hostname"], self.server_pn["hostname"]) - self.assertEqual(server_q[1]["supernet_ipv4"], self.pn_ipv4["hostname"]) + self.assertEqual(server_q[0]['hostname'], self.server_rn['hostname']) + self.assertEqual(server_q[0]['supernet_ipv4'], self.pn_ipv4['hostname']) + self.assertEqual(server_q[1]['hostname'], self.server_pn['hostname']) + self.assertEqual(server_q[1]['supernet_ipv4'], self.pn_ipv4['hostname']) # Test that af_q is correctly applied in _condition_sql with self.assertRaises(DatasetError): server_q = Query( - {"supernet_ipv4": self.pn_ipv6["hostname"], "servertype": "host"}, - ["hostname", "supernet_ipv4"], + {'supernet_ipv4': self.pn_ipv6['hostname'], 'servertype': 'host'}, + ['hostname', 'supernet_ipv4'], ).get() with self.assertRaises(DatasetError): server_q = Query( - {"supernet_ipv6": self.pn_ipv4["hostname"], "servertype": "host"}, - ["hostname", "supernet_ipv6"], + {'supernet_ipv6': self.pn_ipv4['hostname'], 'servertype': 'host'}, + ['hostname', 'supernet_ipv6'], ).get() def test_af_aware_supernet_related(self): # Query a related attribute over an AF-aware supernet - server_q = list(Query( - {"network_type_ipv4": "public_ipv4", "servertype": "host"}, - ["hostname", "ip_config_ipv4", "network_type_ipv4", "network_type_ipv6"], - ["ip_config_ipv4"], - )) + server_q = list( + Query( + {'network_type_ipv4': 'public_ipv4', 'servertype': 'host'}, + ['hostname', 'ip_config_ipv4', 'network_type_ipv4', 'network_type_ipv6'], + ['ip_config_ipv4'], + ) + ) self.assertEqual(len(server_q), 2) - self.assertEqual(server_q[0]["hostname"], self.server_rn["hostname"]) - self.assertEqual(server_q[0]["network_type_ipv4"], self.pn_ipv4["network_type_ipv4"]) - self.assertEqual(server_q[1]["hostname"], self.server_pn["hostname"]) - self.assertEqual(server_q[1]["network_type_ipv4"], self.pn_ipv4["network_type_ipv4"]) + self.assertEqual(server_q[0]['hostname'], self.server_rn['hostname']) + self.assertEqual(server_q[0]['network_type_ipv4'], self.pn_ipv4['network_type_ipv4']) + self.assertEqual(server_q[1]['hostname'], self.server_pn['hostname']) + self.assertEqual(server_q[1]['network_type_ipv4'], self.pn_ipv4['network_type_ipv4']) with self.assertRaises(DatasetError): server_q = Query( - {"supernet_ipv6": self.pn_ipv4["network_type_ipv4"], "servertype": "host"}, - ["hostname", "supernet_ipv6", "ip_config_ipv6"], - ["ip_config_ipv6"] + {'supernet_ipv6': self.pn_ipv4['network_type_ipv4'], 'servertype': 'host'}, + ['hostname', 'supernet_ipv6', 'ip_config_ipv6'], + ['ip_config_ipv6'], ).get() # Test that af_q is correctly applied in _real_condition_sql with self.assertRaises(DatasetError): server_q = Query( - {"network_type_ipv4": "public_ipv6", "servertype": "host"}, - ["hostname", "network_type_ipv4", "network_type_ipv6"], + {'network_type_ipv4': 'public_ipv6', 'servertype': 'host'}, + ['hostname', 'network_type_ipv4', 'network_type_ipv6'], ).get() with self.assertRaises(DatasetError): server_q = Query( - {"network_type_ipv6": "public_ipv4", "servertype": "host"}, - ["hostname", "network_type_ipv4", "network_type_ipv6"], + {'network_type_ipv6': 'public_ipv4', 'servertype': 'host'}, + ['hostname', 'network_type_ipv4', 'network_type_ipv6'], ).get() + class TestIpAddrTypeContainment(TestIpAddrType): def setUp(self): super().setUp() - self.network_1 = self._get_server("provider_network") - self.network_1["intern_ip"] = "2001:db8::/64" - self.network_1["ip_config_ipv6"] = "2001:db8::/64" + self.network_1 = self._get_server('provider_network') + self.network_1['intern_ip'] = '2001:db8::/64' + self.network_1['ip_config_ipv6'] = '2001:db8::/64' self.network_1.commit(user=User.objects.first()) - self.network_2 = self._get_server("route_network") - self.network_2["intern_ip"] = "2001:db8::0010/124" - self.network_2["ip_config_ipv6"] = "2001:db8::0010/124" + self.network_2 = self._get_server('route_network') + self.network_2['intern_ip'] = '2001:db8::0010/124' + self.network_2['ip_config_ipv6'] = '2001:db8::0010/124' self.network_2.commit(user=User.objects.first()) - self.server_1 = self._get_server("host") - self.server_1["intern_ip"] = "2001:db8::0011" - self.server_1["ip_config_ipv6"] = "2001:db8::0011" + self.server_1 = self._get_server('host') + self.server_1['intern_ip'] = '2001:db8::0011' + self.server_1['ip_config_ipv6'] = '2001:db8::0011' self.server_1.commit(user=User.objects.first()) - self.server_2 = self._get_server("host") - self.server_2["intern_ip"] = "2001:db8::0021" - self.server_2["ip_config_ipv6"] = "2001:db8::0021" + self.server_2 = self._get_server('host') + self.server_2['intern_ip'] = '2001:db8::0021' + self.server_2['ip_config_ipv6'] = '2001:db8::0021' self.server_2.commit(user=User.objects.first()) # I honestly don't understand what inet.startswith() is supposed to do") - #def test_startswith(self): + # def test_startswith(self): # pass def test_contains(self): - network_q = list(Query( - {"ip_config_ipv6": filters.Contains("2001:db8::0021")}, - ["hostname", "servertype", "ip_config_ipv6"], - ["ip_config_ipv6"], - )) + network_q = list( + Query( + {'ip_config_ipv6': filters.Contains('2001:db8::0021')}, + ['hostname', 'servertype', 'ip_config_ipv6'], + ['ip_config_ipv6'], + ) + ) self.assertEqual(len(network_q), 2) - self.assertEqual(network_q[0]["hostname"], self.network_1["hostname"]) - self.assertEqual(network_q[1]["hostname"], self.server_2["hostname"]) + self.assertEqual(network_q[0]['hostname'], self.network_1['hostname']) + self.assertEqual(network_q[1]['hostname'], self.server_2['hostname']) def test_containedby(self): - network_q = list(Query( - {"ip_config_ipv6": filters.ContainedBy("2001:db8::0000/120")}, - ["hostname", "servertype", "ip_config_ipv6"], - ["ip_config_ipv6"], - )) + network_q = list( + Query( + {'ip_config_ipv6': filters.ContainedBy('2001:db8::0000/120')}, + ['hostname', 'servertype', 'ip_config_ipv6'], + ['ip_config_ipv6'], + ) + ) self.assertEqual(len(network_q), 3) - self.assertEqual(network_q[0]["hostname"], self.network_2["hostname"]) - self.assertEqual(network_q[1]["hostname"], self.server_1["hostname"]) - self.assertEqual(network_q[2]["hostname"], self.server_2["hostname"]) + self.assertEqual(network_q[0]['hostname'], self.network_2['hostname']) + self.assertEqual(network_q[1]['hostname'], self.server_1['hostname']) + self.assertEqual(network_q[2]['hostname'], self.server_2['hostname']) def test_containedonlyby(self): # ContainedOnlyBy means find objects contained by given prefix # apart from the ones contained by another object. - network_q = list(Query( - {"ip_config_ipv6": filters.ContainedOnlyBy("2001:db8::0000/120")}, - ["hostname", "servertype", "ip_config_ipv6"], - ["ip_config_ipv6"], - )) + network_q = list( + Query( + {'ip_config_ipv6': filters.ContainedOnlyBy('2001:db8::0000/120')}, + ['hostname', 'servertype', 'ip_config_ipv6'], + ['ip_config_ipv6'], + ) + ) self.assertEqual(len(network_q), 2) - self.assertEqual(network_q[0]["hostname"], self.network_2["hostname"]) - self.assertEqual(network_q[1]["hostname"], self.server_2["hostname"]) \ No newline at end of file + self.assertEqual(network_q[0]['hostname'], self.network_2['hostname']) + self.assertEqual(network_q[1]['hostname'], self.server_2['hostname'])