Browse Source

Fix RuleChainMetadata for older Edge versions

- added new problem node
- added test
- refactoring
pull/12843/head
yevhenii 2 years ago
parent
commit
4e51398cc4
  1. 49
      application/src/main/java/org/thingsboard/server/service/edge/EdgeMsgConstructorUtils.java
  2. 146
      application/src/test/java/org/thingsboard/server/service/edge/EdgeMsgConstructorUtilsTest.java

49
application/src/main/java/org/thingsboard/server/service/edge/EdgeMsgConstructorUtils.java

@ -25,6 +25,10 @@ import com.google.gson.JsonPrimitive;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.action.TbSaveToCustomCassandraTableNode;
import org.thingsboard.rule.engine.aws.lambda.TbAwsLambdaNode;
import org.thingsboard.rule.engine.rest.TbSendRestApiCallReplyNode;
import org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode;
import org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode; import org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode;
import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.common.adaptor.JsonConverter;
import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Customer;
@ -117,11 +121,25 @@ import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.service.edge.rpc.utils.EdgeVersionUtils; import org.thingsboard.server.service.edge.rpc.utils.EdgeVersionUtils;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
@Slf4j @Slf4j
public class EdgeMsgConstructorUtils { public class EdgeMsgConstructorUtils {
public static final Map<String, String> NODE_TO_IGNORE_PARAM_FOR_OLD_EDGE_VERSION = Map.of(
TbMsgTimeseriesNode.class.getName(), "processingSettings",
TbMsgAttributesNode.class.getName(), "processingSettings",
TbSaveToCustomCassandraTableNode.class.getName(), "defaultTtl"
);
//added in edge version 3.8.0
public static final Set<String> MISSING_NODES_IN_VERSION_37 = Set.of(
TbSendRestApiCallReplyNode.class.getName(),
TbAwsLambdaNode.class.getName()
);
public static AlarmUpdateMsg constructAlarmUpdatedMsg(UpdateMsgType msgType, Alarm alarm) { public static AlarmUpdateMsg constructAlarmUpdatedMsg(UpdateMsgType msgType, Alarm alarm) {
return AlarmUpdateMsg.newBuilder().setMsgType(msgType) return AlarmUpdateMsg.newBuilder().setMsgType(msgType)
@ -431,25 +449,36 @@ public class EdgeMsgConstructorUtils {
} }
private static String filterMetadataForOldEdgeVersions(RuleChainMetaData ruleChainMetaData, EdgeVersion edgeVersion) { private static String filterMetadataForOldEdgeVersions(RuleChainMetaData ruleChainMetaData, EdgeVersion edgeVersion) {
if (EdgeVersionUtils.isEdgeVersionOlderThan(edgeVersion, EdgeVersion.V_3_9_0)) { JsonNode jsonNode = JacksonUtil.valueToTree(ruleChainMetaData);
JsonNode jsonNode = JacksonUtil.valueToTree(ruleChainMetaData); JsonNode nodes = jsonNode.get("nodes");
JsonNode nodes = jsonNode.get("nodes");
if (EdgeVersionUtils.isEdgeVersionOlderThan(edgeVersion, EdgeVersion.V_3_8_0)) {
Iterator<JsonNode> iterator = nodes.iterator();
while (iterator.hasNext()) {
JsonNode node = iterator.next();
for (JsonNode node : nodes) { String type = node.get("type").asText();
if (node.isObject()) { if (MISSING_NODES_IN_VERSION_37.contains(type)) {
removeIncompatibleFields((ObjectNode) node); iterator.remove();
} }
} }
}
if (EdgeVersionUtils.isEdgeVersionOlderThan(edgeVersion, EdgeVersion.V_3_9_0)) {
nodes.forEach(EdgeMsgConstructorUtils::changeRuleNodeConfigForOldEdgeVersion);
return JacksonUtil.toString(jsonNode); return JacksonUtil.toString(jsonNode);
} else { } else {
return JacksonUtil.toString(ruleChainMetaData); return JacksonUtil.toString(ruleChainMetaData);
} }
} }
private static void removeIncompatibleFields(ObjectNode node) { private static void changeRuleNodeConfigForOldEdgeVersion(JsonNode node) {
if (TbMsgTimeseriesNode.class.getName().equals(node.get("type").asText())) { if (node.isObject()) {
if (node.has("configuration") && node.get("configuration").isObject()) { JsonNode configurationNode = node.get("configuration");
((ObjectNode) node.get("configuration")).remove("processingSettings"); if (configurationNode != null && configurationNode.isObject() &&
NODE_TO_IGNORE_PARAM_FOR_OLD_EDGE_VERSION.containsKey(node.get("type").asText())) {
((ObjectNode) configurationNode).remove(NODE_TO_IGNORE_PARAM_FOR_OLD_EDGE_VERSION.get(node.get("type").asText()));
} }
} }
} }

146
application/src/test/java/org/thingsboard/server/service/edge/EdgeMsgConstructorUtilsTest.java

@ -15,9 +15,20 @@
*/ */
package org.thingsboard.server.service.edge; package org.thingsboard.server.service.edge;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.action.TbSaveToCustomCassandraTableNode;
import org.thingsboard.rule.engine.action.TbSaveToCustomCassandraTableNodeConfiguration;
import org.thingsboard.rule.engine.api.NodeConfiguration;
import org.thingsboard.rule.engine.aws.lambda.TbAwsLambdaNode;
import org.thingsboard.rule.engine.aws.lambda.TbAwsLambdaNodeConfiguration;
import org.thingsboard.rule.engine.rest.TbSendRestApiCallReplyNode;
import org.thingsboard.rule.engine.rest.TbSendRestApiCallReplyNodeConfiguration;
import org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode;
import org.thingsboard.rule.engine.telemetry.TbMsgAttributesNodeConfiguration;
import org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode;
import org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNodeConfiguration; import org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNodeConfiguration;
import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.rule.RuleNode;
@ -26,66 +37,129 @@ import org.thingsboard.server.gen.edge.v1.RuleChainMetadataUpdateMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType; import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.service.edge.rpc.utils.EdgeVersionUtils; import org.thingsboard.server.service.edge.rpc.utils.EdgeVersionUtils;
import java.util.Collections; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static org.thingsboard.server.service.edge.EdgeMsgConstructorUtils.MISSING_NODES_IN_VERSION_37;
import static org.thingsboard.server.service.edge.EdgeMsgConstructorUtils.NODE_TO_IGNORE_PARAM_FOR_OLD_EDGE_VERSION;
@Slf4j
public class EdgeMsgConstructorUtilsTest { public class EdgeMsgConstructorUtilsTest {
private static final int CONFIGURATION_VERSION = 5; private static final int CONFIGURATION_VERSION = 5;
public static final List<EdgeVersion> TEST_SUPPORTED_EDGE_VERSIONS = Arrays.asList(
EdgeVersion.V_4_0_0, EdgeVersion.V_3_9_0, EdgeVersion.V_3_8_0, EdgeVersion.V_3_7_0
);
private static final Map<NodeConfiguration, String> CONFIG_TO_NODE_NAME = Map.of(
new TbMsgTimeseriesNodeConfiguration(), TbMsgTimeseriesNode.class.getName(),
new TbMsgAttributesNodeConfiguration(), TbMsgAttributesNode.class.getName(),
new TbSaveToCustomCassandraTableNodeConfiguration(), TbSaveToCustomCassandraTableNode.class.getName()
);
private static final Map<String, Integer> NODE_TO_CONFIG_PARAMS_COUNT = Map.of(
TbMsgTimeseriesNode.class.getName(), 3,
TbMsgAttributesNode.class.getName(), 5,
TbSaveToCustomCassandraTableNode.class.getName(), 3
);
private static final Map<NodeConfiguration, String> CONFIG_TO_MISS_NODE_FOR_OLD_EDGE = Map.of(
new TbSendRestApiCallReplyNodeConfiguration(), TbSendRestApiCallReplyNode.class.getName(),
new TbAwsLambdaNodeConfiguration(), TbAwsLambdaNode.class.getName()
);
@Test @Test
public void testRuleChainMetadataUpdateMsgForAllEdgeVersions() { public void testRuleChainMetadataUpdateMsgForOldEdgeVersions() {
// GIVEN // GIVEN
RuleChainMetaData metaData = createIncompatibleRuleNodesForOldEdge(); RuleChainMetaData metaData = createMetadataWithProblemNodes(CONFIG_TO_NODE_NAME);
// WHEN TEST_SUPPORTED_EDGE_VERSIONS.forEach(edgeVersion -> {
RuleNode ruleNode_V_4_0_0 = getRuleNodeFromMetadataUpdateMessage(metaData, EdgeVersion.V_4_0_0); // WHEN
RuleNode ruleNode_V_3_9_0 = getRuleNodeFromMetadataUpdateMessage(metaData, EdgeVersion.V_3_9_0); List<RuleNode> ruleNodes = getRuleNodesFromUpdateMsg(metaData, edgeVersion);
RuleNode ruleNode_V_3_8_0 = getRuleNodeFromMetadataUpdateMessage(metaData, EdgeVersion.V_3_8_0);
RuleNode ruleNode_V_3_7_0 = getRuleNodeFromMetadataUpdateMessage(metaData, EdgeVersion.V_3_7_0); // THEN
validateRuleNodeConfig(ruleNodes, edgeVersion);
// THEN });
assertRuleNodeConfiguration(ruleNode_V_4_0_0, EdgeVersion.V_4_0_0);
assertRuleNodeConfiguration(ruleNode_V_3_9_0, EdgeVersion.V_3_9_0);
assertRuleNodeConfiguration(ruleNode_V_3_8_0, EdgeVersion.V_3_8_0);
assertRuleNodeConfiguration(ruleNode_V_3_7_0, EdgeVersion.V_3_7_0);
} }
private RuleChainMetaData createIncompatibleRuleNodesForOldEdge() { @Test
public void testRuleChainMetadataWithMissingNodeForOldEdgeVersions() {
// GIVEN
RuleChainMetaData metaData = createMetadataWithProblemNodes(CONFIG_TO_MISS_NODE_FOR_OLD_EDGE);
TEST_SUPPORTED_EDGE_VERSIONS.forEach(edgeVersion -> {
// WHEN
List<RuleNode> ruleNodes = getRuleNodesFromUpdateMsg(metaData, edgeVersion);
// THEN
boolean isOldEdge = EdgeVersionUtils.isEdgeVersionOlderThan(edgeVersion, EdgeVersion.V_3_8_0);
if (isOldEdge) {
Assert.assertTrue("Rule Node must be empty", ruleNodes.isEmpty());
} else {
Assert.assertEquals(MISSING_NODES_IN_VERSION_37.size(), ruleNodes.size());
}
});
}
private RuleChainMetaData createMetadataWithProblemNodes(Map<NodeConfiguration, String> nodeMap) {
RuleChainMetaData ruleChainMetaData = new RuleChainMetaData(); RuleChainMetaData ruleChainMetaData = new RuleChainMetaData();
List<RuleNode> ruleNodes = new ArrayList<>();
nodeMap.entrySet().forEach(configToNodeName -> {
RuleNode ruleNode = new RuleNode();
RuleNode ruleNode1 = new RuleNode(); ruleNode.setName(configToNodeName.getValue());
ruleNode1.setName("TbMsgTimeseriesNode"); ruleNode.setType(configToNodeName.getValue());
ruleNode1.setType(org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode.class.getName()); ruleNode.setConfigurationVersion(CONFIGURATION_VERSION);
ruleNode1.setConfigurationVersion(CONFIGURATION_VERSION); ruleNode.setConfiguration(JacksonUtil.valueToTree(configToNodeName.getKey().defaultConfiguration()));
ruleNode1.setConfiguration(JacksonUtil.valueToTree(new TbMsgTimeseriesNodeConfiguration().defaultConfiguration()));
ruleNodes.add(ruleNode);
});
ruleChainMetaData.setFirstNodeIndex(0); ruleChainMetaData.setFirstNodeIndex(0);
ruleChainMetaData.setNodes(Collections.singletonList(ruleNode1)); ruleChainMetaData.setNodes(ruleNodes);
return ruleChainMetaData; return ruleChainMetaData;
} }
private List<RuleNode> getRuleNodesFromUpdateMsg(RuleChainMetaData metaData, EdgeVersion edgeVersion) {
private RuleNode getRuleNodeFromMetadataUpdateMessage(RuleChainMetaData metaData, EdgeVersion edgeVersion) {
RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg =
EdgeMsgConstructorUtils.constructRuleChainMetadataUpdatedMsg(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, metaData, edgeVersion); EdgeMsgConstructorUtils.constructRuleChainMetadataUpdatedMsg(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, metaData, edgeVersion);
RuleChainMetaData ruleChainMetaData = JacksonUtil.fromString(ruleChainMetadataUpdateMsg.getEntity(), RuleChainMetaData.class, true); RuleChainMetaData ruleChainMetaData = JacksonUtil.fromString(ruleChainMetadataUpdateMsg.getEntity(), RuleChainMetaData.class, true);
Assert.assertNotNull("RuleChainMetaData is null", ruleChainMetaData); Assert.assertNotNull("RuleChainMetaData is null", ruleChainMetaData);
RuleNode ruleNode = ruleChainMetaData.getNodes().stream().findFirst().orElse(null); return ruleChainMetaData.getNodes();
Assert.assertNotNull("RuleNode is null for Edge version " + edgeVersion, ruleNode); }
Assert.assertNotNull("Configuration is null for Edge version " + edgeVersion, ruleNode.getConfiguration());
return ruleNode; private void validateRuleNodeConfig(List<RuleNode> ruleNodes, EdgeVersion edgeVersion) {
ruleNodes.forEach(ruleNode -> {
int ruleNodeConfigAmount = NODE_TO_CONFIG_PARAMS_COUNT.get(ruleNode.getName());
boolean isOldEdge = EdgeVersionUtils.isEdgeVersionOlderThan(edgeVersion, EdgeVersion.V_3_9_0);
int expectedConfigAmount = isOldEdge ? ruleNodeConfigAmount - 1 : ruleNodeConfigAmount;
boolean includeConfigParam = !isOldEdge;
validateParams(ruleNode, expectedConfigAmount, includeConfigParam);
});
} }
private void assertRuleNodeConfiguration(RuleNode ruleNode, EdgeVersion edgeVersion) { private void validateParams(RuleNode ruleNode, int expectedConfigAmount, boolean includeConfigParam) {
if (EdgeVersionUtils.isEdgeVersionOlderThan(edgeVersion, EdgeVersion.V_3_9_0)) { String ignoreConfigParam = NODE_TO_IGNORE_PARAM_FOR_OLD_EDGE_VERSION.get(ruleNode.getName());
Assert.assertEquals("Unexpected config size", 2, ruleNode.getConfiguration().size());
Assert.assertFalse("Unexpected field 'processingSettings'", ruleNode.getConfiguration().has("processingSettings")); Assert.assertEquals(
}else{ String.format("Expected %d config params for ruleNode '%s', but found %d", expectedConfigAmount, ruleNode.getName(), ruleNode.getConfiguration().size()),
Assert.assertEquals("Unexpected config size", 3, ruleNode.getConfiguration().size()); expectedConfigAmount, ruleNode.getConfiguration().size()
Assert.assertTrue("Missing field 'processingSettings'", ruleNode.getConfiguration().has("processingSettings")); );
}
boolean hasIgnoredField = ruleNode.getConfiguration().has(ignoreConfigParam);
Assert.assertEquals(
String.format("Field '%s' for ruleNode '%s' should %s be present", ignoreConfigParam, ruleNode.getName(), includeConfigParam ? "not" : ""),
includeConfigParam, hasIgnoredField
);
} }
} }

Loading…
Cancel
Save