Skip to content

Instantly share code, notes, and snippets.

@erodozer
Last active February 27, 2018 20:07
Show Gist options
  • Save erodozer/277abc18e1b309dbabf1ac2c5fad73ec to your computer and use it in GitHub Desktop.
Save erodozer/277abc18e1b309dbabf1ac2c5fad73ec to your computer and use it in GitHub Desktop.
Sanic Config loading with Consul
from sanic import Sanic
from consul.aio import Consul
import default_settings
import asyncio
"""
Initialize application
"""
app = Sanic()
app.config.from_object(default_settings)
async def load_config_from_consul():
"""
Load config from Consul.
Pings the Consul service every 30 or so seconds for changes
This version will iterate over each key of the app and look for individaul Consul entries for them.
A bit more complex, but allows for lighter-weight, fine grained updates.
"""
consul = Consul(loop=app.loop)
conf = { attr: None for (attr, value) in app.config.items() }
async def update_key(key):
print(f"consul:{key}:Reading Value")
index, data = await consul.kv.get("/".join(key.lower().split("_")), index=conf[key])
if bool(data):
val = data['Value'].decode("utf-8")
if app.config[key] != val:
app.config[key] = val
print(f"consul:{key}:{val}")
else:
print(f"consul:{key}:Value Unchanged")
else:
print(f"consul:{key}:Value Not Found")
conf[key] = index
while True:
for attr, val in app.config.items():
await update_key(attr)
await asyncio.sleep(30)
@app.listener('before_server_start')
def before(app, loop):
app.add_task(load_config_from_consul)
if __name__ == "__main__":
app.run(host="localhost", port=54658, debug=True)
from sanic import Sanic
from consul.aio import Consul
import default_settings
import asyncio
import json
"""
Initialize application
"""
app = Sanic()
app.config.from_object(default_settings)
async def load_config_from_consul():
"""
Load config from Consul.
Pings the Consul service every 30 or so seconds for changes
This version will look for a single config entry for the entire app. Whenever something
of it changes, it'll reload the entire thing. The config should be stored as json, for easy parsing.
"""
consul = Consul(loop=app.loop)
index = None
while True:
index, data = await consul.kv.get("myapp.properties", index=index)
if bool(data):
val = data['Value'].decode("utf-8")
obj = json.loads(val)
app.config.update(obj)
print("consul:config:App Updated")
await asyncio.sleep(30)
@app.listener('before_server_start')
def before(app, loop):
app.add_task(load_config_from_consul)
if __name__ == "__main__":
app.run(host="localhost", port=54658, debug=True)
"""
Default configuration values for the app.
Production should pull accurate values from Consul, but this is fine for local development and to get the app started
Sanic requires settings to be in all upper-case.
We translate underscores into / for consul, allowing us to have organized paths for configuration when using
the per key loader, else this is how key-value pairs should appear in a json stored in Consul.
"""
NEO4J_HOST = "http://localhost:7474/data/db/"
NEO4J_USERNAME = "neo4j"
NEO4J_PASSWORD = "neo4j"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment