Skip to content

Commit

Permalink
Version 1.0.0-beta.1 - Almost Stable
Browse files Browse the repository at this point in the history
### Added

- An interface for Fidelius gateway repos and admins to fulfil
- A mock implementation of a Fidelius gateway repo and admin that use a
  simple singleton dict to store (and share) data during runtime
- Unittests for the mock implementation
- Unittests for the Parameter Store implementation using LocalStack
- A Factory class to get different implementation classes
- Methods to delete parameters
- Config params for the `AwsParamStoreRepo` to use a custom AWS endpoint in
  order to hook up to stuff like LocalStack for testing and such

### Changed

- The API a little bit so we're no longer backwards compatible (hence the
  major version bump to 1.0.0)
- All config params can now be explicitly given to the `AwsParamStoreRepo`
  in addition to being picked up from environment variables if not supplied
  • Loading branch information
CCP-Zeulix committed Apr 11, 2024
1 parent 4cf941d commit 96ba36d
Show file tree
Hide file tree
Showing 21 changed files with 829 additions and 204 deletions.
20 changes: 16 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,26 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased] - ?
## [1.0.0-beta.1] - 2024-04-11

### Added

- An interface for Fidelius gateway repos and admins to fulfil
- A mock implementation of a Fidelius gateway repo and admin that can read
in mock values from JSON files and mess with them in-memory, for use in
unit-tests of other code that uses Fidelius
- A mock implementation of a Fidelius gateway repo and admin that use a
simple singleton dict to store (and share) data during runtime
- Unittests for the mock implementation
- Unittests for the Parameter Store implementation using LocalStack
- A Factory class to get different implementation classes
- Methods to delete parameters
- Config params for the `AwsParamStoreRepo` to use a custom AWS endpoint in
order to hook up to stuff like LocalStack for testing and such

### Changed

- The API a little bit so we're no longer backwards compatible (hence the
major version bump to 1.0.0)
- All config params can now be explicitly given to the `AwsParamStoreRepo`
in addition to being picked up from environment variables if not supplied


## [0.6.0] - 2024-04-05
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ package in mind but should work for other cases as well.
**IMPORTANT:** This has been migrated more-or-less _"as-is"_ from CCP Tool's
internal repo and hasn't yet been given the love it needs to be properly
open-sourced and user friendly for other people _(unless you read though the
code and find it perfectly fits your use case)_.
code and find it perfectly fits your use case)_.

**ALSO IMPORTANT:** This README hasn't been updated to reflect changes in
version 1.0.0 yet. Sowwie! :-/

## What should be stored with Fidelius

Expand Down
2 changes: 1 addition & 1 deletion fidelius/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '0.7.0-dev.3'
__version__ = '1.0.0-beta.1'

__author__ = 'Thordur Matthiasson <[email protected]>'
__license__ = 'MIT License'
Expand Down
24 changes: 16 additions & 8 deletions fidelius/gateway/_abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ def make_app_path(self, env: Optional[str] = None) -> str:
"""The full path to application specific parameters/secrets.
"""
return self._APP_PATH_FORMAT.format(group=self.app_props.group,
env=env or self.app_props.env,
app=self.app_props.app,
name='{name}')
env=env or self.app_props.env,
app=self.app_props.app,
name='{name}')

def make_shared_path(self, folder: str, env: Optional[str] = None) -> str:
"""The full path to group shared parameters/secrets.
Expand Down Expand Up @@ -117,23 +117,30 @@ def get(self, name: str, folder: Optional[str] = None, no_default: bool = False)
value was found for the current set environment.
:return: The requested parameter/secret or None if it was not found.
"""
log.debug('_BaseFideliusRepo.get(name=%s, folder=%s, no_default=%s))', name, folder, no_default)
if folder:
val = self.get_shared_param(name=name, folder=folder)
log.debug('_BaseFideliusRepo.get->get_shared_param val=%s', val)
if val is not None:
return val

if no_default:
log.debug('_BaseFideliusRepo.get->(shared) no_default STOP!')
return None

log.debug('_BaseFideliusRepo.get->(shared) Lets try the default!!!')
return self.get_shared_param(name=name, folder=folder, env='default')
else:
val = self.get_app_param(name=name)
log.debug('_BaseFideliusRepo.get->get_app_param val=%s', val)
if val is not None:
return val

if no_default:
log.debug('_BaseFideliusRepo.get->(app) no_default STOP!')
return None

log.debug('_BaseFideliusRepo.get->(app) Lets try the default!!!')
return self.get_app_param(name=name, env='default')

