-
Notifications
You must be signed in to change notification settings - Fork 25
/
config.go
165 lines (145 loc) · 4.83 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// +kubebuilder:validation:Optional
package config
import (
"fmt"
"os"
"path"
"strings"
guuid "github.com/google/uuid"
"github.com/spf13/pflag"
"go.uber.org/fx"
"github.com/fluxninja/aperture/pkg/filesystem"
"github.com/fluxninja/aperture/pkg/info"
"github.com/fluxninja/aperture/pkg/panichandler"
)
var (
// DefaultAssetsDirectory is path to default assets directory.
DefaultAssetsDirectory = path.Join("/", "etc", info.Prefix, info.Service)
// DefaultArtifactsDirectory is path to default artifacts directory.
DefaultArtifactsDirectory = path.Join("/", "var", "lib", info.Prefix, info.Service)
// DefaultLogDirectory is path to default log directory.
DefaultLogDirectory = path.Join("/", "var", "log", info.Prefix, info.Service)
// DefaultTempBase is path to default temporary base.
DefaultTempBase = path.Join(os.TempDir(), info.Prefix, info.Service)
// DefaultTempDirectory is path to default temporary directory.
DefaultTempDirectory = path.Join(DefaultTempBase, guuid.NewString())
// DefaultConfigDirectory is path to default config directory.
DefaultConfigDirectory = path.Join(DefaultAssetsDirectory, "config")
// EnvPrefix is default environment prefix.
EnvPrefix = strings.ReplaceAll(strings.ToUpper(info.Service), "-", "_") + "_"
)
const (
// DefaultConfigFileExt is default config file extension.
DefaultConfigFileExt = ".yaml"
// DefaultKoanfDelim is default koanf delimiter.
DefaultKoanfDelim = "."
)
// ConfigPath stores the path to config directory for other modules
// to look for their config files.
type ConfigPath struct {
Path string
}
// ModuleConfig holds configuration for the config module.
type ModuleConfig struct {
MergeConfig map[string]interface{}
UnknownFlags bool
ExitOnHelp bool
}
// Module is a fx Module that invokes CreateGlobalPanicHandlerRegistry and provides an annotated
// instance of CommandLine and FileUnmarshaller.
func (config ModuleConfig) Module() fx.Option {
return fx.Options(
fx.Invoke(
panichandler.RegisterPanicHandlers,
),
fx.Provide(CommandLineConfig{UnknownFlags: config.UnknownFlags, ExitOnHelp: config.ExitOnHelp}.NewCommandLine),
FileUnmarshallerConstructor{
Name: info.Service,
PathFlag: ConfigPathFlag,
Path: DefaultConfigDirectory,
MergeConfig: config.MergeConfig,
NoErrOnFile: true,
EnableEnv: true,
}.Annotate(),
)
}
// Annotate creates an annotated instance of FileUnmarshaller.
func (constructor FileUnmarshallerConstructor) Annotate() fx.Option {
var returnName string
if constructor.Name == info.Service {
returnName = ``
} else {
returnName = NameTag(constructor.Name)
}
return fx.Options(
fx.Provide(
fx.Annotate(
constructor.NewFileUnmarshaller,
fx.ParamTags(`optional:"true"`),
fx.ResultTags(returnName, returnName),
),
),
)
}
// NameTag returns the name tag for the given name in the manner of fmt.Sprintf.
func NameTag(name string) string {
return fmt.Sprintf("name:\"%s\"", name)
}
// GroupTag returns the group tag for the given group name in the manner of fmt.Sprintf.
func GroupTag(group string) string {
return fmt.Sprintf("group:\"%s\"", group)
}
// FileUnmarshallerConstructor holds fields to create an annotated instance of FileUnmarshaller.
type FileUnmarshallerConstructor struct {
// Optional Merge Config
MergeConfig map[string]interface{}
// Config Name -- config file name without the extension -- it's also the annotated name of koanf instance
Name string
// Command line flag for reading file path
PathFlag string
// If flag is empty or not provided on CL, fallback to explicit path
Path string
// Extension of file (exact) - empty = yaml
FileExt string
// Enable AutomaticEnv
EnableEnv bool
// NoErrOnFile
NoErrOnFile bool
}
// NewFileUnmarshaller creates a new instance of FileUnmarshaller and ConfigPath that unmarshals the config file.
func (constructor FileUnmarshallerConstructor) NewFileUnmarshaller(flagSet *pflag.FlagSet) (Unmarshaller, ConfigPath, error) {
var configPath string
var err error
if constructor.PathFlag != "" {
configPath, err = flagSet.GetString(constructor.PathFlag)
if err != nil {
return nil, ConfigPath{}, err
}
}
if configPath == "" {
if constructor.Path == "" {
configPath = DefaultConfigDirectory
} else {
configPath = constructor.Path
}
}
if constructor.FileExt == "" {
constructor.FileExt = DefaultConfigFileExt
}
fileInfo := filesystem.NewFileInfo(configPath, constructor.Name, constructor.FileExt)
bytes, err := fileInfo.ReadAsByteBufferFromFile()
if err != nil {
if !constructor.NoErrOnFile {
return nil, ConfigPath{}, err
}
}
unmarshaller, err := KoanfUnmarshallerConstructor{
FlagSet: flagSet,
EnableEnv: constructor.EnableEnv,
MergeConfig: constructor.MergeConfig,
}.NewKoanfUnmarshaller(bytes)
if err != nil {
return nil, ConfigPath{}, err
}
return unmarshaller, ConfigPath{Path: configPath}, nil
}