xref: /openbmc/phosphor-ipmi-flash/bmc/version-handler/version_handlers_builder.cpp (revision abf17354324e2ad81bbbf2c63dbdffc5453b62b8)
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 {
35*abf17354SWilliam A. Kennington III 
36*abf17354SWilliam A. Kennington III std::vector<HandlerConfig<VersionBlobHandler::ActionPack>>
3785e54f1bSJason Ling     VersionHandlersBuilder::buildHandlerFromJson(const nlohmann::json& data)
3885e54f1bSJason Ling {
39*abf17354SWilliam 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         {
45*abf17354SWilliam 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. */
6185e54f1bSJason Ling             const auto& v = item.at("version");
6285e54f1bSJason Ling             /* version must have handler */
6385e54f1bSJason Ling             const auto& h = v.at("handler");
6485e54f1bSJason Ling 
658557a939SWilliam A. Kennington III             const std::string& handlerType = h.at("type");
6685e54f1bSJason Ling             if (handlerType == "file")
6785e54f1bSJason Ling             {
6885e54f1bSJason Ling                 const auto& path = h.at("path");
6985e54f1bSJason Ling                 output.handler = std::make_unique<FileHandler>(path);
7085e54f1bSJason Ling             }
7185e54f1bSJason Ling             else
7285e54f1bSJason Ling             {
7385e54f1bSJason Ling                 throw std::runtime_error("Invalid handler type: " +
7485e54f1bSJason Ling                                          handlerType);
7585e54f1bSJason Ling             }
7685e54f1bSJason Ling 
7785e54f1bSJason Ling             /* actions are required (presently). */
7885e54f1bSJason Ling             const auto& a = v.at("actions");
79*abf17354SWilliam A. Kennington III             auto pack = std::make_unique<VersionBlobHandler::ActionPack>();
8085e54f1bSJason Ling 
8185e54f1bSJason Ling             /* to make an action optional, assign type "skip" */
8285e54f1bSJason Ling             const auto& onOpen = a.at("open");
838557a939SWilliam A. Kennington III             const std::string& onOpenType = onOpen.at("type");
8485e54f1bSJason Ling             if (onOpenType == "systemd")
8585e54f1bSJason Ling             {
8685e54f1bSJason Ling                 pack->onOpen = std::move(buildSystemd(onOpen));
8785e54f1bSJason Ling             }
8885e54f1bSJason Ling             else if (onOpenType == "skip")
8985e54f1bSJason Ling             {
9085e54f1bSJason Ling                 pack->onOpen = SkipAction::CreateSkipAction();
9185e54f1bSJason Ling             }
9285e54f1bSJason Ling             else
9385e54f1bSJason Ling             {
9485e54f1bSJason Ling                 throw std::runtime_error("Invalid preparation type: " +
9585e54f1bSJason Ling                                          onOpenType);
9685e54f1bSJason Ling             }
9785e54f1bSJason Ling 
9885e54f1bSJason Ling             output.actions = std::move(pack);
9985e54f1bSJason Ling             handlers.push_back(std::move(output));
10085e54f1bSJason Ling         }
10185e54f1bSJason Ling         catch (const std::exception& e)
10285e54f1bSJason Ling         {
10385e54f1bSJason Ling             /* TODO: Once phosphor-logging supports unit-test injection, fix
10485e54f1bSJason Ling              * this to log.
10585e54f1bSJason Ling              */
10685e54f1bSJason Ling             std::fprintf(stderr,
10785e54f1bSJason Ling                          "Excepted building HandlerConfig from json: %s\n",
10885e54f1bSJason Ling                          e.what());
10985e54f1bSJason Ling         }
11085e54f1bSJason Ling     }
11185e54f1bSJason Ling 
11285e54f1bSJason Ling     return handlers;
11385e54f1bSJason Ling }
114*abf17354SWilliam A. Kennington III 
11585e54f1bSJason Ling } // namespace ipmi_flash
116