blob: d38612808813becb9e853177a6cfd91e99c6ef21 [file] [log] [blame]
Jason Ling85e54f12020-11-05 18:47:21 -08001/*
2 * Copyright 2019 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "version_handlers_builder.hpp"
17
18#include "file_handler.hpp"
19#include "fs.hpp"
20#include "skip_action.hpp"
21
22#include <nlohmann/json.hpp>
23
24#include <algorithm>
25#include <cstdio>
26#include <exception>
27#include <fstream>
28#include <memory>
29#include <regex>
30#include <string>
31#include <vector>
32
33namespace ipmi_flash
34{
35std::vector<HandlerConfig<VersionActionPack>>
36 VersionHandlersBuilder::buildHandlerFromJson(const nlohmann::json& data)
37{
38 std::vector<HandlerConfig<VersionActionPack>> handlers;
39
40 for (const auto& item : data)
41 {
42 try
43 {
44 HandlerConfig<VersionActionPack> output;
45
46 /* at() throws an exception when the key is not present. */
47 item.at("blob").get_to(output.blobId);
48
49 /* name must be: /flash/... or /version/...*/
50 std::regex regexpr("^\\/(?:flash|version)\\/(.+)");
51 std::smatch matches;
52 if (!std::regex_search(output.blobId, matches, regexpr))
53 {
54 throw std::runtime_error(
55 "Invalid blob name: '" + output.blobId +
56 "' must start with /flash/ or /version/");
57 }
58 output.blobId = "/version/" + matches[1].str();
59 /* version is required. */
60 const auto& v = item.at("version");
61 /* version must have handler */
62 const auto& h = v.at("handler");
63
64 const std::string handlerType = h.at("type");
65 if (handlerType == "file")
66 {
67 const auto& path = h.at("path");
68 output.handler = std::make_unique<FileHandler>(path);
69 }
70 else
71 {
72 throw std::runtime_error("Invalid handler type: " +
73 handlerType);
74 }
75
76 /* actions are required (presently). */
77 const auto& a = v.at("actions");
78 std::unique_ptr<VersionActionPack> pack =
79 std::make_unique<VersionActionPack>();
80
81 /* to make an action optional, assign type "skip" */
82 const auto& onOpen = a.at("open");
83 const std::string onOpenType = onOpen.at("type");
84 if (onOpenType == "systemd")
85 {
86 pack->onOpen = std::move(buildSystemd(onOpen));
87 }
88 else if (onOpenType == "skip")
89 {
90 pack->onOpen = SkipAction::CreateSkipAction();
91 }
92 else
93 {
94 throw std::runtime_error("Invalid preparation type: " +
95 onOpenType);
96 }
97
98 output.actions = std::move(pack);
99 handlers.push_back(std::move(output));
100 }
101 catch (const std::exception& e)
102 {
103 /* TODO: Once phosphor-logging supports unit-test injection, fix
104 * this to log.
105 */
106 std::fprintf(stderr,
107 "Excepted building HandlerConfig from json: %s\n",
108 e.what());
109 }
110 }
111
112 return handlers;
113}
114} // namespace ipmi_flash