Skip to content

Commit

Permalink
Added tests for Redis loader
Browse files Browse the repository at this point in the history
  • Loading branch information
rochacbruno committed May 15, 2018
1 parent d4f7914 commit 490691e
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 17 deletions.
21 changes: 19 additions & 2 deletions .travis.yml
Expand Up @@ -3,8 +3,8 @@ jobs:
- stage: tests
language: python
python: 3.6
services:
- redis-server
# services:
# - redis-server
env:
- DYNACONF_SETTINGS=dynaconf.test_settings
- DOTENV_PATH_FOR_DYNACONF=/home/travis/build/rochacbruno/dynaconf/.env
Expand Down Expand Up @@ -51,3 +51,20 @@ jobs:
before_script:
- sleep 5
script: make test_vault
- stage: test_redis
language: python
services:
- docker
before_install:
- docker pull redis
- docker run -d -p 6379:6379 redis
- docker ps -a
python: 3.6
env:
REDIS_FOR_DYNACONF_ENABLED=1
install:
- "pip install --upgrade pip"
- "pip install --upgrade -r requirements_dev.txt"
before_script:
- sleep 5
script: make test_redis
10 changes: 9 additions & 1 deletion Makefile
@@ -1,4 +1,4 @@
.PHONY: test install pep8 release clean doc test_examples
.PHONY: test install pep8 release clean doc test_examples test_vault test_redis

test_examples:
@cd example/;pwd;python full_example.py | grep -c full_example
Expand All @@ -16,11 +16,19 @@ test_examples:
@cd example/flask_with_ini;pwd;flask routes | grep -c flask_with_ini
@cd example/validator/;pwd;python app.py | grep -c validator


test_vault:
@cd example/vault;pwd;python write.py
@sleep 5
@cd example/vault;pwd;python vault_example.py | grep -c vault_works


test_redis:
@cd example/redis_example;pwd;python write.py
@sleep 5
@cd example/redis_example;pwd;python redis_example.py | grep -c redis_works


