Go library for Spring Config Server. Inspired by the Java library Cloud Config Client.
go get github.com/Piszmog/cloudconfigclient/v2
See V2 Migration for details on how to migrate from V1 to V2
Spring's Config Server provides way to externalize configurations of applications. Spring's Spring Cloud Config Client can be used to load the base configurations that an application requires to properly function.
This library provides clients the ability to load Configurations and Files from the Config Server.
This library is compatible with versions of Spring Config Server greater than or equal to 1.4.x.RELEASE
. Prior
versions of the Config Server do not provide the endpoint necessary to retrieve files for the Config Server's default
branch.
Since Spring Cloud Services v3.0, the service name in VCAP_SERVICES
has changed from p-config-server
to
be p.config-server
.
To help mitigate migration difficulties, cloudconfigclient.New(cloudconfigclient.DefaultCFService())
will first search
for the service p.config-server
(v3.x). If the v3.x service could not be found,
p-config-server
(v2.x) will be search for.
See Spring Cloud Services Differences for more details.
Below is an example usage of the library to retrieve a file from the Config Server and to retrieve the application's configurations
- For local config client, there are two options (
Option
) the create a client- Call
LocalEnv()
. Set the environment variableCONFIG_SERVER_URLS
. It is a comma separated list of all the base URLs - Call
Local(baseUrls ...string)
. Provide the array of base URLs of Config Servers.
- Call
- If the config server is protected with basic auth, call
Basic
with the username and password. - For running in Cloud Foundry, ensure a Config Server is bounded to the application.
VCAP_SERVICES
will be provided as an environment variables with the credentials to access the Config Server - For connecting to a Config Server via OAuth2 and not deployed to Cloud Foundry, an OAuth2 Client can be created
with
OAuth2(baseURL string, clientId string, secret string, tokenURI string)
package main
import (
"fmt"
"github.com/Piszmog/cloudconfigclient/v2"
"net/http"
)
type File struct {
Example Example `json:"example"`
}
type Example struct {
Field string `json:"field"`
}
func main() {
// To create a Client for a locally running Spring Config Server
configClient, err := cloudconfigclient.New(cloudconfigclient.LocalEnv(&http.Client{}))
// Or
configClient, err = cloudconfigclient.New(cloudconfigclient.Local(&http.Client{}, "http://localhost:8888"))
// or to create a Client for a Spring Config Server using Basic Authentication
configClient, err = cloudconfigclient.New(cloudconfigclient.Basic(&http.Client{}, "username", "password" "http://localhost:8888"))
// or to create a Client for a Spring Config Server in Cloud Foundry
configClient, err = cloudconfigclient.New(cloudconfigclient.DefaultCFService())
// or to create a Client for a Spring Config Server with OAuth2
configClient, err = cloudconfigclient.New(cloudconfigclient.OAuth2("config server uri", "client id", "client secret",
"access token uri"))
// or a combination of local, Cloud Foundry, and OAuth2
configClient, err = cloudconfigclient.New(
cloudconfigclient.Local(&http.Client{}, "http://localhost:8888"),
cloudconfigclient.DefaultCFService(),
cloudconfigclient.OAuth2("config server uri", "client id", "client secret", "access token uri"),
)
if err != nil {
fmt.Println(err)
return
}
var file File
// Retrieves a 'temp1.json' from the Config Server's default branch in directory 'temp' and deserialize to File
err = configClient.GetFile("temp", "temp1.json", &file)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v\n", file)
// Retrieves a 'temp2.txt' from the Config Server's default branch in directory 'temp' as a byte slice ([]byte)
b, err := configClient.GetFileRaw("temp", "temp2.txt")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(b))
// Retrieves the configurations from the Config Server based on the application name and active profiles
config, err := configClient.GetConfiguration("testApp", "dev")
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v", config)
// if we want, we can convert the config to a struct
var configStruct Config
err = config.Unmarshal(&configStruct)
if err != nil {
fmt.Println(err)
}
}
type Config struct {
Field1 string `json:"example"`
Field2 int `json:"field2"`
}
When an application is deployed to Cloud Foundry, services can be bounded to the application. When a service is bounded
to an application, the application will have the necessary connection information provided in the environment
variable VCAP_SERVICES
.
Structure of the VCAP_SERVICES
value
{
"<service type :: e.g. p-config-server>": [
{
"name": "<the service name>",
"instance_name": "<service name>",
"binding_name": "<bounded name of the service>",
"credentials": {
"uri": "<URI of the service :: used to connect to the service>",
"client_secret": "<OAuth2 client secret>",
"client_id": "<OAuth2 client id>",
"access_token_uri": "<OAuth2 token URI>"
},
...
}
]
}
Newer versions of PCF (>=2.6) may have services that use a CredHub Reference to store credential information.
When viewing the Environment Variables of an application via the UI, the credentials may appear as the following
{
"credentials": {
"credhub-ref": "/c/example-service-broker/example-service/faa677f5-25cd-4f1e-8921-14a9d5ab48b8/credentials"
}
}
When the application starts up, the credhub-ref
is replaced with the actual credential values that application will
need to connect to the service.
The Config Server allows the ability to retrieve configurations for an application. Only files that follow a strict naming convention will be loaded,
File Name |
---|
application.{yml/properties} |
application-{profile}.{yml/properties} |
{application name}.{yml/properties} |
{application name}-{profile}.{yml/properties} |
The loaded configurations are in the following JSON format,
{
"name": "<name of application>",
"profiles": "<profiles passed in request>",
"label": "<GIT branch configurations loaded from>",
"version": "<version>",
"state": "<state>",
"propertySources": [
{
"<propertySourceName>": {
"name": "<property source name>",
"source": {
"<source path in .properties format>": "<value>"
}
}
}
]
}
To use the library to retrieve configurations, create a Client
and invoke the
method GetConfiguration(applicationName string, profiles ...string)
. The return will be the struct representation of
the configuration JSON - client.Configuration
.
Spring's Config Server allows two ways to retrieve files from a backing repository.
URL Path |
---|
/<appName>/<profiles>/<directory>/<file>?useDefaultLabel=true |
/<appName>/<profiles>/<branch>/<directory>/<file> |
- When retrieving a file from the Config Server's default branch, the file must not exist at the root of the repository.
- If the
directory
is in thesearchPath
, it does not have to be specified (depending on SCCS version)
The functions available to retrieve resource files
are GetFile(directory string, file string, interfaceType interface{})
and
GetFileFromBranch(branch string, directory string, file string, interfaceType interface{})
. To retrieve the data from
the files, the functions available are GetFileRaw(directory string, file string)
and
GetFileFromBranchRaw(branch string, directory string, file string)
- The
interfaceType
is the object to deserialize the file to
The following is only for certain versions of SCCS v3.x. If a file is not being found by the client, the following may be true.
SCCS v3.x slightly changed how files are retrieved. If the Config Server specified a directory in the searchPaths
, the
path should be excluded from the GetFile(..)
invocation.
For example if common
has been specified in the searchPaths
and the file common/foo.txt
needs to be retrieved,
then the directory
to provide to GetFile(..)
should be ""
(blank).
This differs with SCS v2.x where the directory in searchPaths
did not impact the directory
provided
to GetFile(..)
(e.g. to retrieve file common/foo.txt
,
directory
would be "common"
).