1 // Copyright (c) 2017 Nuxi, https://nuxi.nl/
2 //
3 // This file is distributed under a 2-clause BSD license.
4 // See the LICENSE file for details.
5 
6 #include <cstdlib>
7 #include <ostream>
8 
9 #include <arpc++/arpc++.h>
10 
11 #include <flower/ls/configuration.ad.h>
12 #include <flower/ls/start.h>
13 #include <flower/protocol/switchboard.ad.h>
14 #include <flower/util/fd_streambuf.h>
15 #include <flower/util/label_map.h>
16 #include <flower/util/logger.h>
17 #include <flower/util/null_streambuf.h>
18 
19 using arpc::Channel;
20 using arpc::ClientContext;
21 using arpc::ClientReader;
22 using arpc::Status;
23 using flower::protocol::switchboard::ListRequest;
24 using flower::protocol::switchboard::ListResponse;
25 using flower::protocol::switchboard::Switchboard;
26 using flower::util::LabelMapToJson;
27 using flower::util::Logger;
28 using flower::util::fd_streambuf;
29 using flower::util::null_streambuf;
30 
Start(const Configuration & configuration)31 void flower::ls::Start(const Configuration& configuration) {
32   // Make logging work.
33   std::unique_ptr<std::streambuf> logger_streambuf;
34   if (const auto& logger_output = configuration.logger_output();
35       logger_output) {
36     logger_streambuf = std::make_unique<fd_streambuf>(logger_output);
37   } else {
38     logger_streambuf = std::make_unique<null_streambuf>();
39   }
40   Logger logger(logger_streambuf.get());
41 
42   // Check that all required fields are present.
43   const auto& switchboard_socket = configuration.switchboard_socket();
44   if (!switchboard_socket) {
45     logger.Log() << "Cannot start without a switchboard socket";
46     std::exit(1);
47   }
48   const auto& list_output_fd = configuration.list_output();
49   if (!list_output_fd) {
50     logger.Log() << "Cannot start without an descriptor for listing output";
51     std::exit(1);
52   }
53   fd_streambuf list_output_streambuf(list_output_fd);
54   std::ostream list_output(&list_output_streambuf);
55 
56   // Request a list of registered targets from the Switchboard.
57   std::shared_ptr<Channel> channel = CreateChannel(switchboard_socket);
58   std::unique_ptr<Switchboard::Stub> stub = Switchboard::NewStub(channel);
59   ClientContext context;
60   ListRequest request;
61   std::unique_ptr<ClientReader<ListResponse>> reader =
62       stub->List(&context, request);
63 
64   // Print the targets.
65   for (ListResponse response; reader->Read(&response);) {
66     LabelMapToJson(response.labels(), &list_output);
67     list_output << std::endl;
68   }
69 
70   if (Status status = reader->Finish(); !status.ok()) {
71     logger.Log() << "Cannot start without a switchboard socket";
72     std::exit(1);
73   }
74   std::exit(0);
75 }
76