• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender / 1006302423

15 Sep 2023 12:56PM UTC coverage: 78.737% (+0.3%) from 78.482%
1006302423

push

gitlab-ci

oleorhagen
feat(daemon): Add state script support

Ticket: MEN-6637
Changelog: None

Signed-off-by: Ole Petter <ole.orhagen@northern.tech>

194 of 194 new or added lines in 4 files covered. (100.0%)

5984 of 7600 relevant lines covered (78.74%)

1109.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.96
/common/config_parser/config_parser.cpp
1
// Copyright 2023 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
#include <common/config_parser.hpp>
16
#include <string>
17
#include <vector>
18
#include <algorithm>
19
#include <common/json.hpp>
20

21
namespace mender {
22
namespace common {
23
namespace config_parser {
24

25
using namespace std;
26
namespace json = mender::common::json;
27

28
const ConfigParserErrorCategoryClass ConfigParserErrorCategory;
29

30
const char *ConfigParserErrorCategoryClass::name() const noexcept {
×
31
        return "ConfigParserErrorCategory";
×
32
}
33

34
string ConfigParserErrorCategoryClass::message(int code) const {
×
35
        switch (code) {
×
36
        case NoError:
×
37
                return "Success";
×
38
        case ValidationError:
×
39
                return "Validation error";
×
40
        default:
×
41
                return "Unknown";
×
42
        }
43
}
44

45
error::Error MakeError(ConfigParserErrorCode code, const string &msg) {
3✔
46
        return error::Error(error_condition(code, ConfigParserErrorCategory), msg);
6✔
47
}
48

49
ExpectedBool MenderConfigFromFile::ValidateArtifactKeyCondition() const {
3✔
50
        if (artifact_verify_key.size() != 0) {
3✔
51
                if (artifact_verify_keys.size() != 0) {
2✔
52
                        auto err = MakeError(
53
                                ConfigParserErrorCode::ValidationError,
54
                                "Both 'ArtifactVerifyKey' and 'ArtifactVerifyKeys' are set");
2✔
55
                        return expected::unexpected(err);
2✔
56
                }
57
        }
58
        return true;
2✔
59
}
60

61
ExpectedBool MenderConfigFromFile::ValidateServerConfig() const {
3✔
62
        if (server_url.size() != 0 && servers.size() != 0) {
3✔
63
                auto err = MakeError(
64
                        ConfigParserErrorCode::ValidationError,
65
                        "Both 'Servers' AND 'ServerURL given in the configuration. Please set only one of these fields");
2✔
66
                return expected::unexpected(err);
2✔
67
        }
68

69
        if (servers.size() == 0) {
2✔
70
                if (server_url.size() == 0) {
1✔
71
                        // TODO - Log warning
72
                }
73
        }
74
        return true;
2✔
75
}
76

77
ExpectedBool MenderConfigFromFile::LoadFile(const string &path) {
203✔
78
        const json::ExpectedJson e_cfg_json = json::LoadFromFile(path);
406✔
79
        if (!e_cfg_json) {
203✔
80
                auto err = e_cfg_json.error();
191✔
81
                return expected::unexpected(err);
382✔
82
        }
83

84
        bool applied = false;
12✔
85

86
        /* Deal with plain string values first */
87
        const json::Json cfg_json = e_cfg_json.value();
24✔
88
        json::ExpectedJson e_cfg_value = cfg_json.Get("ArtifactVerifyKey");
24✔
89
        if (e_cfg_value) {
12✔
90
                const json::Json value_json = e_cfg_value.value();
20✔
91
                const json::ExpectedString e_cfg_string = value_json.GetString();
20✔
92
                if (e_cfg_string) {
10✔
93
                        this->artifact_verify_key = e_cfg_string.value();
10✔
94
                        applied = true;
10✔
95
                }
96
        }
97

98
        e_cfg_value = cfg_json.Get("RootfsPartA");
12✔
99
        if (e_cfg_value) {
12✔
100
                const json::Json value_json = e_cfg_value.value();
16✔
101
                const json::ExpectedString e_cfg_string = value_json.GetString();
16✔
102
                if (e_cfg_string) {
8✔
103
                        this->rootfs_part_A = e_cfg_string.value();
7✔
104
                        applied = true;
7✔
105
                }
106
        }
107

108
        e_cfg_value = cfg_json.Get("RootfsPartB");
12✔
109
        if (e_cfg_value) {
12✔
110
                const json::Json value_json = e_cfg_value.value();
20✔
111
                const json::ExpectedString e_cfg_string = value_json.GetString();
20✔
112
                if (e_cfg_string) {
10✔
113
                        this->rootfs_part_B = e_cfg_string.value();
10✔
114
                        applied = true;
10✔
115
                }
116
        }
117

118
        e_cfg_value = cfg_json.Get("BootUtilitiesSetActivePart");
12✔
119
        if (e_cfg_value) {
12✔
120
                const json::Json value_json = e_cfg_value.value();
20✔
121
                const json::ExpectedString e_cfg_string = value_json.GetString();
20✔
122
                if (e_cfg_string) {
10✔
123
                        this->boot_utilities_set_active_part = e_cfg_string.value();
10✔
124
                        applied = true;
10✔
125
                }
126
        }
127

128
        e_cfg_value = cfg_json.Get("BootUtilitiesGetNextActivePart");
12✔
129
        if (e_cfg_value) {
12✔
130
                const json::Json value_json = e_cfg_value.value();
14✔
131
                const json::ExpectedString e_cfg_string = value_json.GetString();
14✔
132
                if (e_cfg_string) {
7✔
133
                        this->boot_utilities_get_next_active_part = e_cfg_string.value();
7✔
134
                        applied = true;
7✔
135
                }
136
        }
137

138
        e_cfg_value = cfg_json.Get("DeviceTypeFile");
12✔
139
        if (e_cfg_value) {
12✔
140
                const json::Json value_json = e_cfg_value.value();
20✔
141
                const json::ExpectedString e_cfg_string = value_json.GetString();
20✔
142
                if (e_cfg_string) {
10✔
143
                        this->device_type_file = e_cfg_string.value();
10✔
144
                        applied = true;
10✔
145
                }
146
        }
147

148
        e_cfg_value = cfg_json.Get("ServerCertificate");
12✔
149
        if (e_cfg_value) {
12✔
150
                const json::Json value_json = e_cfg_value.value();
14✔
151
                const json::ExpectedString e_cfg_string = value_json.GetString();
14✔
152
                if (e_cfg_string) {
7✔
153
                        this->server_certificate = e_cfg_string.value();
7✔
154
                        applied = true;
7✔
155
                }
156
        }
157

158
        e_cfg_value = cfg_json.Get("ServerURL");
12✔
159
        if (e_cfg_value) {
12✔
160
                const json::Json value_json = e_cfg_value.value();
20✔
161
                const json::ExpectedString e_cfg_string = value_json.GetString();
20✔
162
                if (e_cfg_string) {
10✔
163
                        this->server_url = e_cfg_string.value();
10✔
164
                        applied = true;
10✔
165
                }
166
        }
167

168
        e_cfg_value = cfg_json.Get("UpdateLogPath");
12✔
169
        if (e_cfg_value) {
12✔
170
                const json::Json value_json = e_cfg_value.value();
14✔
171
                const json::ExpectedString e_cfg_string = value_json.GetString();
14✔
172
                if (e_cfg_string) {
7✔
173
                        this->update_log_path = e_cfg_string.value();
7✔
174
                        applied = true;
7✔
175
                }
176
        }
177

178
        e_cfg_value = cfg_json.Get("TenantToken");
12✔
179
        if (e_cfg_value) {
12✔
180
                const json::Json value_json = e_cfg_value.value();
14✔
181
                const json::ExpectedString e_cfg_string = value_json.GetString();
14✔
182
                if (e_cfg_string) {
7✔
183
                        this->tenant_token = e_cfg_string.value();
7✔
184
                        applied = true;
7✔
185
                }
186
        }
187

188
        e_cfg_value = cfg_json.Get("DaemonLogLevel");
12✔
189
        if (e_cfg_value) {
12✔
190
                const json::Json value_json = e_cfg_value.value();
14✔
191
                const json::ExpectedString e_cfg_string = value_json.GetString();
14✔
192
                if (e_cfg_string) {
7✔
193
                        this->daemon_log_level = e_cfg_string.value();
7✔
194
                        applied = true;
7✔
195
                }
196
        }
197

198
        /* Boolean values now */
199
        e_cfg_value = cfg_json.Get("SkipVerify");
12✔
200
        if (e_cfg_value) {
12✔
201
                const json::Json value_json = e_cfg_value.value();
18✔
202
                const json::ExpectedBool e_cfg_bool = value_json.GetBool();
18✔
203
                if (e_cfg_bool) {
9✔
204
                        this->skip_verify = e_cfg_bool.value();
9✔
205
                        applied = true;
9✔
206
                }
207
        }
208

209
        e_cfg_value = cfg_json.Get("DBus");
12✔
210
        if (e_cfg_value) {
12✔
211
                const json::Json value_json = e_cfg_value.value();
14✔
212
                const json::ExpectedJson e_cfg_subval = value_json.Get("Enabled");
14✔
213
                if (e_cfg_subval) {
7✔
214
                        const json::Json subval_json = e_cfg_subval.value();
14✔
215
                        const json::ExpectedBool e_cfg_bool = subval_json.GetBool();
14✔
216
                        if (e_cfg_bool) {
7✔
217
                                this->dbus_enabled = e_cfg_bool.value();
7✔
218
                                applied = true;
7✔
219
                        }
220
                }
221
        }
222

223
        /* Integer values */
224
        e_cfg_value = cfg_json.Get("UpdateControlMapExpirationTimeSeconds");
12✔
225
        if (e_cfg_value) {
12✔
226
                const json::Json value_json = e_cfg_value.value();
14✔
227
                const auto e_cfg_int = value_json.GetInt();
14✔
228
                if (e_cfg_int) {
7✔
229
                        this->update_control_map_expiration_time_seconds = e_cfg_int.value();
7✔
230
                        applied = true;
7✔
231
                }
232
        }
233

234
        e_cfg_value = cfg_json.Get("UpdateControlMapBootExpirationTimeSeconds");
12✔
235
        if (e_cfg_value) {
12✔
236
                const json::Json value_json = e_cfg_value.value();
14✔
237
                const auto e_cfg_int = value_json.GetInt();
14✔
238
                if (e_cfg_int) {
7✔
239
                        this->update_control_map_boot_expiration_time_seconds = e_cfg_int.value();
7✔
240
                        applied = true;
7✔
241
                }
242
        }
243

244
        e_cfg_value = cfg_json.Get("UpdatePollIntervalSeconds");
12✔
245
        if (e_cfg_value) {
12✔
246
                const json::Json value_json = e_cfg_value.value();
14✔
247
                const auto e_cfg_int = value_json.GetInt();
14✔
248
                if (e_cfg_int) {
7✔
249
                        this->update_poll_interval_seconds = e_cfg_int.value();
7✔
250
                        applied = true;
7✔
251
                }
252
        }
253

254
        e_cfg_value = cfg_json.Get("InventoryPollIntervalSeconds");
12✔
255
        if (e_cfg_value) {
12✔
256
                const json::Json value_json = e_cfg_value.value();
14✔
257
                const auto e_cfg_int = value_json.GetInt();
14✔
258
                if (e_cfg_int) {
7✔
259
                        this->inventory_poll_interval_seconds = e_cfg_int.value();
7✔
260
                        applied = true;
7✔
261
                }
262
        }
263

264
        e_cfg_value = cfg_json.Get("RetryPollIntervalSeconds");
12✔
265
        if (e_cfg_value) {
12✔
266
                const json::Json value_json = e_cfg_value.value();
14✔
267
                const auto e_cfg_int = value_json.GetInt();
14✔
268
                if (e_cfg_int) {
7✔
269
                        this->retry_poll_interval_seconds = e_cfg_int.value();
7✔
270
                        applied = true;
7✔
271
                }
272
        }
273

274
        e_cfg_value = cfg_json.Get("RetryPollCount");
12✔
275
        if (e_cfg_value) {
12✔
276
                const json::Json value_json = e_cfg_value.value();
14✔
277
                const auto e_cfg_int = value_json.GetInt();
14✔
278
                if (e_cfg_int) {
7✔
279
                        this->retry_poll_count = e_cfg_int.value();
7✔
280
                        applied = true;
7✔
281
                }
282
        }
283

284
        e_cfg_value = cfg_json.Get("StateScriptTimeoutSeconds");
12✔
285
        if (e_cfg_value) {
12✔
286
                const json::Json value_json = e_cfg_value.value();
14✔
287
                const auto e_cfg_int = value_json.GetInt();
14✔
288
                if (e_cfg_int) {
7✔
289
                        this->state_script_timeout_seconds = e_cfg_int.value();
7✔
290
                        applied = true;
7✔
291
                }
292
        }
293

294
        e_cfg_value = cfg_json.Get("StateScriptRetryTimeoutSeconds");
12✔
295
        if (e_cfg_value) {
12✔
296
                const json::Json value_json = e_cfg_value.value();
14✔
297
                const auto e_cfg_int = value_json.GetInt();
14✔
298
                if (e_cfg_int) {
7✔
299
                        this->state_script_retry_timeout_seconds = e_cfg_int.value();
7✔
300
                        applied = true;
7✔
301
                }
302
        }
303

304
        e_cfg_value = cfg_json.Get("StateScriptRetryIntervalSeconds");
12✔
305
        if (e_cfg_value) {
12✔
306
                const json::Json value_json = e_cfg_value.value();
14✔
307
                const auto e_cfg_int = value_json.GetInt();
14✔
308
                if (e_cfg_int) {
7✔
309
                        this->state_script_retry_interval_seconds = e_cfg_int.value();
7✔
310
                        applied = true;
7✔
311
                }
312
        }
313

314
        e_cfg_value = cfg_json.Get("ModuleTimeoutSeconds");
12✔
315
        if (e_cfg_value) {
12✔
316
                const json::Json value_json = e_cfg_value.value();
14✔
317
                const auto e_cfg_int = value_json.GetInt();
14✔
318
                if (e_cfg_int) {
7✔
319
                        this->module_timeout_seconds = e_cfg_int.value();
7✔
320
                        applied = true;
7✔
321
                }
322
        }
323

324
        /* Vectors/arrays now */
325
        e_cfg_value = cfg_json.Get("ArtifactVerifyKeys");
12✔
326
        if (e_cfg_value) {
12✔
327
                const json::Json value_array = e_cfg_value.value();
16✔
328
                const json::ExpectedSize e_n_items = value_array.GetArraySize();
16✔
329
                if (e_n_items) {
8✔
330
                        for (size_t i = 0; i < e_n_items.value(); i++) {
31✔
331
                                const json::ExpectedJson e_array_item = value_array.Get(i);
46✔
332
                                if (e_array_item) {
23✔
333
                                        const json::ExpectedString e_item_string = e_array_item.value().GetString();
46✔
334
                                        if (e_item_string) {
23✔
335
                                                const string item_value = e_item_string.value();
46✔
336
                                                if (count(
23✔
337
                                                                this->artifact_verify_keys.begin(),
338
                                                                this->artifact_verify_keys.end(),
339
                                                                item_value)
340
                                                        == 0) {
23✔
341
                                                        this->artifact_verify_keys.push_back(item_value);
23✔
342
                                                        applied = true;
23✔
343
                                                }
344
                                        }
345
                                }
346
                        }
347
                }
348
        }
349

350
        e_cfg_value = cfg_json.Get("Servers");
12✔
351
        if (e_cfg_value) {
12✔
352
                const json::Json value_array = e_cfg_value.value();
16✔
353
                const json::ExpectedSize e_n_items = value_array.GetArraySize();
16✔
354
                if (e_n_items) {
8✔
355
                        for (size_t i = 0; i < e_n_items.value(); i++) {
23✔
356
                                const json::ExpectedJson e_array_item = value_array.Get(i);
30✔
357
                                if (e_array_item) {
15✔
358
                                        const json::ExpectedJson e_item_json = e_array_item.value().Get("ServerURL");
30✔
359
                                        if (e_item_json) {
15✔
360
                                                const json::ExpectedString e_item_string = e_item_json.value().GetString();
30✔
361
                                                if (e_item_string) {
15✔
362
                                                        const string item_value = e_item_string.value();
30✔
363
                                                        if (count(this->servers.begin(), this->servers.end(), item_value)
15✔
364
                                                                == 0) {
15✔
365
                                                                this->servers.push_back(std::move(item_value));
15✔
366
                                                                applied = true;
15✔
367
                                                        }
368
                                                }
369
                                        }
370
                                }
371
                        }
372
                }
373
        }
374

375
        /* Last but not least, complex values */
376
        e_cfg_value = cfg_json.Get("HttpsClient");
12✔
377
        if (e_cfg_value) {
12✔
378
                const json::Json value_json = e_cfg_value.value();
16✔
379
                json::ExpectedJson e_cfg_subval = value_json.Get("Certificate");
16✔
380
                if (e_cfg_subval) {
8✔
381
                        const json::Json subval_json = e_cfg_subval.value();
16✔
382
                        const json::ExpectedString e_cfg_string = subval_json.GetString();
16✔
383
                        if (e_cfg_string) {
8✔
384
                                this->https_client.certificate = e_cfg_string.value();
8✔
385
                                applied = true;
8✔
386
                        }
387
                }
388

389
                e_cfg_subval = value_json.Get("Key");
8✔
390
                if (e_cfg_subval) {
8✔
391
                        const json::Json subval_json = e_cfg_subval.value();
14✔
392
                        const json::ExpectedString e_cfg_string = subval_json.GetString();
14✔
393
                        if (e_cfg_string) {
7✔
394
                                this->https_client.key = e_cfg_string.value();
7✔
395
                                applied = true;
7✔
396
                        }
397
                }
398

399
                e_cfg_subval = value_json.Get("SSLEngine");
8✔
400
                if (e_cfg_subval) {
8✔
401
                        const json::Json subval_json = e_cfg_subval.value();
14✔
402
                        const json::ExpectedString e_cfg_string = subval_json.GetString();
14✔
403
                        if (e_cfg_string) {
7✔
404
                                this->https_client.ssl_engine = e_cfg_string.value();
7✔
405
                                applied = true;
7✔
406
                        }
407
                }
408
        }
409

410
        e_cfg_value = cfg_json.Get("Security");
12✔
411
        if (e_cfg_value) {
12✔
412
                const json::Json value_json = e_cfg_value.value();
14✔
413
                json::ExpectedJson e_cfg_subval = value_json.Get("AuthPrivateKey");
14✔
414
                if (e_cfg_subval) {
7✔
415
                        const json::Json subval_json = e_cfg_subval.value();
14✔
416
                        const json::ExpectedString e_cfg_string = subval_json.GetString();
14✔
417
                        if (e_cfg_string) {
7✔
418
                                this->security.auth_private_key = e_cfg_string.value();
7✔
419
                                applied = true;
7✔
420
                        }
421
                }
422

423
                e_cfg_subval = value_json.Get("SSLEngine");
7✔
424
                if (e_cfg_subval) {
7✔
425
                        const json::Json subval_json = e_cfg_subval.value();
14✔
426
                        const json::ExpectedString e_cfg_string = subval_json.GetString();
14✔
427
                        if (e_cfg_string) {
7✔
428
                                this->security.ssl_engine = e_cfg_string.value();
7✔
429
                                applied = true;
7✔
430
                        }
431
                }
432
        }
433

434
        e_cfg_value = cfg_json.Get("Connectivity");
12✔
435
        if (e_cfg_value) {
12✔
436
                const json::Json value_json = e_cfg_value.value();
16✔
437
                json::ExpectedJson e_cfg_subval = value_json.Get("DisableKeepAlive");
16✔
438
                if (e_cfg_subval) {
8✔
439
                        const json::Json subval_json = e_cfg_subval.value();
16✔
440
                        const json::ExpectedBool e_cfg_bool = subval_json.GetBool();
16✔
441
                        if (e_cfg_bool) {
8✔
442
                                this->connectivity.disable_keep_alive = e_cfg_bool.value();
8✔
443
                                applied = true;
8✔
444
                        }
445
                }
446

447
                e_cfg_subval = value_json.Get("IdleConnTimeoutSeconds");
8✔
448
                if (e_cfg_subval) {
8✔
449
                        const json::Json subval_json = e_cfg_subval.value();
16✔
450
                        const auto e_cfg_int = subval_json.GetInt();
16✔
451
                        if (e_cfg_int) {
8✔
452
                                this->connectivity.idle_conn_timeout_seconds = e_cfg_int.value();
8✔
453
                                applied = true;
8✔
454
                        }
455
                }
456
        }
457

458
        return applied;
12✔
459
}
460

461
void MenderConfigFromFile::Reset() {
1✔
462
        *this = MenderConfigFromFile();
1✔
463
}
1✔
464

465
ExpectedBool MenderConfigFromFile::ValidateConfig() {
×
466
        auto ak_conf = this->ValidateArtifactKeyCondition();
×
467
        if (!ak_conf) {
×
468
                return ak_conf;
×
469
        }
470
        auto server_conf = this->ValidateServerConfig();
×
471
        if (!server_conf) {
×
472
                return server_conf;
×
473
        }
474
        return true;
×
475
}
476

477

478

479
} // namespace config_parser
480
} // namespace common
481
} // namespace mender
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc