Skip to content

Commit 185b860

Browse files
committed
feat: Support configuration via flags, env vars and config file
1 parent 36ed826 commit 185b860

26 files changed

+1296
-126
lines changed

Makefile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ else
88
GOBIN=$(shell go env GOBIN)
99
endif
1010

11+
# Set license header files.
12+
LICENSE_HEADER_GO ?= hack/boilerplate.go.txt
13+
1114
# Setting SHELL to bash allows bash commands to be executed by recipes.
1215
# This is a requirement for 'setup-envtest.sh' in the test target.
1316
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
@@ -56,6 +59,12 @@ tidy: ## Run go mod tidy.
5659
test: ## Run tests with coverage. Outputs to combined.cov.
5760
go test -v -coverprofile=coverage.txt -covermode=count ./...
5861

62+
.PHONY: generate
63+
generate: generate-deepcopy fmt ## Generate Go code.
64+
65+
generate-deepcopy: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
66+
$(CONTROLLER_GEN) object:headerFile="$(LICENSE_HEADER_GO)" paths="./..."
67+
5968
##@ Building
6069

6170
.PHONY: build
@@ -72,9 +81,11 @@ $(LOCALBIN): ## Ensure that the directory exists
7281
## Tool Binaries
7382
GOIMPORTS ?= $(LOCALBIN)/goimports
7483
GOLANGCI_LINT ?= $(LOCALBIN)/golangci-lint@$(GOLANGCILINT_VERSION)
84+
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen@$(CONTROLLER_TOOLS_VERSION)
7585

7686
## Tool Versions
7787
GOLANGCILINT_VERSION ?= v1.61.0
88+
CONTROLLER_TOOLS_VERSION ?= v0.16.1
7889

7990
.PHONY: goimports
8091
goimports: $(GOIMPORTS) ## Download goimports locally if necessary.
@@ -87,3 +98,9 @@ golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
8798
$(GOLANGCI_LINT):
8899
@[ -f $(GOLANGCI_LINT) ] || curl -sSfL $(GOLANGCILINT_INSTALL_SCRIPT) | sh -s $(GOLANGCILINT_VERSION)
89100
mv $(LOCALBIN)/golangci-lint $(LOCALBIN)/golangci-lint@$(GOLANGCILINT_VERSION)
101+
102+
.PHONY: controller-gen
103+
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
104+
$(CONTROLLER_GEN):
105+
GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
106+
mv $(LOCALBIN)/controller-gen $(LOCALBIN)/controller-gen@$(CONTROLLER_TOOLS_VERSION)

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,17 @@ $ docker run --rm irvinlim/apple-health-ingester --help
6565

6666
## Configuration
6767

