in libminifi/src/agent/JsonSchema.cpp [121:383]
static std::string buildSchema(const std::unordered_map<std::string, std::string>& relationships, const std::string& processors, const std::string& controller_services) {
std::stringstream all_rels;
for (const auto& [name, rels] : relationships) {
all_rels << "\"relationships-" << escape(name) << "\": " << rels << ", ";
}
const auto rpg_property_refs = minifi::RemoteProcessorGroupPort::Properties;
std::vector<core::Property> rpg_properties(rpg_property_refs.begin(), rpg_property_refs.end());
std::stringstream remote_port_props;
writeProperties(rpg_properties, minifi::RemoteProcessorGroupPort::SupportsDynamicProperties, remote_port_props);
std::string process_group_properties = R"(
"Processors": {
"type": "array",
"items": {"$ref": "#/definitions/processor"}
},
"Connections": {
"type": "array",
"items": {"$ref": "#/definitions/connection"}
},
"Controller Services": {
"type": "array",
"items": {"$ref": "#/definitions/controller_service"}
},
"Remote Process Groups": {
"type": "array",
"items": {"$ref": "#/definitions/remote_process_group"}
},
"Process Groups": {
"type": "array",
"items": {"$ref": "#/definitions/simple_process_group"}
},
"Funnels": {
"type": "array",
"items": {"$ref": "#/definitions/funnel"}
},
"Input Ports": {
"type": "array",
"items": {"$ref": "#/definitions/port"}
},
"Output Ports": {
"type": "array",
"items": {"$ref": "#/definitions/port"}
}
)";
std::stringstream cron_pattern;
{
const char* all = "\\\\*";
const char* any = "\\\\?";
const char* increment = "(-?[0-9]+)";
const char* secs = "([0-5]?[0-9])";
const char* mins = "([0-5]?[0-9])";
const char* hours = "(1?[0-9]|2[0-3])";
const char* days = "([1-2]?[0-9]|3[0-1])";
const char* months = "([0-9]|1[0-2]|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)";
const char* weekdays = "([0-7]|sun|mon|tue|wed|thu|fri|sat)";
const char* years = "([0-9]+)";
auto makeCommon = [&] (const char* pattern) {
std::stringstream common;
common << all << "|" << any
<< "|" << pattern << "(," << pattern << ")*"
<< "|" << pattern << "-" << pattern
<< "|" << "(" << all << "|" << pattern << ")" << "/" << increment;
return std::move(common).str();
};
cron_pattern << "^"
<< "(" << makeCommon(secs) << ")"
<< " (" << makeCommon(mins) << ")"
<< " (" << makeCommon(hours) << ")"
<< " (" << makeCommon(days) << "|LW|L|L-" << days << "|" << days << "W" << ")"
<< " (" << makeCommon(months) << ")"
<< " (" << makeCommon(weekdays) << "|" << weekdays << "?L|" << weekdays << "#" << "[1-5]" << ")"
<< "( (" << makeCommon(years) << "))?"
<< "$";
}
// the schema specification does not allow case-insensitive regex
std::stringstream cron_pattern_case_insensitive;
for (char ch : cron_pattern.str()) {
if (std::isalpha(static_cast<unsigned char>(ch))) {
cron_pattern_case_insensitive << "["
<< static_cast<char>(std::tolower(static_cast<unsigned char>(ch)))
<< static_cast<char>(std::toupper(static_cast<unsigned char>(ch)))
<< "]";
} else {
cron_pattern_case_insensitive << ch;
}
}
return prettifyJson(R"(
{
"$schema": "http://json-schema.org/draft-07/schema",
"definitions": {)" + std::move(all_rels).str() + R"(
"datasize": {
"type": "string",
"pattern": "^\\s*[0-9]+\\s*(B|K|M|G|T|P|KB|MB|GB|TB|PB)\\s*$"
},
"uuid": {
"type": "string",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
"default": "00000000-0000-0000-0000-000000000000"
},
"cron_pattern": {
"type": "string",
"pattern": ")" + std::move(cron_pattern_case_insensitive).str() + R"("
},
"remote_port": {
"type": "object",
"required": ["name", "id", "Properties"],
"properties": {
"name": {"type": "string"},
"id": {"$ref": "#/definitions/uuid"},
"max concurrent tasks": {"type": "integer"},
)" + std::move(remote_port_props).str() + R"(
}
},
"port": {
"type": "object",
"required": ["name", "id"],
"properties": {
"name": {"type": "string"},
"id": {"$ref": "#/definitions/uuid"}
}
},
"time": {
"type": "string",
"pattern": "^\\s*[0-9]+\\s*(ns|nano|nanos|nanoseconds|nanosecond|us|micro|micros|microseconds|microsecond|msec|ms|millisecond|milliseconds|msecs|millis|milli|sec|s|second|seconds|secs|min|m|mins|minute|minutes|h|hr|hour|hrs|hours|d|day|days)\\s*$"
},
"controller_service": {"allOf": [{
"type": "object",
"required": ["name", "id", "class"],
"properties": {
"name": {"type": "string"},
"class": {"type": "string"},
"id": {"$ref": "#/definitions/uuid"}
}
}, )" + controller_services + R"(]},
"processor": {"allOf": [{
"type": "object",
"required": ["name", "id", "class", "scheduling strategy"],
"additionalProperties": false,
"properties": {
"name": {"type": "string"},
"id": {"$ref": "#/definitions/uuid"},
"class": {"type": "string"},
"max concurrent tasks": {"type": "integer", "default": 1},
"penalization period": {"$ref": "#/definitions/time"},
"yield period": {"$ref": "#/definitions/time"},
"run duration nanos": {"$ref": "#/definitions/time"},
"Properties": {},
"scheduling strategy": {"enum": ["EVENT_DRIVEN", "TIMER_DRIVEN", "CRON_DRIVEN"]},
"scheduling period": {},
"auto-terminated relationships list": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true
}
}}, {
"if": {"properties": {"scheduling strategy": {"const": "EVENT_DRIVEN"}}},
"then": {"properties": {"scheduling period": false}}
}, {
"if": {"properties": {"scheduling strategy": {"const": "TIMER_DRIVEN"}}},
"then": {"required": ["scheduling period"], "properties": {"scheduling period": {"$ref": "#/definitions/time"}}}
}, {
"if": {"properties": {"scheduling strategy": {"const": "CRON_DRIVEN"}}},
"then": {"required": ["scheduling period"], "properties": {"scheduling period": {"$ref": "#/definitions/cron_pattern"}}}
})" + (!processors.empty() ? ", " : "") + processors + R"(]
},
"remote_process_group": {"allOf": [{
"type": "object",
"required": ["name", "id", "Input Ports"],
"properties": {
"name": {"type": "string"},
"id": {"$ref": "#/definitions/uuid"},
"url": {"type": "string"},
"yield period": {"$ref": "#/definitions/time"},
"timeout": {"$ref": "#/definitions/time"},
"local network interface": {"type": "string"},
"transport protocol": {"enum": ["HTTP", "RAW"]},
"Input Ports": {
"type": "array",
"items": {"$ref": "#/definitions/remote_port"}
},
"Output Ports": {
"type": "array",
"items": {"$ref": "#/definitions/remote_port"}
}
}
}, {
"if": {"properties": {"transport protocol": {"const": "HTTP"}}},
"then": {"properties": {
"proxy host": {"type": "string"},
"proxy user": {"type": "string"},
"proxy password": {"type": "string"},
"proxy port": {"type": "integer"}
}}
}]},
"connection": {
"type": "object",
"additionalProperties": false,
"required": ["name", "id", "source id", "source relationship names", "destination id"],
"properties": {
"name": {"type": "string"},
"id": {"$ref": "#/definitions/uuid"},
"source name": {"type": "string"},
"source id": {"$ref": "#/definitions/uuid"},
"source relationship names": {
"type": "array",
"items": {"type": "string"}
},
"destination name": {"type": "string"},
"destination id": {"$ref": "#/definitions/uuid"},
"max work queue size": {"type": "integer", "default": 10000},
"max work queue data size": {"$ref": "#/definitions/datasize", "default": "10 MB"},
"flowfile expiration": {"$ref": "#/definitions/time", "default": "0 ms"}
}
},
"funnel": {
"type": "object",
"required": ["id"],
"properties": {
"id": {"$ref": "#/definitions/uuid"},
"name": {"type": "string"}
}
},
"simple_process_group": {
"type": "object",
"required": ["name"],
"additionalProperties": false,
"properties": {
"name": {"type": "string"},
"version": {"type": "integer"},
)" + process_group_properties + R"(
}
},
"root_process_group": {
"type": "object",
"required": ["Flow Controller"],
"additionalProperties": false,
"properties": {
"$schema": {"type": "string"},
"Flow Controller": {
"type": "object",
"required": ["name"],
"properties": {
"name": {"type": "string"},
"version": {"type": "integer"}
}
},
)" + process_group_properties + R"(
}
}
},
"$ref": "#/definitions/root_process_group"
}
)");
}