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

mendersoftware / mender / 1448115011

10 Sep 2024 10:12AM UTC coverage: 76.326%. Remained the same
1448115011

push

gitlab-ci

web-flow
Merge pull request #1664 from kacf/small_fixes

Smaller fixes to support upcoming commits

9 of 12 new or added lines in 3 files covered. (75.0%)

27 existing lines in 2 files now uncovered.

7367 of 9652 relevant lines covered (76.33%)

11321.93 hits per line

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

64.18
/src/mender-auth/cli/cli.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-auth/cli/cli.hpp>
16

17
#include <string>
18

19
#include <client_shared/conf.hpp>
20
#include <common/expected.hpp>
21
#include <common/io.hpp>
22

23
#include <mender-auth/cli/actions.hpp>
24
#include <mender-auth/context.hpp>
25

26
#ifdef MENDER_USE_DBUS
27
#include <mender-auth/ipc/server.hpp>
28
#endif
29

30
namespace mender {
31
namespace auth {
32
namespace cli {
33

34
using namespace std;
35

36
namespace conf = mender::client_shared::conf;
37
namespace expected = mender::common::expected;
38
namespace io = mender::common::io;
39

40
namespace context = mender::auth::context;
41

42
#ifdef MENDER_USE_DBUS
43
namespace ipc = mender::auth::ipc;
44
#endif
45

46
const vector<conf::CliOption> opts_bootstrap_daemon {
47
        conf::CliOption {
48
                .long_option = "forcebootstrap",
49
                .short_option = "F",
50
                .description = "Force bootstrap",
51
        },
52
        conf::CliOption {
53
                .long_option = "passphrase-file",
54
                .description =
55
                        "Passphrase file for decrypting an encrypted private key. '-' loads passphrase from stdin",
56
                .default_value = "''",
57
        },
58
};
59

60
const conf::CliCommand cmd_bootstrap {
61
        .name = "bootstrap",
62
        .description = "Perform bootstrap and exit",
63
        .options = opts_bootstrap_daemon,
64
};
65

66
const conf::CliCommand cmd_daemon {
67
        .name = "daemon",
68
        .description = "Start the client as a background service",
69
        .options = opts_bootstrap_daemon,
70
};
71

72
const conf::CliApp cli_mender_auth = {
73
        .name = "mender-auth",
74
        .short_description = "manage and start Mender Auth",
75
        .long_description =
76
                R"(mender-auth integrates both the mender-auth daemon and commands for manually
77
   performing tasks performed by the daemon (see list of COMMANDS below).)",
78
        .commands =
79
                {
80
                        cmd_bootstrap,
81
                        cmd_daemon,
82
                },
83
};
84

85
static expected::ExpectedString GetPassphraseFromFile(const string &filepath) {
×
86
        string passphrase = "";
×
87
        if (filepath == "") {
×
88
                return passphrase;
×
89
        }
90

91
        auto ex_ifs = io::OpenIfstream(filepath == "-" ? io::paths::Stdin : filepath);
×
92
        if (!ex_ifs) {
×
93
                return expected::unexpected(ex_ifs.error());
×
94
        }
95
        auto &ifs = ex_ifs.value();
×
96

97
        errno = 0;
×
98
        getline(ifs, passphrase);
×
99
        if (ifs.bad()) {
×
100
                int io_errno = errno;
×
101
                error::Error err {
102
                        generic_category().default_error_condition(io_errno),
×
103
                        "Failed to read passphrase from '" + filepath + "'"};
×
104
                return expected::unexpected(err);
×
105
        }
106

107
        return passphrase;
×
108
}
109

110
static ExpectedActionPtr ParseAuthArguments(
6✔
111
        const conf::MenderConfig &config,
112
        vector<string>::const_iterator start,
113
        vector<string>::const_iterator end) {
114
        if (start == end) {
6✔
115
                return expected::unexpected(conf::MakeError(conf::InvalidOptionsError, "Need an action"));
3✔
116
        }
117

118
        bool help_arg = conf::FindCmdlineHelpArg(start + 1, end);
5✔
119
        if (help_arg) {
5✔
120
                conf::PrintCliCommandHelp(cli_mender_auth, start[0]);
×
121
                return expected::unexpected(error::MakeError(error::ExitWithSuccessError, ""));
×
122
        }
123

124
        string passphrase = "";
5✔
125
        bool forcebootstrap = false;
126
        if (start[0] == "bootstrap" || start[0] == "daemon") {
5✔
127
                conf::CmdlineOptionsIterator opts_iter(start + 1, end, opts_bootstrap_daemon);
8✔
128
                auto ex_opt_val = opts_iter.Next();
4✔
129

130
                while (ex_opt_val
131
                           && ((ex_opt_val.value().option != "") || (ex_opt_val.value().value != ""))) {
5✔
132
                        auto opt_val = ex_opt_val.value();
1✔
133
                        if ((opt_val.option == "--passphrase-file")) {
1✔
134
                                auto ex_passphrase = GetPassphraseFromFile(opt_val.value);
×
UNCOV
135
                                if (!ex_passphrase) {
×
UNCOV
136
                                        return expected::unexpected(ex_passphrase.error());
×
137
                                }
UNCOV
138
                                passphrase = ex_passphrase.value();
×
139
                        } else if ((opt_val.option == "--forcebootstrap" || opt_val.option == "-F")) {
1✔
140
                                forcebootstrap = true;
141
                        } else {
142
                                assert(false);
143
                        }
144
                        ex_opt_val = opts_iter.Next();
2✔
145
                }
146
                if (!ex_opt_val) {
4✔
UNCOV
147
                        return expected::unexpected(ex_opt_val.error());
×
148
                }
149
        }
150

151
        if (start[0] == "bootstrap") {
5✔
152
                return BootstrapAction::Create(config, passphrase, forcebootstrap);
4✔
153
        } else if (start[0] == "daemon") {
1✔
154
#ifdef MENDER_USE_DBUS
UNCOV
155
                return DaemonAction::Create(config, passphrase, forcebootstrap);
×
156
#else
157
                return expected::unexpected(error::Error(
158
                        make_error_condition(errc::not_supported),
159
                        "Daemon mode not support when DBus support is compiled out"));
160
#endif
161
        } else {
162
                return expected::unexpected(
1✔
163
                        conf::MakeError(conf::InvalidOptionsError, "No such action: " + start[0]));
3✔
164
        }
165
}
166

167
error::Error DoMain(
10✔
168
        const vector<string> &args, function<void(context::MenderContext &ctx)> test_hook) {
169
        conf::MenderConfig config;
20✔
170
        auto arg_pos = config.ProcessCmdlineArgs(args.begin(), args.end(), cli_mender_auth);
10✔
171
        if (!arg_pos) {
10✔
172
                if (arg_pos.error().code != error::MakeError(error::ExitWithSuccessError, "").code) {
4✔
173
                        conf::PrintCliHelp(cli_mender_auth);
1✔
174
                }
175
                return arg_pos.error();
4✔
176
        }
177

178
        auto action = ParseAuthArguments(config, args.begin() + arg_pos.value(), args.end());
6✔
179
        if (!action) {
6✔
180
                if (action.error().code != error::MakeError(error::ExitWithSuccessError, "").code) {
2✔
181
                        if (args.size() > 0) {
2✔
182
                                conf::PrintCliCommandHelp(cli_mender_auth, args[0]);
1✔
183
                        } else {
184
                                conf::PrintCliHelp(cli_mender_auth);
1✔
185
                        }
186
                }
187
                return action.error();
2✔
188
        }
189

190
        context::MenderContext context(config);
191

192
        test_hook(context);
4✔
193

194
        return action.value()->Execute(context);
4✔
195
}
196

197
int Main(const vector<string> &args, function<void(context::MenderContext &ctx)> test_hook) {
10✔
198
        auto err = mender::auth::cli::DoMain(args, test_hook);
10✔
199

200
        if (err != error::NoError) {
10✔
201
                if (err.code == error::MakeError(error::ExitWithSuccessError, "").code) {
6✔
202
                        return 0;
203
                } else if (err.code != error::MakeError(error::ExitWithFailureError, "").code) {
3✔
204
                        cerr << "Failed to process command line options: " + err.String() << endl;
6✔
205
                }
206
                return 1;
3✔
207
        }
208

209
        return 0;
210
}
211

212
} // namespace cli
213
} // namespace auth
214
} // 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

© 2026 Coveralls, Inc