-
Notifications
You must be signed in to change notification settings - Fork 1
/
AppConfig.go
143 lines (125 loc) · 3.48 KB
/
AppConfig.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
package lib
import (
"fmt"
"os"
"bufio"
"github.com/go-chat-bot/bot/irc"
"github.com/mbaynton/SimplePuppetProvisioner/lib/genericexec"
"github.com/mbaynton/SimplePuppetProvisioner/lib/puppetconfig"
"github.com/spf13/viper"
"io"
"io/ioutil"
"log"
"runtime"
)
type AppConfig struct {
BindAddress string
LogFile string
HttpAuth *HttpAuthConfig
PuppetExecutable string
PuppetConfDir string
PuppetConfig *puppetconfig.PuppetConfig
GenericExecTasks []*genericexec.GenericExecConfig
GithubWebhooks *WebhooksConfig
Notifications []*NotificationsConfig
Log *log.Logger
logBuffer *bufio.Writer
}
type HttpAuthConfig struct {
Type string
Realm string
DbFile string
}
type NotificationsConfig struct {
Type string
IrcConfig *irc.Config
SlackToken *string
}
func LoadTheConfig(configName string, configPaths []string) AppConfig {
if len(configPaths) == 0 {
viper.SetConfigFile(configName)
} else {
viper.SetConfigName(configName) // So spp.conf.json, spp.conf.yml, ...
for _, path := range configPaths {
viper.AddConfigPath(path)
}
}
// Can we find a properly formatted file?
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Configuration file error: %s\n", err))
}
// Does the properly formatted file have the needed data?
var C AppConfig
err = viper.Unmarshal(&C)
if err != nil {
panic(fmt.Errorf("Configuration file error: %s\n", err))
}
C.setDefaults()
C.establishLogger()
configLoader := puppetconfig.NewPuppetConfigParser(C.Log)
puppetConfig := configLoader.LoadPuppetConfig(C.PuppetExecutable, C.PuppetConfDir)
if puppetConfig == nil {
C.Log.Println("Invalid puppet installation, cannot proceed.")
os.Exit(1)
}
C.PuppetConfig = puppetConfig
return C
}
func (ctx *AppConfig) setDefaults() {
if ctx.HttpAuth != nil && ctx.HttpAuth.Realm == "" {
hostname, err := os.Hostname()
if err == nil {
ctx.HttpAuth.Realm = hostname
} else {
ctx.HttpAuth.Realm = "[realm not configured]"
}
}
if ctx.PuppetExecutable == "" {
ctx.PuppetExecutable = "/opt/puppetlabs/bin/puppet"
}
if ctx.PuppetConfDir == "" {
if runtime.GOOS == "windows" {
ctx.PuppetConfDir = "C:\\ProgramData\\PuppetLabs\\puppet\\etc"
} else {
ctx.PuppetConfDir = "/etc/puppetlabs/puppet"
}
}
if ctx.GithubWebhooks == nil {
ctx.GithubWebhooks = &WebhooksConfig{
EnableStandardR10kListener: false,
Listeners: make([]ExecListener, 0),
}
}
}
func (ctx *AppConfig) establishLogger() {
ctx.Log = log.New(os.Stdout, "", log.LstdFlags)
}
func (ctx *AppConfig) MoveLoggingToFile() {
var logOutput io.Writer
var newLocation string
if ctx.LogFile != "" {
fileOutput, err := os.OpenFile(ctx.LogFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0640)
if err != nil {
fmt.Errorf("Unable to create or open logfile: %s\n", err.Error())
os.Exit(1)
}
// Using a buffer seems like it might theoretically offer performance benefits, but would require a synchronized goroutine to flush it regularly.
//ctx.logBuffer = bufio.NewWriter(fileOutput)
//logOutput = ctx.logBuffer
logOutput = fileOutput
newLocation = ctx.LogFile
} else {
// A null writer
logOutput = ioutil.Discard
newLocation = "a black hole (log location not configured.)"
}
ctx.Log.Printf("This log is moving to %s", newLocation)
ctx.Log.SetOutput(logOutput)
ctx.Log.Printf("--- continuation of logging that began on stdout ---")
}
func (ctx *AppConfig) FlushLog() {
if ctx.logBuffer != nil {
ctx.logBuffer.Flush()
}
}