amenezes / config-client

config-client package for spring cloud config and cloud foundry
https://config-client.amenezes.net/
Apache License 2.0
24 stars 17 forks source link

Local Configuration Support #19

Closed Lubytes closed 4 years ago

Lubytes commented 4 years ago

This might already exist and I just don't know how to utilise it, but is it possible for a local build to use an already existing application.json/yaml inside the project?

In Spring Java, you can put an application.yml inside src/main/resources/ and it'll pick that up with a local build. The config-server replaces this when deployed to Cloud Foundry. Is it possible for this to do the same?

anishp55 commented 4 years ago

those are facilities provided by Spring as a whole. I would say that this particular request is outside the scope of this project.

amenezes commented 4 years ago

@Lubytes at first I agree with @anishp55 this library it's useful for integrate a python application to spring cloud config. I think that the python ecosystem has more robust and powerful tools to address this as, for example:

Do you have any specific need to discuss or this answer satisfies this issue?

Lubytes commented 4 years ago

Yeah I'm currently parsing a local config if cf cannot be reached like so:

try:
  cf = CF()
  cf.get_config()
  resources = cf.config
except:
  resources = yaml.load(open('resources/application.yml','r'), Loader=yaml.FullLoader)

I can't be specific on the except as there's a sys.exit happening if the get_config() fails. Perhaps throwing an exception might be better?

But I guess my main issue is having to wrap the cf config stuff in a try to begin with. Any ideas for a cleaner implementation?

amenezes commented 4 years ago

@Lubytes really sorry for delay.

I can't be specific on the except as there's a sys.exit happening if the get_config() fails. Perhaps throwing an exception might be better?

I'm fixing this for the next release 0.6.0 changing sys.exit(1) to raise SystemExit(1). But anyway I added an option to disable fail_fast behavior that will be True by default. So can you disable this feature setting fail_fast to False. For example:

client = spring.ConfigClient(app_name='myapp', fail_fast=False)

But I guess my main issue is having to wrap the cf config stuff in a try to begin with. Any ideas for a cleaner implementation?

For the above case what I've been using is set the environment variables to override the default values to contact the configuration server or exit in case of fail. So on the application startup one of the first things I do it's request my profile configuration to setup the application propertly or exit in case of fail. This for Java or Python applications.

For example my bootstrap.yml have this only:

spring:
  application:
    name: myapp
  cloud:
    config:
      uri: http://configserver:8080
      failFast: true
      retry:
        maxAttempts: 5

And for Python application I have use python-dotenv including the below variables on the .env file:

APP_NAME=myapp
CONFIGSERVER_ADDRESS=http://configserver:8080
PROFILE=development

Any additional parameter will be present on the .env file, following 12factor.

Maybe an example could be:

notice: I have change CF to ConfigClient to test locally

Could you use a config-server instance like:

docker run -d --rm --name config-server -p 8888:8888 amenezes/spring-cloud-configserver

First try use development profile configuring the .env file like:

APP_NAME=simpleweb000
PROFILE=development

And the application like:

import json
from pathlib import Path
from dotenv import load_dotenv
from config.spring import ConfigClient
from flask import Flask, escape, request

load_dotenv(
    dotenv_path=Path('.') / '.env',
    verbose=True,
    override=False
)

cf = ConfigClient()
cf.get_config()

app = Flask(__name__)

@app.route('/')
def hello():
    name = request.args.get("name", "World")
    return f'Hello, {escape(name)}!'

@app.route('/config')
def config():
    return cf.config

@app.route('/config-keys')
def keys():
    return json.dumps(list(cf.get_keys()))

# to run execute: env FLASK_APP=<file_name>.py flask run

Tests:

  1. access http://localhost:5000/config check the config;
  2. stop application and change the profile to prod and make another request;
  3. down the container docker stop config-server and try run application again.

This flow make sense to your use case? Or is there something I didn't consider?

amenezes commented 4 years ago

Issue resolved in version 0.6.0.