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