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