1c893f43dSJason Ling #pragma once
2c893f43dSJason Ling 
3*e82d7395SJason Ling #include "fs.hpp"
4c893f43dSJason Ling #include "general_systemd.hpp"
5c893f43dSJason Ling #include "image_handler.hpp"
6c893f43dSJason Ling 
7c893f43dSJason Ling #include <nlohmann/json.hpp>
8c893f43dSJason Ling 
9c893f43dSJason Ling #include <memory>
10c893f43dSJason Ling #include <string>
11c893f43dSJason Ling #include <vector>
12c893f43dSJason Ling 
13c893f43dSJason Ling namespace ipmi_flash
14c893f43dSJason Ling {
15*e82d7395SJason Ling /**
16*e82d7395SJason Ling  * build a systemd file triggerable action from json data
17*e82d7395SJason Ling  */
18c893f43dSJason Ling std::unique_ptr<TriggerableActionInterface>
19c893f43dSJason Ling     buildFileSystemd(const nlohmann::json& data);
20c893f43dSJason Ling 
21*e82d7395SJason Ling /**
22*e82d7395SJason Ling  * build a systemd triggerable action from json data
23*e82d7395SJason Ling  */
24c893f43dSJason Ling std::unique_ptr<TriggerableActionInterface>
25c893f43dSJason Ling     buildSystemd(const nlohmann::json& data);
26c893f43dSJason Ling 
27c893f43dSJason Ling /**
28c893f43dSJason Ling  * HandlerConfig associates a blobID with an ImageHandler and a set of
29c893f43dSJason Ling  * supported actions of type T.
30c893f43dSJason Ling  */
31c893f43dSJason Ling template <typename T>
32c893f43dSJason Ling class HandlerConfig
33c893f43dSJason Ling {
34c893f43dSJason Ling   public:
35c893f43dSJason Ling     HandlerConfig() = default;
36c893f43dSJason Ling     ~HandlerConfig() = default;
37c893f43dSJason Ling     HandlerConfig(const HandlerConfig&) = delete;
38c893f43dSJason Ling     HandlerConfig& operator=(const HandlerConfig&) = delete;
39c893f43dSJason Ling     HandlerConfig(HandlerConfig&&) = default;
40c893f43dSJason Ling     HandlerConfig& operator=(HandlerConfig&&) = default;
41c893f43dSJason Ling 
42c893f43dSJason Ling     /* A string in the form: /flash/{unique}, s.t. unique is something like,
43c893f43dSJason Ling      * flash, ubitar, statictar, or bios
44c893f43dSJason Ling      */
45c893f43dSJason Ling     std::string blobId;
46c893f43dSJason Ling 
47c893f43dSJason Ling     /* This owns a handler interface, this is typically going to be a file
48c893f43dSJason Ling      * writer object.
49c893f43dSJason Ling      */
50c893f43dSJason Ling     std::unique_ptr<ImageHandlerInterface> handler;
51c893f43dSJason Ling 
52c893f43dSJason Ling     /*  specifies actions to be taken in response to certain operations on a
53c893f43dSJason Ling      *  blob.
54c893f43dSJason Ling      *  Usually required but there are exceptions;  the hashBlobId doesn't have
55c893f43dSJason Ling      * an action pack.
56c893f43dSJason Ling      */
57c893f43dSJason Ling     std::unique_ptr<T> actions;
58c893f43dSJason Ling };
59c893f43dSJason Ling 
60c893f43dSJason Ling /* HandlersBuilderIfc is a helper class that builds Handlers from the json files
61c893f43dSJason Ling  * found within a specified directory.
62c893f43dSJason Ling  * The child class that inherits from HandlersBuilderIfc should implement
63c893f43dSJason Ling  * buildHandlersConfigs to perform json validation and parsing.
64c893f43dSJason Ling  *
65c893f43dSJason Ling  */
66c893f43dSJason Ling template <typename T>
67c893f43dSJason Ling class HandlersBuilderIfc
68c893f43dSJason Ling {
69c893f43dSJason Ling   public:
70c893f43dSJason Ling     HandlersBuilderIfc() = default;
71c893f43dSJason Ling     ~HandlersBuilderIfc() = default;
72c893f43dSJason Ling     HandlersBuilderIfc(const HandlersBuilderIfc&) = delete;
73c893f43dSJason Ling     HandlersBuilderIfc& operator=(const HandlersBuilderIfc&) = delete;
74c893f43dSJason Ling     HandlersBuilderIfc(HandlersBuilderIfc&&) = default;
75c893f43dSJason Ling     HandlersBuilderIfc& operator=(HandlersBuilderIfc&&) = default;
76c893f43dSJason Ling     /**
77c893f43dSJason Ling      * Given a folder of json configs, build the configurations.
78c893f43dSJason Ling      *
79c893f43dSJason Ling      * @param[in] directory - the directory to search (recurisvely).
80c893f43dSJason Ling      * @return list of HandlerConfig objects.
81c893f43dSJason Ling      */
82c893f43dSJason Ling     std::vector<HandlerConfig<T>>
83*e82d7395SJason Ling         buildHandlerConfigs(const std::string& directory)
84*e82d7395SJason Ling     {
85*e82d7395SJason Ling 
86*e82d7395SJason Ling         std::vector<HandlerConfig<T>> output;
87*e82d7395SJason Ling 
88*e82d7395SJason Ling         std::vector<std::string> jsonPaths = GetJsonList(directory);
89*e82d7395SJason Ling         for (const auto& path : jsonPaths)
90*e82d7395SJason Ling         {
91*e82d7395SJason Ling             std::ifstream jsonFile(path);
92*e82d7395SJason Ling             if (!jsonFile.is_open())
93*e82d7395SJason Ling             {
94*e82d7395SJason Ling                 std::fprintf(stderr, "Unable to open json file: %s\n",
95*e82d7395SJason Ling                              path.c_str());
96*e82d7395SJason Ling                 continue;
97*e82d7395SJason Ling             }
98*e82d7395SJason Ling 
99*e82d7395SJason Ling             auto data = nlohmann::json::parse(jsonFile, nullptr, false);
100*e82d7395SJason Ling             if (data.is_discarded())
101*e82d7395SJason Ling             {
102*e82d7395SJason Ling                 std::fprintf(stderr, "Parsing json failed: %s\n", path.c_str());
103*e82d7395SJason Ling                 continue;
104*e82d7395SJason Ling             }
105*e82d7395SJason Ling 
106*e82d7395SJason Ling             std::vector<HandlerConfig<T>> configs = buildHandlerFromJson(data);
107*e82d7395SJason Ling             std::move(configs.begin(), configs.end(),
108*e82d7395SJason Ling                       std::back_inserter(output));
109*e82d7395SJason Ling         }
110*e82d7395SJason Ling         return output;
111*e82d7395SJason Ling     };
112c893f43dSJason Ling     /**
113c893f43dSJason Ling      * Given a list of handlers as json data, construct the appropriate
114c893f43dSJason Ling      * HandlerConfig objects.  This method is meant to be called per json
115c893f43dSJason Ling      * configuration file found.
116c893f43dSJason Ling      *
117c893f43dSJason Ling      * The list will only contain validly build HandlerConfig objects.  Any
118c893f43dSJason Ling      * invalid configuration is skipped. The hope is that the BMC firmware
119c893f43dSJason Ling      * update configuration will never be invalid, but if another aspect is
120c893f43dSJason Ling      * invalid, it can be fixed with a BMC firmware update once the bug is
121c893f43dSJason Ling      * identified.
122c893f43dSJason Ling      *
123c893f43dSJason Ling      * This code does not validate that the blob specified is unique, that
124c893f43dSJason Ling      * should be handled at a higher layer.
125c893f43dSJason Ling      *
126c893f43dSJason Ling      * @param[in] data - json data from a json file.
127c893f43dSJason Ling      * @return list of HandlerConfig objects.
128c893f43dSJason Ling      */
129c893f43dSJason Ling     virtual std::vector<HandlerConfig<T>>
130c893f43dSJason Ling         buildHandlerFromJson(const nlohmann::json& data) = 0;
131c893f43dSJason Ling };
132c893f43dSJason Ling } // namespace ipmi_flash
133