From 69f14cf420f32a008d79e08d30d0d20f3778a676 Mon Sep 17 00:00:00 2001 From: Vegard Vesterheim Date: Fri, 8 Jan 2021 15:17:52 +0100 Subject: [PATCH 1/9] unfinished script for syncing rooms --- bin/nettinst2room | 135 ++++++++++++++++++++++++++++++++++++++++++ kindnavsync/navapi.py | 4 ++ 2 files changed, 139 insertions(+) create mode 100755 bin/nettinst2room diff --git a/bin/nettinst2room b/bin/nettinst2room new file mode 100755 index 0000000..bcd2341 --- /dev/null +++ b/bin/nettinst2room @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Synkronisering av KIND/nettinstallasjon -> NAV/room +""" +import requests +import argparse +import logging +import sys +import os + +import collections.abc + +# FIXME: why do I need this +sys.path.append(os.path.abspath(os.path.join(os.path.dirname("__file__"), '..'))) + +from kindnavsync.errors import retry_on_timeout +from kindnavsync.navapi import NAVAPI, ObjectNotFound, ClientError + +# FIXME +# NAV_API_URL = "https://uninavn.uninett.no/api/1" +NAV_API_URL = "http://localhost/api/1" + +NAV_API_TIMEOUT = 10.0 + +# FIXME +KIND_SERVICE_URL = 'http://localhost:7080/api/nettinstallasjoner.json?navn=oslo' + +DEFAULT_ORGANIZATION = "uninett" +DEFAULT_LOCATION = "norge" + +LOG = logging.getLogger("nettinst2room") + +def main(): + args = parse_args() + nettinst = get_kind_data() + api_url=args.api_url + api_token=args.api_token + + nav_api = NAVAPI(url=api_url, auth_token=api_token, timeout=NAV_API_TIMEOUT) + LOG.setLevel(logging.DEBUG if args.debug else logging.INFO) + LOG.warning("Starting up:") + for ni in nettinst: + try: + room_response = nav_api.get_room(ni['navn']) + room = room_response.body + LOG.warning("Fant rom: %s", room) + except ObjectNotFound: + + ## { + ## "id": "vvwashere", + ## "position": [ + ## "59.913054035463", + ## "10.720285183010" + ## ], + ## "description": "Observatoriegata 1b, 0254 Oslo", + ## "data": { + ## "tlf": "23118900", + ## "site_owner": "Norsk kulturråd", + ## "site_owner_url": "https://kind.uninett.no/263" + ## }, + ## "location": "norge" + ## } + + LOG.warning ("Creating rom for: %s", ni['navn']) + room = dict(id=ni['navn'], location=DEFAULT_LOCATION) + nav_api.post_room(room) + + + except Exception as e: + LOG.warning ("Error: ", e) + # Update room attributes + patch = update (room, { + 'location': DEFAULT_LOCATION, + 'position': [str(round(ni['lat'], 12)), str(round(ni['lon'], 12))], + + # FIXME, add more into description + # description = ni['termineringsadresse']+"\n"+ni['rombeskrivelse'], + 'description': ni['termineringsadresse'], + 'data': { + 'site_owner': ni['org'], + 'site_owner_url': 'https://kind.uninett.no/'+ str(int(ni['org_id'])) + } + }) + nav_api.patch_room(room_id=ni['navn'], patch=patch) + +# https://stackoverflow.com/questions/3232943/update-value-of-a-nested-dictionary-of-varying-depth +def update(d, u): + patch = {} + for k, v in u.items(): + if isinstance(v, collections.abc.Mapping): + d[k] = update(d.get(k, {}), v) + else: + if d[k] != v: + LOG.warning("Updating %s from %s to %s", k, d[k], v) + d[k] = v + return d + + +def get_kind_data(): + LOG.warning("Henter data fra %s", KIND_SERVICE_URL) + return requests.get(KIND_SERVICE_URL).json() + +def parse_args(): + parser = argparse.ArgumentParser( + description="Synchronizes rooms in NAV with those from Kind" + ) + parser.add_argument( + "--api-url", + "-a", + default=os.environ.get("NAV_API_URL", NAV_API_URL), + help="URL to the NAV API. Default={}".format(NAV_API_URL), + ) + parser.add_argument( + "--api-token", + "-t", + default=os.environ.get("NAV_API_TOKEN"), + help="NAV API Token", + ) + parser.add_argument( + "--debug", "-d", action="store_true", help="enable debug logging" + ) + args = parser.parse_args() + + if not args.api_token: + parser.error( + "You must supply a NAV API token using either the " + "NAV_API_TOKEN environment variable, or the --api-token " + "option" + ) + + return args + +if __name__ == "__main__": + main() diff --git a/kindnavsync/navapi.py b/kindnavsync/navapi.py index 5609949..43e36f7 100644 --- a/kindnavsync/navapi.py +++ b/kindnavsync/navapi.py @@ -80,6 +80,10 @@ class NAVAPI(object): def post_room(self, room): return self.api.room.create(body=room) + @_translate_exceptions + def patch_room(self, room_id, patch): + return self.api.room.partial_update(room_id, body=patch) + @functools.lru_cache(1) @_translate_exceptions def get_version(self): -- GitLab From 9d10447ea9c815bedba79b471107f617e62f613b Mon Sep 17 00:00:00 2001 From: Vegard Vesterheim Date: Wed, 13 Jan 2021 16:53:31 +0100 Subject: [PATCH 2/9] For the most part, working --- bin/nettinst2room | 73 +++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/bin/nettinst2room b/bin/nettinst2room index bcd2341..e8fedc6 100755 --- a/bin/nettinst2room +++ b/bin/nettinst2room @@ -8,8 +8,9 @@ import argparse import logging import sys import os - +from deepdiff import DeepDiff import collections.abc +import copy # FIXME: why do I need this sys.path.append(os.path.abspath(os.path.join(os.path.dirname("__file__"), '..'))) @@ -24,7 +25,8 @@ NAV_API_URL = "http://localhost/api/1" NAV_API_TIMEOUT = 10.0 # FIXME -KIND_SERVICE_URL = 'http://localhost:7080/api/nettinstallasjoner.json?navn=oslo' +#KIND_SERVICE_URL = 'http://localhost:7080/api/nettinstallasjoner.json?navn=tromso' +KIND_SERVICE_URL = 'http://localhost:7080/api/nettinstallasjoner.json' DEFAULT_ORGANIZATION = "uninett" DEFAULT_LOCATION = "norge" @@ -39,12 +41,12 @@ def main(): nav_api = NAVAPI(url=api_url, auth_token=api_token, timeout=NAV_API_TIMEOUT) LOG.setLevel(logging.DEBUG if args.debug else logging.INFO) - LOG.warning("Starting up:") + LOG.addHandler(logging.StreamHandler()) for ni in nettinst: try: room_response = nav_api.get_room(ni['navn']) room = room_response.body - LOG.warning("Fant rom: %s", room) + LOG.debug("Fant rom: %s", room) except ObjectNotFound: ## { @@ -62,43 +64,66 @@ def main(): ## "location": "norge" ## } - LOG.warning ("Creating rom for: %s", ni['navn']) + LOG.debug ("Creating rom for: %s", ni['navn']) room = dict(id=ni['navn'], location=DEFAULT_LOCATION) - nav_api.post_room(room) + try: + LOG.debug("Creating room: %s", ni['navn']) + nav_api.post_room(room) + except Exception as e: + LOG.debug ("Error in creating room for %s: ", ni['navn']) + continue except Exception as e: - LOG.warning ("Error: ", e) + LOG.debug ("Error: ", e) # Update room attributes - patch = update (room, { - 'location': DEFAULT_LOCATION, - 'position': [str(round(ni['lat'], 12)), str(round(ni['lon'], 12))], - - # FIXME, add more into description - # description = ni['termineringsadresse']+"\n"+ni['rombeskrivelse'], - 'description': ni['termineringsadresse'], - 'data': { + patch = copy.deepcopy(room) + org = {} + org['location'] = DEFAULT_LOCATION + # FIXME, add more into description + desc_fields = ['beskrivelse','termineringsadresse'] + description = '. '.join([ni[p] for p in desc_fields if p in ni and ni[p]]) + if not description: + description = 'No description found' + org['description'] = description + if 'org' in ni: + org['data'] = { 'site_owner': ni['org'], 'site_owner_url': 'https://kind.uninett.no/'+ str(int(ni['org_id'])) } - }) - nav_api.patch_room(room_id=ni['navn'], patch=patch) + if 'lat' in ni and 'lon' in ni: + org['position'] = [ + '%.12f' % round(ni['lat'], 12), + '%.12f' % round(ni['lon'], 12) + ] + + merge_dict (patch, org) + if DeepDiff (patch, room, ignore_order=True): + LOG.debug ("Update needed") + LOG.debug (patch) + nav_api.patch_room(room_id=ni['navn'], patch=patch) + else: + LOG.debug ("No update needed for room: %s", ni['navn']) # https://stackoverflow.com/questions/3232943/update-value-of-a-nested-dictionary-of-varying-depth -def update(d, u): - patch = {} - for k, v in u.items(): +def merge_dict(d, updates): + """Merge entries from updates into d""" + for k, v in updates.items(): if isinstance(v, collections.abc.Mapping): - d[k] = update(d.get(k, {}), v) + d[k] = merge_dict(d.get(k, {}), v) else: - if d[k] != v: - LOG.warning("Updating %s from %s to %s", k, d[k], v) + if (not k in d): + LOG.debug("Setting %s to %s", k, v) + d[k] = v + elif d[k] != v: + LOG.debug("Updating %s from %s to %s", k, d[k], v) d[k] = v return d + def get_kind_data(): - LOG.warning("Henter data fra %s", KIND_SERVICE_URL) + LOG.debug("Henter data fra %s", KIND_SERVICE_URL) return requests.get(KIND_SERVICE_URL).json() def parse_args(): -- GitLab From 5ca2a4ad599cece1d3fda871ccb54b206fc46ebd Mon Sep 17 00:00:00 2001 From: Vegard Vesterheim Date: Thu, 14 Jan 2021 21:31:25 +0100 Subject: [PATCH 3/9] misc fixups, add --room CLI argument --- bin/nettinst2room | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/bin/nettinst2room b/bin/nettinst2room index e8fedc6..a3bb218 100755 --- a/bin/nettinst2room +++ b/bin/nettinst2room @@ -11,6 +11,7 @@ import os from deepdiff import DeepDiff import collections.abc import copy +import urllib.parse # FIXME: why do I need this sys.path.append(os.path.abspath(os.path.join(os.path.dirname("__file__"), '..'))) @@ -19,14 +20,14 @@ from kindnavsync.errors import retry_on_timeout from kindnavsync.navapi import NAVAPI, ObjectNotFound, ClientError # FIXME -# NAV_API_URL = "https://uninavn.uninett.no/api/1" -NAV_API_URL = "http://localhost/api/1" +# NAV_API_URL = "http://localhost/api/1" +NAV_API_URL = "https://uninavn.uninett.no/api/1" NAV_API_TIMEOUT = 10.0 # FIXME -#KIND_SERVICE_URL = 'http://localhost:7080/api/nettinstallasjoner.json?navn=tromso' -KIND_SERVICE_URL = 'http://localhost:7080/api/nettinstallasjoner.json' +# KIND_SERVICE_URL = 'http://localhost:7080/api/nettinstallasjoner.json' +KIND_SERVICE_URL = 'https://kind.uninett.no/api/nettinstallasjoner.json' DEFAULT_ORGANIZATION = "uninett" DEFAULT_LOCATION = "norge" @@ -35,7 +36,8 @@ LOG = logging.getLogger("nettinst2room") def main(): args = parse_args() - nettinst = get_kind_data() + room = args.room + nettinst = get_kind_data(args.room) api_url=args.api_url api_token=args.api_token @@ -64,23 +66,28 @@ def main(): ## "location": "norge" ## } - LOG.debug ("Creating rom for: %s", ni['navn']) + LOG.debug ("Creating room for: %s", ni['navn']) room = dict(id=ni['navn'], location=DEFAULT_LOCATION) try: - LOG.debug("Creating room: %s", ni['navn']) nav_api.post_room(room) except Exception as e: - LOG.debug ("Error in creating room for %s: ", ni['navn']) + LOG.error ("Error in creating room for %s: ", ni['navn']) + LOG.error ("Error is : %s", e) continue except Exception as e: - LOG.debug ("Error: ", e) - # Update room attributes + LOG.error ("Error in fetching room for %s: ", ni['navn']) + LOG.error ("Error: %s", e) + continue + + # Creating a deep copy can make the patch bigger than needed... patch = copy.deepcopy(room) + org = {} + # Update room attributes org['location'] = DEFAULT_LOCATION - # FIXME, add more into description + # FIXME, maybe add more into description? desc_fields = ['beskrivelse','termineringsadresse'] description = '. '.join([ni[p] for p in desc_fields if p in ni and ni[p]]) if not description: @@ -96,7 +103,7 @@ def main(): '%.12f' % round(ni['lat'], 12), '%.12f' % round(ni['lon'], 12) ] - + # Merge data from KIND into existing entry merge_dict (patch, org) if DeepDiff (patch, room, ignore_order=True): LOG.debug ("Update needed") @@ -120,16 +127,23 @@ def merge_dict(d, updates): d[k] = v return d +def get_kind_data(room): + url = KIND_SERVICE_URL + if room: + url = KIND_SERVICE_URL+'?navn='+urllib.parse.quote(room) + LOG.debug("Fetching data from: %s", url) + return requests.get(url).json() -def get_kind_data(): - LOG.debug("Henter data fra %s", KIND_SERVICE_URL) - return requests.get(KIND_SERVICE_URL).json() - def parse_args(): parser = argparse.ArgumentParser( description="Synchronizes rooms in NAV with those from Kind" ) + parser.add_argument( + "--room", + "-r", + help="Name of single room to sync. (All rooms otherwise)", + ) parser.add_argument( "--api-url", "-a", @@ -156,5 +170,6 @@ def parse_args(): return args + if __name__ == "__main__": main() -- GitLab From d7d0ab43860409c02a7cf2c9eddc04a87fb49d7e Mon Sep 17 00:00:00 2001 From: Vegard Vesterheim Date: Fri, 15 Jan 2021 11:27:58 +0100 Subject: [PATCH 4/9] Flake8 cleanups --- bin/nettinst2room | 57 ++++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/bin/nettinst2room b/bin/nettinst2room index a3bb218..3f03a49 100755 --- a/bin/nettinst2room +++ b/bin/nettinst2room @@ -15,9 +15,7 @@ import urllib.parse # FIXME: why do I need this sys.path.append(os.path.abspath(os.path.join(os.path.dirname("__file__"), '..'))) - -from kindnavsync.errors import retry_on_timeout -from kindnavsync.navapi import NAVAPI, ObjectNotFound, ClientError +from kindnavsync.navapi import NAVAPI, ObjectNotFound # FIXME # NAV_API_URL = "http://localhost/api/1" @@ -34,14 +32,16 @@ DEFAULT_LOCATION = "norge" LOG = logging.getLogger("nettinst2room") + def main(): args = parse_args() room = args.room nettinst = get_kind_data(args.room) - api_url=args.api_url - api_token=args.api_token + api_url = args.api_url + api_token = args.api_token - nav_api = NAVAPI(url=api_url, auth_token=api_token, timeout=NAV_API_TIMEOUT) + nav_api = NAVAPI(url=api_url, auth_token=api_token, + timeout=NAV_API_TIMEOUT) LOG.setLevel(logging.DEBUG if args.debug else logging.INFO) LOG.addHandler(logging.StreamHandler()) for ni in nettinst: @@ -51,34 +51,18 @@ def main(): LOG.debug("Fant rom: %s", room) except ObjectNotFound: - ## { - ## "id": "vvwashere", - ## "position": [ - ## "59.913054035463", - ## "10.720285183010" - ## ], - ## "description": "Observatoriegata 1b, 0254 Oslo", - ## "data": { - ## "tlf": "23118900", - ## "site_owner": "Norsk kulturråd", - ## "site_owner_url": "https://kind.uninett.no/263" - ## }, - ## "location": "norge" - ## } - - LOG.debug ("Creating room for: %s", ni['navn']) + LOG.debug("Creating room for: %s", ni['navn']) room = dict(id=ni['navn'], location=DEFAULT_LOCATION) try: nav_api.post_room(room) except Exception as e: - LOG.error ("Error in creating room for %s: ", ni['navn']) - LOG.error ("Error is : %s", e) + LOG.error("Error in creating room for %s: ", ni['navn']) + LOG.error("Error is : %s", e) continue - except Exception as e: - LOG.error ("Error in fetching room for %s: ", ni['navn']) - LOG.error ("Error: %s", e) + LOG.error("Error in fetching room for %s: ", ni['navn']) + LOG.error("Error: %s", e) continue # Creating a deep copy can make the patch bigger than needed... @@ -88,7 +72,7 @@ def main(): # Update room attributes org['location'] = DEFAULT_LOCATION # FIXME, maybe add more into description? - desc_fields = ['beskrivelse','termineringsadresse'] + desc_fields = ['beskrivelse', 'termineringsadresse'] description = '. '.join([ni[p] for p in desc_fields if p in ni and ni[p]]) if not description: description = 'No description found' @@ -96,7 +80,8 @@ def main(): if 'org' in ni: org['data'] = { 'site_owner': ni['org'], - 'site_owner_url': 'https://kind.uninett.no/'+ str(int(ni['org_id'])) + 'site_owner_url': 'https://kind.uninett.no/' + + str(int(ni['org_id'])) } if 'lat' in ni and 'lon' in ni: org['position'] = [ @@ -104,13 +89,14 @@ def main(): '%.12f' % round(ni['lon'], 12) ] # Merge data from KIND into existing entry - merge_dict (patch, org) - if DeepDiff (patch, room, ignore_order=True): - LOG.debug ("Update needed") - LOG.debug (patch) + merge_dict(patch, org) + if DeepDiff(patch, room, ignore_order=True): + LOG.debug("Update needed") + LOG.debug(patch) nav_api.patch_room(room_id=ni['navn'], patch=patch) else: - LOG.debug ("No update needed for room: %s", ni['navn']) + LOG.debug("No update needed for room: %s", ni['navn']) + # https://stackoverflow.com/questions/3232943/update-value-of-a-nested-dictionary-of-varying-depth def merge_dict(d, updates): @@ -119,7 +105,7 @@ def merge_dict(d, updates): if isinstance(v, collections.abc.Mapping): d[k] = merge_dict(d.get(k, {}), v) else: - if (not k in d): + if (k not in d): LOG.debug("Setting %s to %s", k, v) d[k] = v elif d[k] != v: @@ -127,6 +113,7 @@ def merge_dict(d, updates): d[k] = v return d + def get_kind_data(room): url = KIND_SERVICE_URL if room: -- GitLab From 4a14b9bf5e3f67059c8ee1a05d8fa0697eb8c22b Mon Sep 17 00:00:00 2001 From: Vegard Vesterheim Date: Fri, 15 Jan 2021 12:06:20 +0100 Subject: [PATCH 5/9] Run black formatting --- bin/nettinst2room | 58 ++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/bin/nettinst2room b/bin/nettinst2room index 3f03a49..0f47c8a 100755 --- a/bin/nettinst2room +++ b/bin/nettinst2room @@ -14,7 +14,9 @@ import copy import urllib.parse # FIXME: why do I need this -sys.path.append(os.path.abspath(os.path.join(os.path.dirname("__file__"), '..'))) +sys.path.append( + os.path.abspath(os.path.join(os.path.dirname("__file__"), "..")) +) from kindnavsync.navapi import NAVAPI, ObjectNotFound # FIXME @@ -25,7 +27,7 @@ NAV_API_TIMEOUT = 10.0 # FIXME # KIND_SERVICE_URL = 'http://localhost:7080/api/nettinstallasjoner.json' -KIND_SERVICE_URL = 'https://kind.uninett.no/api/nettinstallasjoner.json' +KIND_SERVICE_URL = "https://kind.uninett.no/api/nettinstallasjoner.json" DEFAULT_ORGANIZATION = "uninett" DEFAULT_LOCATION = "norge" @@ -40,28 +42,27 @@ def main(): api_url = args.api_url api_token = args.api_token - nav_api = NAVAPI(url=api_url, auth_token=api_token, - timeout=NAV_API_TIMEOUT) + nav_api = NAVAPI(url=api_url, auth_token=api_token, timeout=NAV_API_TIMEOUT) LOG.setLevel(logging.DEBUG if args.debug else logging.INFO) LOG.addHandler(logging.StreamHandler()) for ni in nettinst: try: - room_response = nav_api.get_room(ni['navn']) + room_response = nav_api.get_room(ni["navn"]) room = room_response.body LOG.debug("Fant rom: %s", room) except ObjectNotFound: - LOG.debug("Creating room for: %s", ni['navn']) - room = dict(id=ni['navn'], location=DEFAULT_LOCATION) + LOG.debug("Creating room for: %s", ni["navn"]) + room = dict(id=ni["navn"], location=DEFAULT_LOCATION) try: nav_api.post_room(room) except Exception as e: - LOG.error("Error in creating room for %s: ", ni['navn']) + LOG.error("Error in creating room for %s: ", ni["navn"]) LOG.error("Error is : %s", e) continue except Exception as e: - LOG.error("Error in fetching room for %s: ", ni['navn']) + LOG.error("Error in fetching room for %s: ", ni["navn"]) LOG.error("Error: %s", e) continue @@ -70,32 +71,34 @@ def main(): org = {} # Update room attributes - org['location'] = DEFAULT_LOCATION + org["location"] = DEFAULT_LOCATION # FIXME, maybe add more into description? - desc_fields = ['beskrivelse', 'termineringsadresse'] - description = '. '.join([ni[p] for p in desc_fields if p in ni and ni[p]]) + desc_fields = ["beskrivelse", "termineringsadresse"] + description = ". ".join( + [ni[p] for p in desc_fields if p in ni and ni[p]] + ) if not description: - description = 'No description found' - org['description'] = description - if 'org' in ni: - org['data'] = { - 'site_owner': ni['org'], - 'site_owner_url': 'https://kind.uninett.no/' + - str(int(ni['org_id'])) + description = "No description found" + org["description"] = description + if "org" in ni: + org["data"] = { + "site_owner": ni["org"], + "site_owner_url": "https://kind.uninett.no/" + + str(int(ni["org_id"])), } - if 'lat' in ni and 'lon' in ni: - org['position'] = [ - '%.12f' % round(ni['lat'], 12), - '%.12f' % round(ni['lon'], 12) + if "lat" in ni and "lon" in ni: + org["position"] = [ + "%.12f" % round(ni["lat"], 12), + "%.12f" % round(ni["lon"], 12), ] # Merge data from KIND into existing entry merge_dict(patch, org) if DeepDiff(patch, room, ignore_order=True): LOG.debug("Update needed") LOG.debug(patch) - nav_api.patch_room(room_id=ni['navn'], patch=patch) + nav_api.patch_room(room_id=ni["navn"], patch=patch) else: - LOG.debug("No update needed for room: %s", ni['navn']) + LOG.debug("No update needed for room: %s", ni["navn"]) # https://stackoverflow.com/questions/3232943/update-value-of-a-nested-dictionary-of-varying-depth @@ -105,7 +108,7 @@ def merge_dict(d, updates): if isinstance(v, collections.abc.Mapping): d[k] = merge_dict(d.get(k, {}), v) else: - if (k not in d): + if k not in d: LOG.debug("Setting %s to %s", k, v) d[k] = v elif d[k] != v: @@ -117,7 +120,7 @@ def merge_dict(d, updates): def get_kind_data(room): url = KIND_SERVICE_URL if room: - url = KIND_SERVICE_URL+'?navn='+urllib.parse.quote(room) + url = KIND_SERVICE_URL + "?navn=" + urllib.parse.quote(room) LOG.debug("Fetching data from: %s", url) return requests.get(url).json() @@ -154,7 +157,6 @@ def parse_args(): "NAV_API_TOKEN environment variable, or the --api-token " "option" ) - return args -- GitLab From 454d804437c24b09f0d33386f8679707649c4f93 Mon Sep 17 00:00:00 2001 From: Vegard Vesterheim Date: Mon, 22 Feb 2021 13:36:41 +0100 Subject: [PATCH 6/9] Added doc of nettinst2room Also: Markdown -> Org formatting --- README.md | 50 -------------------------------------- README.org | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 50 deletions(-) delete mode 100644 README.md create mode 100644 README.org diff --git a/README.md b/README.md deleted file mode 100644 index d2d2285..0000000 --- a/README.md +++ /dev/null @@ -1,50 +0,0 @@ -Synchronization of equipment from Kind to NAV -============================================= - - usage: kindnavsync [-h] [--dry-run] [--kind-only] [--debug] - [--api-url API_URL] [--api-token API_TOKEN] - [--no-timestamps] - - Synchronizes devices in NAV with those from Kind - - optional arguments: - -h, --help show this help message and exit - --dry-run, -n don't change anything in NAV, just print what would - have been done - --kind-only only check contents of Kind, do not talk to NAV - --debug, -d enable debug logging - --api-url API_URL, -a API_URL - URL to the NAV API. Default=http://localhost/api/1 - --api-token API_TOKEN, -t API_TOKEN - NAV API Token - --no-timestamps Don't add timestamps to log output - - Since Kind only stores names of devices, while NAV requires specific IP - addresses, up-to-date DNS entries are required. If the environment variable - SLACK_URL is set, this program will post log messages to Slack using this as a - webhook URL. - - -Supported environment variables -------------------------------- - -- `NAV_API_URL`: URL to NAV API -- `NAV_API_TOKEN`: NAV API token, providing at least read/write access for the - `/netbox` and `/room` endpoints. -- `SLACK_URL`: If set, log output will be posted to this slack webhook URL. See - for details. - -Notes ------ - -- This program will not touch NAV devices owned by the organizational units -`urc` or `privat`. -- All devices will be set as owned by the organizational unit `uninett`. -- _"Nettinstallasjon"_ will be used as the device room in NAV. -- Any new room that this program creates in NAV will have its location set to - `norge`. - -Bugs ----- - -- Doesn't update IP addresses in NAV if DNS changes. diff --git a/README.org b/README.org new file mode 100644 index 0000000..a7f7b14 --- /dev/null +++ b/README.org @@ -0,0 +1,71 @@ +* Synchronization of data from Kind to NAV + :PROPERTIES: + :CUSTOM_ID: synchronization-of-equipment-from-kind-to-nav + :END: + +** Synchronization of equipment from Kind to NAV + +#+BEGIN_EXAMPLE + usage: kindnavsync [-h] [--dry-run] [--kind-only] [--debug] + [--api-url API_URL] [--api-token API_TOKEN] + [--no-timestamps] + + Synchronizes devices in NAV with those from Kind + + optional arguments: + -h, --help show this help message and exit + --dry-run, -n don't change anything in NAV, just print what would + have been done + --kind-only only check contents of Kind, do not talk to NAV + --debug, -d enable debug logging + --api-url API_URL, -a API_URL + URL to the NAV API. Default=http://localhost/api/1 + --api-token API_TOKEN, -t API_TOKEN + NAV API Token + --no-timestamps Don't add timestamps to log output + + Since Kind only stores names of devices, while NAV requires specific IP + addresses, up-to-date DNS entries are required. If the environment variable + SLACK_URL is set, this program will post log messages to Slack using this as a + webhook URL. +#+END_EXAMPLE + +** Supported environment variables + :PROPERTIES: + :CUSTOM_ID: supported-environment-variables + :END: + +- =NAV_API_URL=: URL to NAV API +- =NAV_API_TOKEN=: NAV API token, providing at least read/write access + for the =/netbox= and =/room= endpoints. +- =SLACK_URL=: If set, log output will be posted to this slack webhook + URL. See [[https://api.slack.com/incoming-webhooks]] for details. + +** Notes + :PROPERTIES: + :CUSTOM_ID: notes + :END: + +- This program will not touch NAV devices owned by the organizational + units =urc= or =privat=. +- All devices will be set as owned by the organizational unit =uninett=. +- /"Nettinstallasjon"/ will be used as the device room in NAV. +- Any new room that this program creates in NAV will have its location + set to =norge=. + +** Bugs + :PROPERTIES: + :CUSTOM_ID: bugs + :END: + +- Doesn't update IP addresses in NAV if DNS changes. + +** Synchronization of rooms from KIND to NAV + + usage: nettinst2room [--debug] + [--api-url API_URL] [--api-token API_TOKEN] + [--room ] + +Syncs room data from KIND to NAV. Takes an optional argument ~--room~ +if only a specific room is to be synced. Default operation is to sync +all rooms returned by the API at https://kind.uninett.no/api/nettinstallasjoner.json -- GitLab From cdc29e91d0d8f97da4bc8e05ac781af3095d942d Mon Sep 17 00:00:00 2001 From: Vegard Vesterheim Date: Mon, 22 Feb 2021 13:38:47 +0100 Subject: [PATCH 7/9] Added missing formatting in README --- README.org | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index a7f7b14..9b0df93 100644 --- a/README.org +++ b/README.org @@ -62,10 +62,13 @@ ** Synchronization of rooms from KIND to NAV - usage: nettinst2room [--debug] +#+BEGIN_EXAMPLE + usage: nettinst2room [--debug] [--api-url API_URL] [--api-token API_TOKEN] [--room ] +#+END_EXAMPLE + Syncs room data from KIND to NAV. Takes an optional argument ~--room~ if only a specific room is to be synced. Default operation is to sync all rooms returned by the API at https://kind.uninett.no/api/nettinstallasjoner.json -- GitLab From c0623f2c99335fd68128783ac9ffadc2e19bff5f Mon Sep 17 00:00:00 2001 From: Vegard Vesterheim Date: Wed, 3 Mar 2021 13:01:05 +0100 Subject: [PATCH 8/9] Apparently NAV does rstrip internally upon saving --- bin/nettinst2room | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/nettinst2room b/bin/nettinst2room index 0f47c8a..f9d8cc4 100755 --- a/bin/nettinst2room +++ b/bin/nettinst2room @@ -75,7 +75,7 @@ def main(): # FIXME, maybe add more into description? desc_fields = ["beskrivelse", "termineringsadresse"] description = ". ".join( - [ni[p] for p in desc_fields if p in ni and ni[p]] + [ni[p].rstrip() for p in desc_fields if p in ni and ni[p]] ) if not description: description = "No description found" -- GitLab From 8f4a9cb1017827808b21b716bf569a7bdbaf976e Mon Sep 17 00:00:00 2001 From: Vegard Vesterheim Date: Wed, 3 Mar 2021 13:09:36 +0100 Subject: [PATCH 9/9] Updated according to comments in MR !2 --- bin/nettinst2room | 17 +++-------------- requirements.txt | 1 + setup.py | 1 + 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/bin/nettinst2room b/bin/nettinst2room index f9d8cc4..84f2917 100755 --- a/bin/nettinst2room +++ b/bin/nettinst2room @@ -13,20 +13,12 @@ import collections.abc import copy import urllib.parse -# FIXME: why do I need this -sys.path.append( - os.path.abspath(os.path.join(os.path.dirname("__file__"), "..")) -) from kindnavsync.navapi import NAVAPI, ObjectNotFound -# FIXME -# NAV_API_URL = "http://localhost/api/1" -NAV_API_URL = "https://uninavn.uninett.no/api/1" +NAV_API_URL = "https://uninav.uninett.no/api/1" NAV_API_TIMEOUT = 10.0 -# FIXME -# KIND_SERVICE_URL = 'http://localhost:7080/api/nettinstallasjoner.json' KIND_SERVICE_URL = "https://kind.uninett.no/api/nettinstallasjoner.json" DEFAULT_ORGANIZATION = "uninett" @@ -118,11 +110,8 @@ def merge_dict(d, updates): def get_kind_data(room): - url = KIND_SERVICE_URL - if room: - url = KIND_SERVICE_URL + "?navn=" + urllib.parse.quote(room) - LOG.debug("Fetching data from: %s", url) - return requests.get(url).json() + LOG.debug("Fetching data from: %s", KIND_SERVICE_URL) + return requests.get(KIND_SERVICE_URL, params={'navn': room}).json() def parse_args(): diff --git a/requirements.txt b/requirements.txt index f82416c..4375fe4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ requests==2.22.0 simple_rest_client==0.5.4 slack-log-handler==0.3.0 +deepdiff diff --git a/setup.py b/setup.py index 9db5b6e..ed6754a 100644 --- a/setup.py +++ b/setup.py @@ -16,6 +16,7 @@ setup( 'requests', 'simple_rest_client', 'slack_log_handler', + 'deepdiff', ], python_requires='>3.4.0', classifiers=[ -- GitLab