README.md

# SpringConfig

SpringConfig allows Elixir projects to load configuration from a Spring centralized configuration server

## Installation

### Hex

using Hex:

```elixir
def deps do
  [
    {:spring_config, "~> 0.1.1"}
  ]
end
```

### Git

SpringConfig can be installed using Git:

```elixir
def deps do
  [
    {:spring_config, github: "johnf9896/spring_config"}
  ]
end
```

## Documentation

Documentation can be found in [https://hexdocs.pm/spring_config](here)

## Usage

Add this to your `config.exs`:

```elixir
config :spring_config,
  otp_app: :my_app,
  profile: Mix.env()
```

### application.yaml

SpringConfig requires an YAML file to be part of your application. By default this file's path is `priv/application.yaml` and the following is an example:

```yaml
spring:
  application:
    name: my_app

---

spring:
  profiles: dev
  cloud:
    config:
      uri: http://localhost:9888/config-service

---

spring:
  profiles: prod
  cloud:
    config:
      uri: http://example.com/config-service
```

### Accessing the configuration

#### provided configuration

```yaml
foo: value
bar:
  bazz: 3
  fuzz: value2
```

#### Accessing it in Elixir

```elixir
iex> SpringConfig.get!(:foo)
"value"

iex> SpringConfig.get!(:"bar.bazz")
3

iex> SpringConfig.get!(:"not.found")
** (RuntimeError) Key not.found not found in configuration entries

iex> SpringConfig.get(:"not.found", "default-value")
"default-value"
```

### Environment configuration

You can set any SpringConfig config key from an environment variable using a system tuple, for example:

```elixir
config :spring_config,
  profile: {:system, "APP_PROFILE", "dev"} # will use dev as profile if APP_PROFILE is not defined

config :spring_config,
  profile: {:system, "APP_PROFILE"} # will raise if APP_PROFILE is not defined
```

### Available config keys

The following keys are allowed to configure SpringConfig

| Key | Description | Example | Required | Default | Type |
| --- | --- | --- | --- | --- | --- |
| otp_app | The app that contains the YAML file | `:my_app` | Yes | N/A | Atom or String |
| path | Spring local configuration file | `"priv/my_app.yml"` | No | `"priv/application.yml"` | String |
| app_name | Name to use when requesting the remote configuration | `"my-app"` | No | The value of the key `"string.application.name"` in the YAML file. Will raise if neither is found | String |
| profile | The profile to use when requesting the remote configuration | `Mix.env()`, `"staging"` | Yes | N/A | Atom or String |
| remote_uri_key | The key in the YAML file to use for the remote server | `:"remote.uri"` | No | `:"spring.cloud.config.uri"` | Atom or String |
| remote_uri | The base url of the remote server | `"http://localhost:9888/config-service"` | No | The value of the `remote_uri_key`. if present the key specified in `remote_uri_key` is not required to be present | String |

The url for requesting the remote configuration is made like so:
`$remote_uri/$app_name/$profile`

### Integrating with Ecto

You can integrate SpringConfig with Ecto through Ecto's `init/2` callback

In your remote configuration:

```yaml

spring:
  profiles: prod

database:
  database: dbname
  password: super-secret
  hostname: 1.2.3.4
  port: "5432"
  username: db_user

```

In Ecto's callback:

```elixir

defmodule MyApp.Repo do
  use Ecto.Repo, otp_app: :my_app, adapter: Ecto.Adapters.Postgres

  def init(_, opts) do
    # When running migrations, Ecto starts the repository outside the supervision tree,
    # so SpringConfig is not available. If you want to run migrations, pass ensure_started: true
    # and SpringConfig will start temporarily using Application.ensure_all_started
    db_config = SpringConfig.get!(:"database", ensure_started: true)

    opts = Keyword.merge(Map.to_list(db_config), opts)
    # or opts = Keyword.merge(opts, Map.to_list(db_config))
    # depening on which configuration should take precedence

    {:ok, opts}
  end
end

```

License

-------

    Copyright 2018 Jhon Pedroza

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.