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

mendersoftware / mender / 1012473002

21 Sep 2023 02:17PM UTC coverage: 78.107% (-0.3%) from 78.44%
1012473002

push

gitlab-ci

lluiscampos
chore: log stdout output on errors when parsing UM yes/no commands

Signed-off-by: Lluis Campos <lluis.campos@northern.tech>

2 of 2 new or added lines in 1 file covered. (100.0%)

6468 of 8281 relevant lines covered (78.11%)

11106.28 hits per line

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

87.12
/mender-update/cli/actions.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 <mender-update/cli/actions.hpp>
16

17
#include <algorithm>
18
#include <iostream>
19
#include <string>
20

21
#include <artifact/config.hpp>
22

23
#include <common/common.hpp>
24
#include <common/error.hpp>
25
#include <common/events.hpp>
26
#include <common/key_value_database.hpp>
27
#include <common/log.hpp>
28
#include <common/path.hpp>
29

30
#include <mender-update/cli/cli.hpp>
31
#include <mender-update/daemon.hpp>
32
#include <mender-update/standalone.hpp>
33

34
namespace mender {
35
namespace update {
36
namespace cli {
37

38
namespace conf = mender::common::conf;
39
namespace daemon = mender::update::daemon;
40
namespace database = mender::common::key_value_database;
41
namespace error = mender::common::error;
42
namespace events = mender::common::events;
43
namespace kv_db = mender::common::key_value_database;
44
namespace log = mender::common::log;
45
namespace path = mender::common::path;
46
namespace standalone = mender::update::standalone;
47

48
static error::Error DoMaybeInstallBootstrapArtifact(context::MenderContext &main_context) {
47✔
49
        const string bootstrap_artifact_path {
50
                main_context.GetConfig().paths.GetBootstrapArtifactFile()};
94✔
51
        // Check if the DB is populated - then install conditionally
52
        auto &db = main_context.GetMenderStoreDB();
47✔
53
        auto exp_key = db.Read(main_context.artifact_name_key);
94✔
54
        if (exp_key) {
47✔
55
                // Key exists. Do nothing
56
                return error::NoError;
13✔
57
        }
58
        error::Error err = exp_key.error();
68✔
59
        if (err.code != kv_db::MakeError(kv_db::KeyError, "Key Not found").code) {
34✔
60
                return err;
×
61
        }
62

63
        // Key does not exist, install the bootstrap artifact if it exists
64
        if (!path::FileExists(bootstrap_artifact_path)) {
34✔
65
                log::Debug("No Bootstrap Artifact found at: " + bootstrap_artifact_path);
33✔
66
                error::Error err =
67
                        db.Write(main_context.artifact_name_key, common::ByteVectorFromString("unknown"));
66✔
68
                if (err != error::NoError) {
33✔
69
                        return err;
×
70
                }
71
                return error::NoError;
33✔
72
        }
73
        log::Info("Installing the bootstrap Artifact");
1✔
74
        auto result = standalone::Install(
75
                main_context, bootstrap_artifact_path, artifact::config::Signature::Skip);
2✔
76

77
        if (result.err != error::NoError) {
1✔
78
                error::Error err =
79
                        db.Write(main_context.artifact_name_key, common::ByteVectorFromString("unknown"));
×
80
                return result.err.FollowedBy(err).WithContext("Failed to install the bootstrap Artifact");
×
81
        }
82
        return error::NoError;
1✔
83
}
84

85
error::Error MaybeInstallBootstrapArtifact(context::MenderContext &main_context) {
47✔
86
        const string bootstrap_artifact_path {
87
                main_context.GetConfig().paths.GetBootstrapArtifactFile()};
94✔
88
        error::Error err = DoMaybeInstallBootstrapArtifact(main_context);
94✔
89

90
        // Unconditionally delete the bootstrap Artifact
91
        if (path::FileExists(bootstrap_artifact_path)) {
47✔
92
                error::Error delete_err = path::FileDelete(bootstrap_artifact_path);
1✔
93
                if (delete_err != error::NoError) {
1✔
94
                        return err.FollowedBy(
95
                                delete_err.WithContext("Failed to delete the bootstrap Artifact"));
×
96
                }
97
        }
98
        return err;
47✔
99
}
100

101
error::Error ShowArtifactAction::Execute(context::MenderContext &main_context) {
2✔
102
        auto exp_provides = main_context.LoadProvides();
4✔
103
        if (!exp_provides) {
2✔
104
                return exp_provides.error();
×
105
        }
106

107
        auto &provides = exp_provides.value();
2✔
108
        if (provides.count("artifact_name") == 0 || provides["artifact_name"] == "") {
5✔
109
                cout << "Unknown" << endl;
1✔
110
        } else {
111
                cout << provides["artifact_name"] << endl;
1✔
112
        }
113
        return error::NoError;
2✔
114
}
115

116
error::Error ShowProvidesAction::Execute(context::MenderContext &main_context) {
32✔
117
        auto exp_provides = main_context.LoadProvides();
64✔
118
        if (!exp_provides) {
32✔
119
                return exp_provides.error();
×
120
        }
121

122
        auto &provides = exp_provides.value();
32✔
123
        for (const auto &elem : provides) {
104✔
124
                cout << elem.first << "=" << elem.second << endl;
72✔
125
        }
126

127
        return error::NoError;
32✔
128
}
129

130
static error::Error ResultHandler(standalone::ResultAndError result) {
54✔
131
        switch (result.result) {
54✔
132
        case standalone::Result::InstalledAndCommitted:
32✔
133
        case standalone::Result::Committed:
134
        case standalone::Result::Installed:
135
        case standalone::Result::RolledBack:
136
                // There should not be any error for these.
137
                assert(result.err == error::NoError);
32✔
138
                break;
32✔
139
        case standalone::Result::InstalledAndCommittedRebootRequired:
2✔
140
        case standalone::Result::InstalledRebootRequired:
141
                if (result.err == error::NoError) {
2✔
142
                        result.err = context::MakeError(context::RebootRequiredError, "Reboot required");
2✔
143
                }
144
                break;
2✔
145
        default:
20✔
146
                // All other states, make sure they have an error.
147
                if (result.err != error::NoError) {
20✔
148
                        log::Error(result.err.String());
14✔
149
                } else {
150
                        result.err = error::MakeError(error::ExitWithFailureError, "");
6✔
151
                }
152
                break;
20✔
153
        }
154

155
        switch (result.result) {
54✔
156
        case standalone::Result::InstalledAndCommitted:
19✔
157
        case standalone::Result::InstalledAndCommittedRebootRequired:
158
                cout << "Installed and committed." << endl;
19✔
159
                break;
19✔
160
        case standalone::Result::Committed:
3✔
161
                cout << "Committed." << endl;
3✔
162
                break;
3✔
163
        case standalone::Result::Installed:
9✔
164
        case standalone::Result::InstalledRebootRequired:
165
                cout << "Installed, but not committed." << endl;
9✔
166
                cout << "Use 'commit' to update, or 'rollback' to roll back the update." << endl;
9✔
167
                break;
9✔
168
        case standalone::Result::InstalledButFailedInPostCommit:
2✔
169
                cout << "Installed, but one or more post-commit steps failed." << endl;
2✔
170
                break;
2✔
171
        case standalone::Result::NoUpdateInProgress:
2✔
172
                cout << "No update in progress." << endl;
2✔
173
                break;
2✔
174
        case standalone::Result::FailedNothingDone:
5✔
175
                cout << "Installation failed. System not modified." << endl;
5✔
176
                break;
5✔
177
        case standalone::Result::RolledBack:
3✔
178
                cout << "Rolled back." << endl;
3✔
179
                break;
3✔
180
        case standalone::Result::NoRollback:
1✔
181
                cout << "Update Module does not support rollback." << endl;
1✔
182
                break;
1✔
183
        case standalone::Result::RollbackFailed:
1✔
184
                cout << "Rollback failed. System may be in an inconsistent state." << endl;
1✔
185
                break;
1✔
186
        case standalone::Result::FailedAndRolledBack:
1✔
187
                cout << "Installation failed. Rolled back modifications." << endl;
1✔
188
                break;
1✔
189
        case standalone::Result::FailedAndNoRollback:
4✔
190
                cout
191
                        << "Installation failed, and Update Module does not support rollback. System may be in an inconsistent state."
4✔
192
                        << endl;
4✔
193
                break;
4✔
194
        case standalone::Result::FailedAndRollbackFailed:
4✔
195
                cout
196
                        << "Installation failed, and rollback also failed. System may be in an inconsistent state."
4✔
197
                        << endl;
4✔
198
                break;
4✔
199
        }
200

201
        switch (result.result) {
54✔
202
        case standalone::Result::InstalledRebootRequired:
2✔
203
        case standalone::Result::InstalledAndCommittedRebootRequired:
204
                cout << "At least one payload requested a reboot of the device it updated." << endl;
2✔
205
                break;
2✔
206
        default:
52✔
207
                break;
52✔
208
        }
209

210
        return result.err;
54✔
211
}
212

213
error::Error InstallAction::Execute(context::MenderContext &main_context) {
44✔
214
        error::Error err = MaybeInstallBootstrapArtifact(main_context);
44✔
215
        if (err != error::NoError) {
44✔
216
                return err;
×
217
        }
218
        auto result = standalone::Install(main_context, src_);
88✔
219
        err = ResultHandler(result);
44✔
220
        if (!reboot_exit_code_
44✔
221
                && err.code == context::MakeError(context::RebootRequiredError, "").code) {
44✔
222
                // If reboot exit code isn't requested, then this type of error should be treated as
223
                // plain success.
224
                err = error::NoError;
1✔
225
        }
226
        return err;
44✔
227
}
228

229
error::Error CommitAction::Execute(context::MenderContext &main_context) {
4✔
230
        auto result = standalone::Commit(main_context);
4✔
231
        return ResultHandler(result);
8✔
232
}
233

234
error::Error RollbackAction::Execute(context::MenderContext &main_context) {
6✔
235
        auto result = standalone::Rollback(main_context);
6✔
236
        return ResultHandler(result);
12✔
237
}
238

239
error::Error DaemonAction::Execute(context::MenderContext &main_context) {
×
240
        events::EventLoop event_loop;
×
241
        daemon::Context ctx(main_context, event_loop);
×
242
        daemon::StateMachine state_machine(ctx, event_loop);
×
243
        state_machine.LoadStateFromDb();
×
244
        error::Error err = MaybeInstallBootstrapArtifact(main_context);
×
245
        if (err != error::NoError) {
×
246
                return err;
×
247
        }
248
        return state_machine.Run();
×
249
}
250

251
} // namespace cli
252
} // namespace update
253
} // 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