xref: /openbmc/phosphor-ipmi-flash/bmc/version-handler/version_handlers_builder.cpp (revision 42a44c281cce08be0ca6251955f4fb73d30c8ced)
185e54f1bSJason Ling /*
285e54f1bSJason Ling  * Copyright 2019 Google Inc.
385e54f1bSJason Ling  *
485e54f1bSJason Ling  * Licensed under the Apache License, Version 2.0 (the "License");
585e54f1bSJason Ling  * you may not use this file except in compliance with the License.
685e54f1bSJason Ling  * You may obtain a copy of the License at
785e54f1bSJason Ling  *
885e54f1bSJason Ling  *     http://www.apache.org/licenses/LICENSE-2.0
985e54f1bSJason Ling  *
1085e54f1bSJason Ling  * Unless required by applicable law or agreed to in writing, software
1185e54f1bSJason Ling  * distributed under the License is distributed on an "AS IS" BASIS,
1285e54f1bSJason Ling  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1385e54f1bSJason Ling  * See the License for the specific language governing permissions and
1485e54f1bSJason Ling  * limitations under the License.
1585e54f1bSJason Ling  */
1685e54f1bSJason Ling #include "version_handlers_builder.hpp"
1785e54f1bSJason Ling 
1885e54f1bSJason Ling #include "file_handler.hpp"
1985e54f1bSJason Ling #include "fs.hpp"
2085e54f1bSJason Ling #include "skip_action.hpp"
2185e54f1bSJason Ling 
2285e54f1bSJason Ling #include <nlohmann/json.hpp>
2385e54f1bSJason Ling 
2485e54f1bSJason Ling #include <algorithm>
2585e54f1bSJason Ling #include <cstdio>
2685e54f1bSJason Ling #include <exception>
2785e54f1bSJason Ling #include <fstream>
2885e54f1bSJason Ling #include <memory>
2985e54f1bSJason Ling #include <regex>
3085e54f1bSJason Ling #include <string>
3185e54f1bSJason Ling #include <vector>
3285e54f1bSJason Ling 
3385e54f1bSJason Ling namespace ipmi_flash
3485e54f1bSJason Ling {
35abf17354SWilliam A. Kennington III 
36abf17354SWilliam A. Kennington III std::vector<HandlerConfig<VersionBlobHandler::ActionPack>>
buildHandlerFromJson(const nlohmann::json & data)3785e54f1bSJason Ling     VersionHandlersBuilder::buildHandlerFromJson(const nlohmann::json& data)
3885e54f1bSJason Ling {
39abf17354SWilliam A. Kennington III     std::vector<HandlerConfig<VersionBlobHandler::ActionPack>> handlers;
4085e54f1bSJason Ling 
4185e54f1bSJason Ling     for (const auto& item : data)
4285e54f1bSJason Ling     {
4385e54f1bSJason Ling         try
4485e54f1bSJason Ling         {
45abf17354SWilliam A. Kennington III             HandlerConfig<VersionBlobHandler::ActionPack> output;
4685e54f1bSJason Ling 
4785e54f1bSJason Ling             /* at() throws an exception when the key is not present. */
4885e54f1bSJason Ling             item.at("blob").get_to(output.blobId);
4985e54f1bSJason Ling 
5085e54f1bSJason Ling             /* name must be: /flash/... or /version/...*/
5185e54f1bSJason Ling             std::regex regexpr("^\\/(?:flash|version)\\/(.+)");
5285e54f1bSJason Ling             std::smatch matches;
5385e54f1bSJason Ling             if (!std::regex_search(output.blobId, matches, regexpr))
5485e54f1bSJason Ling             {
5585e54f1bSJason Ling                 throw std::runtime_error(
5685e54f1bSJason Ling                     "Invalid blob name: '" + output.blobId +
5785e54f1bSJason Ling                     "' must start with /flash/ or /version/");
5885e54f1bSJason Ling             }
5985e54f1bSJason Ling             output.blobId = "/version/" + matches[1].str();
6085e54f1bSJason Ling             /* version is required. */
61b8fd6d38SWilly Tu             if (!item.contains("version"))
62b8fd6d38SWilly Tu             {
63b8fd6d38SWilly Tu                 continue;
64b8fd6d38SWilly Tu             }
65b8fd6d38SWilly Tu 
6685e54f1bSJason Ling             const auto& v = item.at("version");
6785e54f1bSJason Ling             /* version must have handler */
6885e54f1bSJason Ling             const auto& h = v.at("handler");
6985e54f1bSJason Ling 
708557a939SWilliam A. Kennington III             const std::string& handlerType = h.at("type");
7185e54f1bSJason Ling             if (handlerType == "file")
7285e54f1bSJason Ling             {
7385e54f1bSJason Ling                 const auto& path = h.at("path");
7485e54f1bSJason Ling                 output.handler = std::make_unique<FileHandler>(path);
7585e54f1bSJason Ling             }
7685e54f1bSJason Ling             else
7785e54f1bSJason Ling             {
78*42a44c28SPatrick Williams                 throw std::runtime_error(
79*42a44c28SPatrick Williams                     "Invalid handler type: " + handlerType);
8085e54f1bSJason Ling             }
8185e54f1bSJason Ling 
8285e54f1bSJason Ling             /* actions are required (presently). */
8385e54f1bSJason Ling             const auto& a = v.at("actions");
84abf17354SWilliam A. Kennington III             auto pack = std::make_unique<VersionBlobHandler::ActionPack>();
8585e54f1bSJason Ling 
8685e54f1bSJason Ling             /* to make an action optional, assign type "skip" */
8785e54f1bSJason Ling             const auto& onOpen = a.at("open");
888557a939SWilliam A. Kennington III             const std::string& onOpenType = onOpen.at("type");
8985e54f1bSJason Ling             if (onOpenType == "systemd")
9085e54f1bSJason Ling             {
9185e54f1bSJason Ling                 pack->onOpen = std::move(buildSystemd(onOpen));
9285e54f1bSJason Ling             }
9385e54f1bSJason Ling             else if (onOpenType == "skip")
9485e54f1bSJason Ling             {
9585e54f1bSJason Ling                 pack->onOpen = SkipAction::CreateSkipAction();
9685e54f1bSJason Ling             }
9785e54f1bSJason Ling             else
9885e54f1bSJason Ling             {
99*42a44c28SPatrick Williams                 throw std::runtime_error(
100*42a44c28SPatrick Williams                     "Invalid preparation type: " + onOpenType);
10185e54f1bSJason Ling             }
10285e54f1bSJason Ling 
10385e54f1bSJason Ling             output.actions = std::move(pack);
10485e54f1bSJason Ling             handlers.push_back(std::move(output));
10585e54f1bSJason Ling         }
10685e54f1bSJason Ling         catch (const std::exception& e)
10785e54f1bSJason Ling         {
10885e54f1bSJason Ling             /* TODO: Once phosphor-logging supports unit-test injection, fix
10985e54f1bSJason Ling              * this to log.
11085e54f1bSJason Ling              */
11185e54f1bSJason Ling             std::fprintf(stderr,
11285e54f1bSJason Ling                          "Excepted building HandlerConfig from json: %s\n",
11385e54f1bSJason Ling                          e.what());
11485e54f1bSJason Ling         }
11585e54f1bSJason Ling     }
11685e54f1bSJason Ling 
11785e54f1bSJason Ling     return handlers;
11885e54f1bSJason Ling }
119abf17354SWilliam A. Kennington III 
12085e54f1bSJason Ling } // namespace ipmi_flash
121