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

mendersoftware / mender / 1332919177

14 Jun 2024 02:53PM UTC coverage: 75.535% (+0.001%) from 75.534%
1332919177

push

gitlab-ci

web-flow
Merge pull request #1637 from kacf/direct_linking

feat: Implement support for compiling without DBus.

47 of 60 new or added lines in 2 files covered. (78.33%)

3 existing lines in 3 files now uncovered.

7058 of 9344 relevant lines covered (75.54%)

11667.04 hits per line

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

64.71
/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(
128
                        start + 1,
129
                        end,
130
                        conf::CommandOptsSetWithValue(opts_bootstrap_daemon),
8✔
131
                        conf::CommandOptsSetWithoutValue(opts_bootstrap_daemon));
12✔
132
                auto ex_opt_val = opts_iter.Next();
4✔
133

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

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

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

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

194
        context::MenderContext context(config);
195

196
        test_hook(context);
4✔
197

198
        return action.value()->Execute(context);
4✔
199
}
200

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

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

213
        return 0;
214
}
215

216
} // namespace cli
217
} // namespace auth
218
} // 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