uber-go / fx

A dependency injection based application framework for Go.
https://uber-go.github.io/fx/
MIT License
5.82k stars 290 forks source link

Injecting yaml configuration #670

Closed Echolz closed 5 years ago

Echolz commented 5 years ago

Can you provide a detailed guide on how to inject a configuration which is in a json/yaml/xml file with fx.

I went through the yarpc's source code, which uses injection through a yaml file but could not understand how it works/how to set up my fx module to use a configuration.

glibsm commented 5 years ago

https://github.com/uber-go/config is a stand-alone package that provides all things configuration related. Sadly, there is currently no publicly available config.Module that easily integrates with Fx.

Here is a full example of how to take a config.yaml file and share the result in the Fx application graph.

❯ cat config.yaml
application:
  name: config-demo

database:
  username: foo
  password: bar
package main

import (
    "fmt"

    "go.uber.org/config"
    "go.uber.org/fx"
)

func main() {
    fx.New(
        fx.Provide(LoadConfig),
        fx.Invoke(ConnectToDB),
    ).Run()
}

// Configuration defines the overall struct for what is expected in yaml
type Configuration struct {
    Application struct {
        Name string
    }
    Database struct {
        Username string
        Password string
    }
}

// LoadConfig constructor that takes "config.yaml" file and loads it into
// Configuration struct.
func LoadConfig() (Configuration, error) {
    var c Configuration

    cfg, err := config.NewYAML(config.File("config.yaml"))
    if err != nil {
        return c, err
    }

    if err := cfg.Get("").Populate(&c); err != nil {
        return c, err
    }

    return c, nil
}

// ConnectToDB depends on the Configuration struct from the container
func ConnectToDB(c Configuration) {
    fmt.Println("configuration >>>", c)
    // at this point configuration can be used to connect to DB, etc...
}

The output from running this does the expected thing:

❯ go run main.go
2019/02/19 10:45:31 [Fx] PROVIDE        main.Configuration <= main.LoadConfig()
2019/02/19 10:45:31 [Fx] PROVIDE        fx.Lifecycle <= go.uber.org/fx.New.func1()
2019/02/19 10:45:31 [Fx] PROVIDE        fx.Shutdowner <= go.uber.org/fx.(*App).shutdowner-fm()
2019/02/19 10:45:31 [Fx] PROVIDE        fx.DotGraph <= go.uber.org/fx.(*App).dotGraph-fm()
2019/02/19 10:45:31 [Fx] INVOKE         main.ConnectToDB()
configuration >>> {{config-demo} {foo bar}}