forked from mendersoftware/mender
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconfig.go
198 lines (171 loc) · 5.85 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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// Copyright 2018 Northern.tech AS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"encoding/json"
"io/ioutil"
"os"
"strings"
"github.com/mendersoftware/log"
"github.com/mendersoftware/mender/client"
"github.com/pkg/errors"
)
type menderConfig struct {
// ClientProtocol "https"
ClientProtocol string
// Path to the public key used to verify signed updates
ArtifactVerifyKey string
// HTTPS client parameters
HttpsClient struct {
Certificate string
Key string
SkipVerify bool
}
// Rootfs device path
RootfsPartA string
RootfsPartB string
// Poll interval for checking for new updates
UpdatePollIntervalSeconds int
// Poll interval for periodically sending inventory data
InventoryPollIntervalSeconds int
// Global retry polling max interval for fetching update, authorize wait and update status
RetryPollIntervalSeconds int
// State script parameters
StateScriptTimeoutSeconds int
StateScriptRetryTimeoutSeconds int
// Poll interval for checking for update (check-update)
StateScriptRetryIntervalSeconds int
// Path to server SSL certificate
ServerCertificate string
// Server URL (For single server conf)
ServerURL string
// Path to deployment log file
UpdateLogPath string
// Server JWT TenantToken
TenantToken string
// List of available servers, to which client can fall over
Servers []client.MenderServer
}
// loadConfig parses the mender configuration json-files
// (/etc/mender/mender.conf and /var/lib/mender/mender.conf) and loads the
// values into the menderConfig structure defining high level client
// configurations.
func loadConfig(mainConfigFile string, fallbackConfigFile string) (*menderConfig, error) {
// Load fallback configuration first, then main configuration.
// It is OK if either file does not exist, so long as the other one does exist.
// It is also OK if both files exist.
// Because the main configuration is loaded last, its option values
// override those from the fallback file, for options present in both files.
var filesLoadedCount int
var config menderConfig
if loadErr := loadConfigFile(fallbackConfigFile, &config, &filesLoadedCount); loadErr != nil {
return nil, loadErr
}
if loadErr := loadConfigFile(mainConfigFile, &config, &filesLoadedCount); loadErr != nil {
return nil, loadErr
}
if filesLoadedCount == 0 {
return nil, errors.New("could not find either configuration file")
}
if config.Servers == nil {
if config.ServerURL == "" {
log.Warn("No server URL(s) specified in mender configuration.")
}
config.Servers = make([]client.MenderServer, 1)
config.Servers[0].ServerURL = config.ServerURL
} else if config.ServerURL != "" {
log.Error("In mender.conf: don't specify both Servers field " +
"AND the corresponding fields in base structure (i.e. " +
"ServerURL). The first server on the list on the" +
"list overwrites these fields.")
return nil, errors.New("Both Servers AND ServerURL given in " +
"mender.conf")
}
for i := 0; i < len(config.Servers); i++ {
// Trim possible '/' suffix, which is added back in URL path
if strings.HasSuffix(config.Servers[i].ServerURL, "/") {
config.Servers[i].ServerURL =
strings.TrimSuffix(
config.Servers[i].ServerURL, "/")
}
if config.Servers[i].ServerURL == "" {
log.Warnf("Server entry %d has no associated server URL.")
}
}
log.Debugf("Merged configuration = %#v", config)
return &config, nil
}
func loadConfigFile(configFile string, config *menderConfig, filesLoadedCount *int) error {
// Do not treat a single config file not existing as an error here.
// It is up to the caller to fail when both config files don't exist.
if _, err := os.Stat(configFile); os.IsNotExist(err) {
log.Info("Configuration file does not exist: ", configFile)
return nil
}
if err := readConfigFile(&config, configFile); err != nil {
log.Errorf("Error loading configuration from file: %s (%s)", configFile, err.Error())
return err
}
(*filesLoadedCount)++
log.Info("Loaded configuration file: ", configFile)
return nil
}
func readConfigFile(config interface{}, fileName string) error {
// Reads mender configuration (JSON) file.
log.Debug("Reading Mender configuration from file " + fileName)
conf, err := ioutil.ReadFile(fileName)
if err != nil {
return err
}
if err := json.Unmarshal(conf, &config); err != nil {
switch err.(type) {
case *json.SyntaxError:
return errors.New("Error parsing mender configuration file: " + err.Error())
}
return errors.New("Error parsing config file: " + err.Error())
}
return nil
}
func (c menderConfig) GetHttpConfig() client.Config {
return client.Config{
ServerCert: c.ServerCertificate,
IsHttps: c.ClientProtocol == "https",
NoVerify: c.HttpsClient.SkipVerify,
}
}
func (c menderConfig) GetDeviceConfig() deviceConfig {
return deviceConfig{
rootfsPartA: c.RootfsPartA,
rootfsPartB: c.RootfsPartB,
}
}
func (c menderConfig) GetDeploymentLogLocation() string {
return c.UpdateLogPath
}
// GetTenantToken returns a default tenant-token if
// no custom token is set in local.conf
func (c menderConfig) GetTenantToken() []byte {
return []byte(c.TenantToken)
}
func (c menderConfig) GetVerificationKey() []byte {
if c.ArtifactVerifyKey == "" {
return nil
}
key, err := ioutil.ReadFile(c.ArtifactVerifyKey)
if err != nil {
log.Info("config: error reading artifact verify key")
return nil
}
return key
}