test: pep8
py.test --boxed -v --cov-config .coveragerc --cov=dynaconf -l --tb=short --maxfail=1 tests/

Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -507,7 +507,7 @@ pip install dynaconf[vault]
VAULT_FOR_DYNACONF_ENABLED=1
VAULT_FOR_DYNACONF_URL="http://localhost:8200"
VAULT_FOR_DYNACONF_TOKEN="myroot"
VAULT_FOR_DYNACONF_PATH="/secret/data/dynaconf"
VAULT_FOR_DYNACONF_PATH="/secret/data/" # the resulting namespace will have namespace added as in /secret/data/dynaconf
```

Now you can have keys like `PASSWORD` and `TOKEN` defined in the vault and
Expand Down
2 changes: 2 additions & 0 deletions dynaconf/base.py
Expand Up @@ -421,6 +421,8 @@ def namespace(self, namespace=None, clean=True, silent=True):

self.logger.debug("Namespace switching to: %s", namespace)

namespace = namespace.upper()

if namespace != self.NAMESPACE_FOR_DYNACONF:
self.loaded_namespaces.append(namespace)
else:
Expand Down
2 changes: 1 addition & 1 deletion dynaconf/default_settings.py
Expand Up @@ -77,7 +77,7 @@ def start_dotenv(obj=None):
VAULT_FOR_DYNACONF = get('VAULT_FOR_DYNACONF', default_vault)
VAULT_FOR_DYNACONF_ENABLED = get('VAULT_FOR_DYNACONF_ENABLED', False)
VAULT_FOR_DYNACONF_PATH = get('VAULT_FOR_DYNACONF_PATH',
'/secret/data/dynaconf')
'/secret/data/') # /namespace will be added

# Loaders to read namespace based vars from different data stores
default_loaders = [
Expand Down
25 changes: 16 additions & 9 deletions dynaconf/loaders/redis_loader.py
Expand Up @@ -28,12 +28,14 @@ def load(obj, namespace=None, silent=True, key=None):
holder = "DYNACONF_%s" % namespace
try:
if key:
value = parse_conf_data(redis.hget(holder.upper(), key))
value = redis.hget(holder.upper(), key)
if value:
obj.set(key, value)
parsed_value = parse_conf_data(value.decode('utf-8'))
if parsed_value:
obj.set(key, parsed_value)
else:
data = {
key: parse_conf_data(value)
key.decode('utf-8'): parse_conf_data(value.decode('utf-8'))
for key, value in redis.hgetall(holder.upper()).items()
}
if data:
Expand All @@ -59,20 +61,25 @@ def clean(obj, namespace, silent=True): # noqa
obj.unset(key)


def write(obj, **kwargs):
def write(obj, data=None, **kwargs):
"""
Write a value in to loader source
:param obj: settings object
:param data: vars to be stored
:param kwargs: vars to be stored
:return:
"""
client = StrictRedis(**obj.REDIS_FOR_DYNACONF)
holder = "DYNACONF_%s" % obj.NAMESPACE_FOR_DYNACONF
data = {
holder = "DYNACONF_%s" % obj.current_namespace
data = data or {}
data.update(kwargs)
if not data:
raise AttributeError('Data must be provided')
redis_data = {
key.upper(): unparse_conf_data(value)
for key, value in kwargs.items()
for key, value in data.items()
}
client.hmset(holder.upper(), data)
client.hmset(holder.upper(), redis_data)
load(obj)


Expand All @@ -84,7 +91,7 @@ def delete(obj, key=None):
:return: None
"""
client = StrictRedis(**obj.REDIS_FOR_DYNACONF)
holder = "DYNACONF_%s" % obj.NAMESPACE_FOR_DYNACONF
holder = "DYNACONF_%s" % obj.current_namespace
if key:
client.hdel(holder.upper(), key.upper())
obj.unset(key)
Expand Down
25 changes: 22 additions & 3 deletions dynaconf/loaders/vault_loader.py
@@ -1,6 +1,7 @@
# docker run -e 'VAULT_DEV_ROOT_TOKEN_ID=myroot' -p 8200:8200 vault
# pip install hvac

import os
from hvac import Client
from dynaconf.utils.parse_conf import parse_conf_data

Expand All @@ -17,7 +18,9 @@ def get_client(obj):

def load(obj, namespace=None, silent=None, key=None):
client = get_client(obj)
data = client.read(obj.VAULT_FOR_DYNACONF_PATH)
namespace = namespace or obj.current_namespace
path = os.path.join(obj.VAULT_FOR_DYNACONF_PATH, namespace.lower())
data = client.read(path)
if data:
data = data.get('data', {}).get('data')

Expand All @@ -36,6 +39,22 @@ def load(obj, namespace=None, silent=None, key=None):
raise


def write(obj, data, lease='1h'):
def write(obj, data=None, lease='1h', **kwargs):
"""
Write a value in to loader source
:param obj: settings object
:param data: vars to be stored
:param kwargs: vars to be stored
:return:
"""
data = data or {}
data.update(kwargs)
if not data:
raise AttributeError('Data must be provided')
client = get_client(obj)
client.write(obj.VAULT_FOR_DYNACONF_PATH, data=data, lease=lease)
path = os.path.join(
obj.VAULT_FOR_DYNACONF_PATH,
obj.current_namespace.lower()
)
client.write(path, data=data, lease=lease)
load(obj)
8 changes: 8 additions & 0 deletions example/redis_example/redis_example.py
@@ -0,0 +1,8 @@
from dynaconf import settings

print(settings.SECRET) # noqa
# >>> 'redis_works'


with settings.using_namespace('dev'):
assert settings.SECRET == 'redis_works_in_dev'
7 changes: 7 additions & 0 deletions example/redis_example/write.py
@@ -0,0 +1,7 @@
from dynaconf import settings
from dynaconf.loaders import redis_loader

redis_loader.write(settings, {'SECRET': 'redis_works'})

with settings.using_namespace('dev'):
redis_loader.write(settings, {'SECRET': 'redis_works_in_dev'})
4 changes: 4 additions & 0 deletions example/vault/vault_example.py
Expand Up @@ -2,3 +2,7 @@

print(settings.SECRET) # noqa
# >>> 'vault_works'


with settings.using_namespace('dev'):
assert settings.SECRET == 'vault_works_in_dev'
3 changes: 3 additions & 0 deletions example/vault/write.py
Expand Up @@ -2,3 +2,6 @@
from dynaconf.loaders import vault_loader

vault_loader.write(settings, {'SECRET': 'vault_works'})

with settings.using_namespace('dev'):
vault_loader.write(settings, {'SECRET': 'vault_works_in_dev'})

0 comments on commit 490691e

Please sign in to comment.