# Manage Application Configuration using GitOPS

This repository hosts configuration files for your service. CI pipelines will keep the remote configuration consistent with this repository and you can subscribe the remote configuration in your service via SDKs. [Design doc](https://docs.google.com/document/d/1rSPoaOfQr12eGSjTEpATWOqpGR-LIrJTMo-iC2c4_-E/edit?n=GitOPS_for_Application_Configuration#)

Branch to environment mappings:

- `dev` branch: dev env, nightly namespace
- `staging` branch: staging env, staging namespace
- `prod` branch: prod env, prod namespace
- `personal/${name}` branch: dev env, `${name}` namespace

## Modify Configuration

Your configuration file should be placed in paths like `${application}/${file}`，e.g. `central/config.yaml`. PR review is required for changes to `dev`, `staging` or `prod` branch.

You can join the "One Config" topic group (search "One Config" on Lark) to receive the configuration change notification in `staging` and `prod` envs. Notifications of other envs are silenced by default.

## Subscribe Configuration

For golang, there is a [viper sdk](https://github.com/tidbcloud/config-service/tree/oneconfig/oneconfig), usage:

```bash
go get github.com/tidbcloud/config-service/oneconfig@v0.0.5
```

Example:

```golang
package main

import (
	"net/http"

	"github.com/spf13/viper"
	ov "github.com/tidbcloud/config-service/oneconfig/viper"
)

func main() {
	// default to the same namespace as current Pod
	viper.AddRemoteProvider(ov.Provider, ov.Endpoint, "oneconfig-central/config.yaml")
	// namespace can be explicitly set, this is useful when you want to reference the config cross namespace or run your service locally
	// v.AddRemoteProvider(ov.Provider, ov.Endpoint, "nightly/oneconfig-central/config.yaml")
	viper.SetConfigType("yaml")
	viper.GetViper().WatchRemoteConfigOnChannel()

	mux := http.NewServeMux()
	mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
		s := viper.GetString("logLevel")
		_, err := writer.Write([]byte(s))
		if err != nil {
			panic(err)
		}
	})
	http.ListenAndServe(":10070", mux)
}
```

The configuration path `oneconfig-central/config.yaml` is consist of `oneconfig-` and the path of your configuration file in this repository (that is, `central/config.yaml` in this example)。

When the remote configuration changed, your service will be notified within a second and the SDK will hot reload the configuration automatically. A log will be printed when hot reload happens:

```
2022/02/09 20:13:03 Config nightly/oneconfig-central changed, new version: 228f305a8c74eccc7dd3903cb806a39c39328899
```

## Troubleshooting

The implementation of the configuration service is `kube-apiserver`, so you can list the configmap in started with `oneconfig-` to troubleshoot problems:

```bash
> kubectl get configmap -n nightly
```