def replace(self, string: str, no_default: bool = False) -> str:
Expand All @@ -145,25 +152,26 @@ def replace(self, string: str, no_default: bool = False) -> str:
- `${__FID__:PARAM_NAME}` for app params/secrets
- `${__FID__:FOLDER:PARAM_NAME}` for shared params/secrets in the given FOLDER
If the given string does not match a Fidilius expression, then it is
returned unchanged.
An empty string is returned if the parameter was not found and if the
string does not match the expression format, it will be returned
unchanged.
:param string: The expression to replace with an actual parameter/secret
:param no_default: If True, does not try and get the default value if no
value was found for the current set environment.
:return: The requested value
:return: The requested value, an empty string or the original string
"""
m = self._EXPRESSION_PATTERN.match(string)
if m:
return self.get(m.group('name'), m.group('folder'), no_default=no_default)
return self.get(m.group('name'), m.group('folder'), no_default=no_default) or ''
return string


class _BaseFideliusAdminRepo(_BaseFideliusRepo, IFideliusAdminRepo, abc.ABC):
"""Covers a lot of admin basic functionality common across most storage back-ends.
"""
def __init__(self, app_props: FideliusAppProps, tags: Optional[FideliusTags] = None, **kwargs):
log.debug('_BaseFideliusAdminRepo.__init__')
log.debug('_BaseFideliusAdminRepo.__init__ (this should set tags?!?)')
super().__init__(app_props, **kwargs)
self._tags = tags

Expand Down
2 changes: 0 additions & 2 deletions fidelius/gateway/file/__init__.py

This file was deleted.

36 changes: 0 additions & 36 deletions fidelius/gateway/file/_filerepo.py

This file was deleted.

10 changes: 8 additions & 2 deletions fidelius/gateway/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,14 @@ def replace(self, string: str, no_default: bool = False) -> str:
- `${__FID__:PARAM_NAME}` for app params/secrets
- `${__FID__:FOLDER:PARAM_NAME}` for shared params/secrets in the given FOLDER
An empty string is returned if the parameter was not found and if the
string does not match the expression format, it will be returned
unchanged.
:param string: The expression to replace with an actual parameter/secret
:param no_default: If True, does not try and get the default value if no
value was found for the current set environment.
:return: The requested value
:return: The requested value, an empty string or the original string
"""
pass

Expand All @@ -147,7 +151,9 @@ def __init__(self, app_props: FideliusAppProps, tags: Optional[FideliusTags] = N
:param app_props: The application properties to use.
:param tags: An optional set of meta-data tags to use when creating new
parameters (if supported by the underlying
parameter/secret storage).
parameter/secret storage). Note that updating a parameter
does not update/change tags, they are only applied when
creating new parameters!
"""
pass

Expand Down
19 changes: 19 additions & 0 deletions fidelius/gateway/mock/_inmemcache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
__all__ = [
'_SingletonDict',
]

from ccptools.structs import *


class _SingletonDict(dict, metaclass=Singleton):
"""Simple Singleton dict :)
It's point is simply to act as a shared centralized store for the mock
stuff, mimicking how multiple instances of Fidelius Repos and/or Admin
Repos would nevertheless fetch data from the same source.
This is just to "mock" the shared parameter/secret stuff.
...sneaky, right?
"""
pass
13 changes: 4 additions & 9 deletions fidelius/gateway/mock/_mockadmin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@

from fidelius.gateway._abstract import *
from fidelius.structs import *
from ._mockrepo import *

import logging
log = logging.getLogger(__name__)


class MockFideliusAdmin(_BaseFideliusAdminRepo):
class MockFideliusAdmin(_BaseFideliusAdminRepo, MockFideliusRepo):
def __init__(self, app_props: FideliusAppProps, tags: Optional[FideliusTags] = None, **kwargs):
"""This mock version of the Fidelius Admin stores created and updated
params in memory only.
params in memory only (although the cache is a singleton so multiple
instances of both admin and repo will be useing the same dict/data.
Note that it does NOT extend the functionality of its non-Admin sibling,
the MockFideliusRepo and thus does not return a base64 encoded version
Expand All @@ -25,13 +27,6 @@ def __init__(self, app_props: FideliusAppProps, tags: Optional[FideliusTags] = N
"""
log.debug('MockFideliusAdmin.__init__')
super().__init__(app_props, tags, **kwargs)
self._cache = {}

def get_app_param(self, name: str, env: Optional[str] = None) -> Optional[str]:
return self._cache.get(self.get_full_path(name, env=env), None)

def get_shared_param(self, name: str, folder: str, env: Optional[str] = None) -> Optional[str]:
return self._cache.get(self.get_full_path(name, folder, env=env), None)

def _create(self, name: str, value: str, env: Optional[str] = None, folder: Optional[str] = None) -> (str, str):
key = self.get_full_path(name, folder=folder, env=env)
Expand Down
6 changes: 4 additions & 2 deletions fidelius/gateway/mock/_mockrepo.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from fidelius.structs import *
from fidelius.gateway._abstract import *
from ._inmemcache import _SingletonDict

import base64

Expand All @@ -21,9 +22,10 @@ def __init__(self, app_props: FideliusAppProps, **kwargs):
"""
log.debug('MockFideliusRepo.__init__')
super().__init__(app_props, **kwargs)
self._cache: _SingletonDict[str, str] = _SingletonDict()

def get_app_param(self, name: str, env: Optional[str] = None) -> Optional[str]:
return base64.encodebytes(self.get_full_path(name, env=env).encode('utf-8')).decode('utf-8').strip()
return self._cache.get(self.get_full_path(name, env=env), None)

def get_shared_param(self, name: str, folder: str, env: Optional[str] = None) -> Optional[str]:
return base64.encodebytes(self.get_full_path(name, folder=folder, env=env).encode('utf-8')).decode('utf-8').strip()
return self._cache.get(self.get_full_path(name, folder, env=env), None)
Loading

0 comments on commit 96ba36d

Please sign in to comment.