68-
### Command-line Flags
68+
### Specifying Configuration
69+
70+
We use [spf13/viper](https://github.com/spf13/viper) for configuration, and therefore configuration can be specified in the following places, in order of precedence from highest to lowest:
71+
72+
- Command-line flags
73+
- Environment variables
74+
- Config file
75+
76+
See the following sections for available configuration keys for each of the available configuration methods.
77+
78+
#### Command-line Flags
6979

7080
```sh
7181
$ ./build/ingester --help
@@ -88,6 +98,12 @@ Usage of ./build/ingester:
8898
--log string Log level to use. (default "info")
8999
```
90100
101+
#### Environment Variables
102+
103+
Any environment variables
104+
105+
#### Config Files
106+
91107
### Global Configuration
92108
93109
#### `http.listenAddr`

apis/config/v1/appconfig_types.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package v1
2+
3+
// Config contains the application configuration.
4+
//
5+
// Configuration be loaded from configuration file, or possibly overridden from
6+
// environment variables if the `env` struct tag is specified.
7+
type Config struct {
8+
// Configuration for the ingester's HTTP server.
9+
HttpServer HttpServerConfig `json:"httpServer"`
10+
// Configuration for individual ingester backends.
11+
Backends BackendsConfig `json:"backends"`
12+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package v1
2+
3+
type BackendsConfig struct {
4+
// If specified, enables the LocalFile backend.
5+
LocalFile LocalFileBackendConfig `json:"localFile,omitempty"`
6+
// If specified, enables the InfluxDB backend.
7+
InfluxDB InfluxdbBackendConfig `json:"influxdb,omitempty"`
8+
}
9+
10+
type LocalFileBackendConfig struct {
11+
// Whether the LocalFile backend is enabled.
12+
// Defaults to false.
13+
Enabled bool `json:"enabled"`
14+
// Output path to write metrics, with one metric per file. Required.
15+
// All data will be aggregated by timestamp.
16+
// Any existing data will be merged together.
17+
MetricsPath string `json:"metricsPath"`
18+
}
19+
20+
type InfluxdbBackendConfig struct {
21+
// Whether the InfluxDB backend is enabled.
22+
// Defaults to false.
23+
Enabled bool `json:"enabled"`
24+
// The URL to the InfluxDB server.
25+
ServerURL string `json:"serverURL" env:"INFLUXDB_SERVER_URL"`
26+
// If true, skips TLS verification of the certificate chain and host name for
27+
// the InfluxDB server.
28+
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty" env:"INFLUXDB_INSECURE_SKIP_VERIFY"`
29+
// Auth token to connect to InfluxDB.
30+
AuthToken string `json:"authToken,omitempty" env:"INFLUXDB_AUTH_TOKEN"`
31+
// InfluxDB organization name.
32+
OrgName string `json:"orgName" env:"INFLUXDB_ORG_NAME"`
33+
// Configuration for InfluxDB bucket names for various data points.
34+
BucketNames InfluxdbBucketNamesConfig `json:"bucketNames"`
35+
// Additional tags to add to InfluxDB for every single request, in key=value format.
36+
StaticTags map[string]string `json:"staticTags,omitempty"`
37+
}
38+
39+
type InfluxdbBucketNamesConfig struct {
40+
// InfluxDB bucket name for metrics.
41+
Metrics string `json:"metrics" env:"INFLUXDB_METRICS_BUCKET"`
42+
// InfluxDB bucket name for workouts.
43+
Workouts string `json:"workouts" env:"INFLUXDB_WORKOUTS_BUCKET"`
44+
}

apis/config/v1/doc.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Package v1 contains API Schema definitions for the config v1 API group
2+
// +kubebuilder:object:generate=true
3+
package v1

apis/config/v1/httpconfig_types.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package v1
2+
3+
type HttpServerConfig struct {
4+
// The address to listen on. Required.
5+
// Must be specified as one of the following:
6+
// - "<ip>:<port>": Binds to the IP address on the given interface only
7+
// - ":<port>": Binds to all interfaces
8+
ListenAddr string `json:"listenAddr" env:"LISTEN_ADDR"`
9+
// Specify TLS configuration for the HTTP server.
10+
// Defaults to running without TLS.
11+
TLS HttpTLSConfig `json:"tls"`
12+
// Specify authentication for the HTTP server.
13+
// Defaults to no authentication.
14+
Auth HttpAuthConfig `json:"auth,omitempty"`
15+
}
16+
17+
type HttpTLSConfig struct {
18+
// Whether TLS is enabled for the HTTP server.
19+
// If enabled, certificate and key files must also be specified.
20+
Enabled bool `json:"enabled" env:"TLS_ENABLED"`
21+
// The path to the TLS certificate to serve.
22+
// At most one of CertFile or CertData can be specified.
23+
CertFile string `json:"certFile,omitempty" env:"TLS_CERT_FILE"`
24+
// The TLS certificate data to serve.
25+
// At most one of CertFile or CertData can be specified.
26+
CertData []byte `json:"certificateData,omitempty"`
27+
// The path to the TLS private key.
28+
KeyFile string `json:"keyFile,omitempty" env:"TLS_KEY_FILE"`
29+
// The TLS private key.
30+
// At most one of KeyFile or KeyData can be specified.
31+
KeyData []byte `json:"keyData,omitempty"`
32+
}
33+
34+
type HttpAuthConfig struct {
35+
// Optionally specify a fixed Bearer token that can be used to authenticate incoming requests.
36+
AuthorizationToken string `json:"authorizationToken,omitempty" env:"AUTH_TOKEN"`
37+
}

apis/config/v1/zz_generated.deepcopy.go

Lines changed: 149 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/ingester/backends.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/pkg/errors"
77

8+
configv1 "github.com/irvinlim/apple-health-ingester/apis/config/v1"
89
"github.com/irvinlim/apple-health-ingester/pkg/backends/influxdb"
910
"github.com/irvinlim/apple-health-ingester/pkg/backends/localfile"
1011
"github.com/irvinlim/apple-health-ingester/pkg/ingester"
@@ -15,27 +16,35 @@ const (
1516
)
1617

1718
// RegisterDebugBackend registers the Debug backend.
18-
func RegisterDebugBackend(ingester *ingester.Ingester, mux *http.ServeMux) error {
19-
if !enableLocalFile {
19+
func RegisterDebugBackend(cfg *configv1.Config, ingester *ingester.Ingester, mux *http.ServeMux) error {
20+
if cfg == nil {
21+
cfg = &configv1.Config{}
22+
}
23+
backendCfg := cfg.Backends.LocalFile.DeepCopy()
24+
if !backendCfg.Enabled {
2025
return nil
2126
}
22-
backend, err := localfile.NewBackend()
27+
backend, err := localfile.NewBackend(backendCfg)
2328
if err != nil {
2429
return err
2530
}
2631
return RegisterBackend(backend, ingester, mux, pathPrefix+"/localfile/ingest")
2732
}
2833

2934
// RegisterInfluxDBBackend registers the InfluxDB backend.
30-
func RegisterInfluxDBBackend(ingester *ingester.Ingester, mux *http.ServeMux) error {
31-
if !enableInfluxDB {
35+
func RegisterInfluxDBBackend(cfg *configv1.Config, ingester *ingester.Ingester, mux *http.ServeMux) error {
36+
if cfg == nil {
37+
cfg = &configv1.Config{}
38+
}
39+
backendCfg := cfg.Backends.InfluxDB.DeepCopy()
40+
if !backendCfg.Enabled {
3241
return nil
3342
}
34-
client, err := influxdb.NewClient()
43+
client, err := influxdb.NewClient(backendCfg)
3544
if err != nil {
3645
return errors.Wrapf(err, "cannot initialize client")
3746
}
38-
backend, err := influxdb.NewBackend(client)
47+
backend, err := influxdb.NewBackend(backendCfg, client)
3948
if err != nil {
4049
return err
4150
}

0 commit comments

Comments
 (0)