From 1c429074def533b832ede62fdb138b1201163439 Mon Sep 17 00:00:00 2001
From: John Estabrook <jestabro@vyos.io>
Date: Fri, 14 Oct 2022 09:11:07 -0500
Subject: http-api: T4749: transition to config_dict

---
 python/vyos/defaults.py           |  2 --
 src/conf_mode/http-api.py         | 63 ++++++++++++++++++++-------------------
 src/services/vyos-http-api-server | 12 ++++++--
 3 files changed, 42 insertions(+), 35 deletions(-)

diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py
index 6894fc4da..7de458960 100644
--- a/python/vyos/defaults.py
+++ b/python/vyos/defaults.py
@@ -49,8 +49,6 @@ api_data = {
     'port' : '8080',
     'socket' : False,
     'strict' : False,
-    'gql' : False,
-    'introspection' : False,
     'debug' : False,
     'api_keys' : [ {"id": "testapp", "key": "qwerty"} ]
 }
diff --git a/src/conf_mode/http-api.py b/src/conf_mode/http-api.py
index 04113fc09..c196e272b 100755
--- a/src/conf_mode/http-api.py
+++ b/src/conf_mode/http-api.py
@@ -24,9 +24,11 @@ from copy import deepcopy
 import vyos.defaults
 
 from vyos.config import Config
+from vyos.configdict import dict_merge
 from vyos.template import render
 from vyos.util import cmd
 from vyos.util import call
+from vyos.xml import defaults
 from vyos import ConfigError
 from vyos import airbag
 airbag.enable()
@@ -36,6 +38,15 @@ systemd_service = '/run/systemd/system/vyos-http-api.service'
 
 vyos_conf_scripts_dir=vyos.defaults.directories['conf_mode']
 
+def _translate_values_to_boolean(d: dict) -> dict:
+    for k in list(d):
+        if d[k] == {}:
+            d[k] = True
+        elif isinstance(d[k], dict):
+            _translate_values_to_boolean(d[k])
+        else:
+            pass
+
 def get_config(config=None):
     http_api = deepcopy(vyos.defaults.api_data)
     x = http_api.get('api_keys')
@@ -54,48 +65,40 @@ def get_config(config=None):
     if not conf.exists(base):
         return None
 
+    api_dict = conf.get_config_dict(base, key_mangling=('-', '_'),
+                                          no_tag_node_value_mangle=True,
+                                          get_first_key=True)
+
+    # One needs to 'flatten' the keys dict from the config into the
+    # http-api.conf format for api_keys:
+    if 'keys' in api_dict:
+        api_dict['api_keys'] = []
+        for el in list(api_dict['keys']['id']):
+            key = api_dict['keys']['id'][el]['key']
+            api_dict['api_keys'].append({'id': el, 'key': key})
+        del api_dict['keys']
+
     # Do we run inside a VRF context?
     vrf_path = ['service', 'https', 'vrf']
     if conf.exists(vrf_path):
         http_api['vrf'] = conf.return_value(vrf_path)
 
-    conf.set_level('service https api')
-    if conf.exists('strict'):
-        http_api['strict'] = True
-
-    if conf.exists('debug'):
-        http_api['debug'] = True
+    if 'api_keys' in api_dict:
+        keys_added = True
 
-    if conf.exists('gql'):
-        http_api['gql'] = True
-        if conf.exists('gql introspection'):
-            http_api['introspection'] = True
+    if 'gql' in api_dict:
+        api_dict = dict_merge(defaults(base), api_dict)
 
-    if conf.exists('socket'):
-        http_api['socket'] = True
-
-    if conf.exists('port'):
-        port = conf.return_value('port')
-        http_api['port'] = port
-
-    if conf.exists('cors'):
-        http_api['cors'] = {}
-        if conf.exists('cors allow-origin'):
-            origins = conf.return_values('cors allow-origin')
-            http_api['cors']['origins'] = origins[:]
-
-    if conf.exists('keys'):
-        for name in conf.list_nodes('keys id'):
-            if conf.exists('keys id {0} key'.format(name)):
-                key = conf.return_value('keys id {0} key'.format(name))
-                new_key = { 'id': name, 'key': key }
-                http_api['api_keys'].append(new_key)
-                keys_added = True
+    http_api.update(api_dict)
 
     if keys_added and default_key:
         if default_key in http_api['api_keys']:
             http_api['api_keys'].remove(default_key)
 
+    # Finally, translate entries in http_api into boolean settings for
+    # backwards compatability of JSON http-api.conf file
+    _translate_values_to_boolean(http_api)
+
     return http_api
 
 def verify(http_api):
diff --git a/src/services/vyos-http-api-server b/src/services/vyos-http-api-server
index 190f3409d..4ace981ca 100755
--- a/src/services/vyos-http-api-server
+++ b/src/services/vyos-http-api-server
@@ -686,10 +686,16 @@ if __name__ == '__main__':
     app.state.vyos_keys = server_config['api_keys']
 
     app.state.vyos_debug = server_config['debug']
-    app.state.vyos_gql = server_config['gql']
-    app.state.vyos_introspection = server_config['introspection']
     app.state.vyos_strict = server_config['strict']
-    app.state.vyos_origins = server_config.get('cors', {}).get('origins', [])
+    app.state.vyos_origins = server_config.get('cors', {}).get('allow_origin', [])
+    if 'gql' in server_config:
+        app.state.vyos_gql = True
+        if isinstance(server_config['gql'], dict) and 'introspection' in server_config['gql']:
+            app.state.vyos_introspection = True
+        else:
+            app.state.vyos_introspection = False
+    else:
+        app.state.vyos_gql = False
 
     if app.state.vyos_gql:
         graphql_init(app)
-- 
cgit v1.2.3