From 487a5b580fd96c84f36ffa78bf26036e76a8dc08 Mon Sep 17 00:00:00 2001 From: hmartel Date: Fri, 31 Jul 2020 08:08:51 -0500 Subject: [PATCH] Local services (#61) * Add intellij to .gitignore * Add a way to invoke local aims-less services Co-authored-by: Hugues Martel --- .gitignore | 3 +++ README.md | 25 +++++++++++++++++++++++++ almdrlib/config.py | 42 ++++++++++++++++++++++++++++++++++++++---- almdrlib/constants.py | 1 + almdrlib/session.py | 17 ++++++++++++++++- 5 files changed, 83 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 158236b..023cb40 100644 --- a/.gitignore +++ b/.gitignore @@ -82,6 +82,9 @@ target/ profile_default/ ipython_config.py +#IntelliJ +.idea + # pyenv .python-version diff --git a/README.md b/README.md index 1639641..af181eb 100644 --- a/README.md +++ b/README.md @@ -79,3 +79,28 @@ pip install -r requirements_dev.txt pip install -e . ``` +### Using local services + +- Setup a local profile: + +``` +[aesolo] +access_key_id=skip +secret_key=skip +global_endpoint=map +endpoint_map_file=aesolo.json +``` + +- Write an endpoint map (here, `~/.alertlogic/aesolo.json`; `endpoint_map_file` can also be an absolute path): + +``` +{ + "aecontent" : "http://127.0.0.1:8810", + "aefr" : "http://127.0.0.1:8808", + "aepublish" : "http://127.0.0.1:8811", + "aerta" : "http://127.0.0.1:8809", + "aetag" : "http://127.0.0.1:8812", + "aetuner": "http://127.0.0.1:3000", + "ingest" : "http://127.0.0.1:9000" +} +``` diff --git a/almdrlib/config.py b/almdrlib/config.py index 130e1fe..9db3bb0 100644 --- a/almdrlib/config.py +++ b/almdrlib/config.py @@ -3,6 +3,7 @@ import os.path import configparser import logging +import json import almdrlib.constants from almdrlib.exceptions import AlmdrlibValueError @@ -16,7 +17,7 @@ def __init__(self, message): class Config(): """ - Reads configuraiton parameters from either environment variables + Reads configuration parameters from either environment variables or from configuration file Environment Variables: @@ -24,10 +25,11 @@ class Config(): ~/.alertlogic/credentials is used ALERTLOGIC_PROFILE - Profile to be used. If not specified [default] section is used - ALERTLOGIC_ACCESS_KEY_ID - Acceess Key Id + ALERTLOGIC_ACCESS_KEY_ID - Access Key Id ALERTLOGIC_SECRET_KEY - Secret Key - ALERTLOGIC_ENDPOINT - production or integration are supported values - ALERTLOGIC_ACCOUNT_ID - Account Id to perform operatins against. + ALERTLOGIC_ENDPOINT - production, integration, or map are supported values + ALERTLOGIC_ENDPOINT_MAP - (full or relative to config directory) path of a json file mapping services to endpoints + ALERTLOGIC_ACCOUNT_ID - Account Id to perform operations against. ALERTLOGIC_RESIDENCY - Data Residency when creating new deployments ALERTLOGIC_API - Directory where OpenAPI yaml files reside @@ -35,6 +37,7 @@ class Config(): access_key_id - User's AIMS Access Key ID secret_key - Secret Key associated with 'access_key_id' global_endpoint - if not specified, 'production' endpoint is used + endpoint_map_file - if not specified, 'endpoint_map.json' in the config directory (default: ~/.alertlogic) is used account_id - if not specified, the account id of the access_key_id is used residency - if not specified, 'us' residency is used @@ -47,6 +50,7 @@ def __init__(self, account_id=None, profile=None, global_endpoint=None, + endpoint_map_file=None, residency=None): self._config_file = os.environ.get('ALERTLOGIC_CONFIG') if self._config_file is None: @@ -66,6 +70,10 @@ def __init__(self, global_endpoint or \ os.environ.get('ALERTLOGIC_ENDPOINT') + self._endpoint_map_file = \ + endpoint_map_file or \ + os.environ.get('ALERTLOGIC_ENDPOINT_MAP') + self._residency = \ residency or \ os.environ.get('ALERTLOGIC_RESIDENCY') @@ -119,6 +127,22 @@ def _initialize_config(self): 'global_endpoint', almdrlib.constants.DEFAULT_GLOBAL_ENDPOINT) + self._endpoint_map_file = \ + self._endpoint_map_file or self._get_config_option( + 'endpoint_map_file', + almdrlib.constants.DEFAULT_ENDPOINT_MAP_FILE) + self._endpoint_map_file = \ + self._endpoint_map_file or \ + almdrlib.constants.DEFAULT_ENDPOINT_MAP_FILE + + if self._global_endpoint == "map": + if os.path.isabs(self._endpoint_map_file): + path = self._endpoint_map_file + else: + path = os.path.join(almdrlib.constants.DEFAULT_CONFIG_DIR, self._endpoint_map_file) + with open(path) as json_file: + self._endpoint_map = json.load(json_file) + self._residency = \ self._residency or \ self._get_config_option( @@ -143,6 +167,7 @@ def configure( account_id=None, access_key_id=None, secret_key=None, global_endpoint=None, + endpoint_map_file=None, residency=None): if not access_key_id: @@ -164,11 +189,16 @@ def configure( parser.set(profile, 'access_key_id', access_key_id) parser.set(profile, 'secret_key', secret_key) + if account_id: parser.set(profile, 'account_id', account_id) + if global_endpoint: parser.set(profile, 'global_endpoint', global_endpoint) + if endpoint_map_file: + parser.set(profile, 'endpoint_map_file', endpoint_map_file) + if residency: parser.set(profile, 'residency', residency) @@ -197,6 +227,10 @@ def account_id(self): def global_endpoint(self): return self._global_endpoint + @property + def endpoint_map(self): + return self._endpoint_map + @property def residency(self): return self._residency diff --git a/almdrlib/constants.py b/almdrlib/constants.py index ec57199..f5ade39 100644 --- a/almdrlib/constants.py +++ b/almdrlib/constants.py @@ -7,4 +7,5 @@ DEFAULT_CREDENTIALS_FILE = os.path.join(DEFAULT_CONFIG_DIR, "credentials") DEFAULT_PROFILE = "default" DEFAULT_GLOBAL_ENDPOINT = "production" +DEFAULT_ENDPOINT_MAP_FILE = "endpoint_map.json" DEFAULT_RESIDENCY = "default" diff --git a/almdrlib/session.py b/almdrlib/session.py index 19b1f76..36a1b68 100644 --- a/almdrlib/session.py +++ b/almdrlib/session.py @@ -59,7 +59,7 @@ def __init__( the account id of the access_key_id is used. :param: profile: name of the profile section of the configuration file :param: global_endpoint: Name of the global endpoint. - 'production' or 'integration' are + 'production', 'integration', or 'map' are the only valid values :param residency: Data residency name to perform data residency dependend actions. @@ -119,6 +119,7 @@ def _init_session(self, *args, **kwargs): self._account_id = self._config.account_id self._residency = self._config.residency self._global_endpoint = self._config.global_endpoint + self._endpoint_map = self._config.endpoint_map self._global_endpoint_url = Region.get_global_endpoint( self._global_endpoint) self._raise_for_status = kwargs.get('raise_for_status') @@ -145,6 +146,14 @@ def _authenticate(self): """ if not self._token: + if self._access_key_id == "skip" and self._secret_key == "skip": + logger.info( + f"Skipping authentication." + ) + self._token = "" + self._account_id = "" + self._account_name = "" + return logger.info( f"Authenticating '{self._access_key_id}' " + f"user against '{self._global_endpoint_url}' endpoint." @@ -238,6 +247,8 @@ def __init__(self, return _client def get_url(self, service_name, account_id=None): + if self._global_endpoint == "map": + return self.get_mapped_url(service_name, account_id) try: response = self.request( 'get', @@ -253,6 +264,10 @@ def get_url(self, service_name, account_id=None): ) return "https://{}".format(response.json()[service_name]) + def get_mapped_url(self, service_name, account_id): + map = self._endpoint_map + return map[service_name] + def request( self, method,