cloudfoundry / go-buildpack

Cloud Foundry buildpack for the Go Language
http://docs.cloudfoundry.org/buildpacks/
Apache License 2.0
82 stars 119 forks source link

Configuration Best Practices? #39

Closed cwlbraa closed 8 years ago

cwlbraa commented 8 years ago

On 1.7.7 of the buildpack, we were trying to deploy a small go web server that needed configuration to vary across local, acceptance, and production environments.

While Golang itself doesn't provide any aid with this, the user experience of picking up and using this buildpack can be pretty awkward in terms of supplying configuration, as Procfiles only take one line of command line flags, and environment variables aren't great for things like lists...

It'd be great to have some documentation or example app surrounding best practices for loading configurations and how that interacts with manifests and Procfiles.

We've found that having a Procfile with:

web: app_name -c config.json

is very effective for supplying complex configurations.

This makes main looks something like:

package main
import (...)
var configFile = flag.String(
    "c",
    "",
    "path to config file",
)

func main() {
    port := os.Getenv("PORT")
    if port == "" {
        log.Fatal("$PORT must be set")
    }

    config, err := config.Parse(*configFile)
    if err != nil {
        log.Fatal("config file error: ", err)
    }

    handler := handlers.NewHandler(*config)
    http.HandleFunc("/", handler.Handle)

    fmt.Println("go-fetch-server.ready")
    log.Fatal(http.ListenAndServe(":"+port, nil))
}

Thanks, Connor && Nima

cf-gitbot commented 8 years ago

We have created an issue in Pivotal Tracker to manage this. You can view the current status of your issue at: https://www.pivotaltracker.com/story/show/118683801.

jvshahid commented 8 years ago

Thanks @cwlbraa for asking this question. There are many solutions that come to my mind. You can provide the config file path as an environment variable and set the env. variable to different values depending on the environment, e.g. CONFIG_FILE = prod_config.json if you are running prod. Alternatively, the config file can have multiple environments, e.g.:

default: &default
  user: admin
  password: admin
  server: staging.server.com

production:
  <<: *default
  server: prod.server.com

Then set the environment in a environment variable and use that env variable during app initialization to find the section of the config file that should be used.

I really encourage you to ask this question on cf-dev mailing list for a much bigger audience and other thoughts from the community.

I'll close this issue since it isn't necessarily relevant for this particular buildpack. Please feel free to reopen it if you feel otherwise.