xref: /openbmc/bmcweb/redfish-core/src/error_message_utils.cpp (revision 6c038f260633414c52ac34ac44d0d3ab23c3d9a5)
1*6c038f26SEd Tanous #include "error_message_utils.hpp"
2*6c038f26SEd Tanous 
3*6c038f26SEd Tanous #include "logging.hpp"
4*6c038f26SEd Tanous 
5*6c038f26SEd Tanous #include <nlohmann/json.hpp>
6*6c038f26SEd Tanous 
7*6c038f26SEd Tanous #include <string>
8*6c038f26SEd Tanous #include <string_view>
9*6c038f26SEd Tanous 
10*6c038f26SEd Tanous namespace redfish
11*6c038f26SEd Tanous {
12*6c038f26SEd Tanous 
13*6c038f26SEd Tanous namespace messages
14*6c038f26SEd Tanous {
15*6c038f26SEd Tanous 
addMessageToErrorJson(nlohmann::json & target,const nlohmann::json & message)16*6c038f26SEd Tanous void addMessageToErrorJson(nlohmann::json& target,
17*6c038f26SEd Tanous                            const nlohmann::json& message)
18*6c038f26SEd Tanous {
19*6c038f26SEd Tanous     auto& error = target["error"];
20*6c038f26SEd Tanous 
21*6c038f26SEd Tanous     // If this is the first error message, fill in the information from the
22*6c038f26SEd Tanous     // first error message to the top level struct
23*6c038f26SEd Tanous     if (!error.is_object())
24*6c038f26SEd Tanous     {
25*6c038f26SEd Tanous         auto messageIdIterator = message.find("MessageId");
26*6c038f26SEd Tanous         if (messageIdIterator == message.end())
27*6c038f26SEd Tanous         {
28*6c038f26SEd Tanous             BMCWEB_LOG_CRITICAL(
29*6c038f26SEd Tanous                 "Attempt to add error message without MessageId");
30*6c038f26SEd Tanous             return;
31*6c038f26SEd Tanous         }
32*6c038f26SEd Tanous 
33*6c038f26SEd Tanous         auto messageFieldIterator = message.find("Message");
34*6c038f26SEd Tanous         if (messageFieldIterator == message.end())
35*6c038f26SEd Tanous         {
36*6c038f26SEd Tanous             BMCWEB_LOG_CRITICAL("Attempt to add error message without Message");
37*6c038f26SEd Tanous             return;
38*6c038f26SEd Tanous         }
39*6c038f26SEd Tanous         error["code"] = *messageIdIterator;
40*6c038f26SEd Tanous         error["message"] = *messageFieldIterator;
41*6c038f26SEd Tanous     }
42*6c038f26SEd Tanous     else
43*6c038f26SEd Tanous     {
44*6c038f26SEd Tanous         // More than 1 error occurred, so the message has to be generic
45*6c038f26SEd Tanous         error["code"] = std::string(messageVersionPrefix) + "GeneralError";
46*6c038f26SEd Tanous         error["message"] = "A general error has occurred. See Resolution for "
47*6c038f26SEd Tanous                            "information on how to resolve the error.";
48*6c038f26SEd Tanous     }
49*6c038f26SEd Tanous 
50*6c038f26SEd Tanous     // This check could technically be done in the default construction
51*6c038f26SEd Tanous     // branch above, but because we need the pointer to the extended info field
52*6c038f26SEd Tanous     // anyway, it's more efficient to do it here.
53*6c038f26SEd Tanous     auto& extendedInfo = error[messages::messageAnnotation];
54*6c038f26SEd Tanous     if (!extendedInfo.is_array())
55*6c038f26SEd Tanous     {
56*6c038f26SEd Tanous         extendedInfo = nlohmann::json::array();
57*6c038f26SEd Tanous     }
58*6c038f26SEd Tanous 
59*6c038f26SEd Tanous     extendedInfo.push_back(message);
60*6c038f26SEd Tanous }
61*6c038f26SEd Tanous 
moveErrorsToErrorJson(nlohmann::json & target,nlohmann::json & source)62*6c038f26SEd Tanous void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source)
63*6c038f26SEd Tanous {
64*6c038f26SEd Tanous     if (!source.is_object())
65*6c038f26SEd Tanous     {
66*6c038f26SEd Tanous         return;
67*6c038f26SEd Tanous     }
68*6c038f26SEd Tanous     auto errorIt = source.find("error");
69*6c038f26SEd Tanous     if (errorIt == source.end())
70*6c038f26SEd Tanous     {
71*6c038f26SEd Tanous         // caller puts error message in root
72*6c038f26SEd Tanous         messages::addMessageToErrorJson(target, source);
73*6c038f26SEd Tanous         source.clear();
74*6c038f26SEd Tanous         return;
75*6c038f26SEd Tanous     }
76*6c038f26SEd Tanous     auto extendedInfoIt = errorIt->find(messages::messageAnnotation);
77*6c038f26SEd Tanous     if (extendedInfoIt == errorIt->end())
78*6c038f26SEd Tanous     {
79*6c038f26SEd Tanous         return;
80*6c038f26SEd Tanous     }
81*6c038f26SEd Tanous     const nlohmann::json::array_t* extendedInfo =
82*6c038f26SEd Tanous         (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>();
83*6c038f26SEd Tanous     if (extendedInfo == nullptr)
84*6c038f26SEd Tanous     {
85*6c038f26SEd Tanous         source.erase(errorIt);
86*6c038f26SEd Tanous         return;
87*6c038f26SEd Tanous     }
88*6c038f26SEd Tanous     for (const nlohmann::json& message : *extendedInfo)
89*6c038f26SEd Tanous     {
90*6c038f26SEd Tanous         addMessageToErrorJson(target, message);
91*6c038f26SEd Tanous     }
92*6c038f26SEd Tanous     source.erase(errorIt);
93*6c038f26SEd Tanous }
94*6c038f26SEd Tanous 
addMessageToJsonRoot(nlohmann::json & target,const nlohmann::json & message)95*6c038f26SEd Tanous void addMessageToJsonRoot(nlohmann::json& target, const nlohmann::json& message)
96*6c038f26SEd Tanous {
97*6c038f26SEd Tanous     if (!target[messages::messageAnnotation].is_array())
98*6c038f26SEd Tanous     {
99*6c038f26SEd Tanous         // Force object to be an array
100*6c038f26SEd Tanous         target[messages::messageAnnotation] = nlohmann::json::array();
101*6c038f26SEd Tanous     }
102*6c038f26SEd Tanous 
103*6c038f26SEd Tanous     target[messages::messageAnnotation].push_back(message);
104*6c038f26SEd Tanous }
105*6c038f26SEd Tanous 
addMessageToJson(nlohmann::json & target,const nlohmann::json & message,std::string_view fieldPath)106*6c038f26SEd Tanous void addMessageToJson(nlohmann::json& target, const nlohmann::json& message,
107*6c038f26SEd Tanous                       std::string_view fieldPath)
108*6c038f26SEd Tanous {
109*6c038f26SEd Tanous     std::string extendedInfo(fieldPath);
110*6c038f26SEd Tanous     extendedInfo += messages::messageAnnotation;
111*6c038f26SEd Tanous 
112*6c038f26SEd Tanous     nlohmann::json& field = target[extendedInfo];
113*6c038f26SEd Tanous     if (!field.is_array())
114*6c038f26SEd Tanous     {
115*6c038f26SEd Tanous         // Force object to be an array
116*6c038f26SEd Tanous         field = nlohmann::json::array();
117*6c038f26SEd Tanous     }
118*6c038f26SEd Tanous 
119*6c038f26SEd Tanous     // Object exists and it is an array so we can just push in the message
120*6c038f26SEd Tanous     field.push_back(message);
121*6c038f26SEd Tanous }
122*6c038f26SEd Tanous 
123*6c038f26SEd Tanous } // namespace messages
124*6c038f26SEd Tanous } // namespace redfish
125