Browse Source

Merge pull request #11520 from irynamatveieva/fix/aws-lambda-node-timeouts

Aws lambda node: added validation on init
pull/11580/head
Viacheslav Klimov 2 years ago
committed by GitHub
parent
commit
5631b78656
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 10
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/lambda/TbAwsLambdaNode.java
  2. 8
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/lambda/TbAwsLambdaNodeConfiguration.java
  3. 65
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/aws/lambda/TbAwsLambdaNodeTest.java

10
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/lambda/TbAwsLambdaNode.java

@ -35,10 +35,13 @@ import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.dao.exception.DataValidationException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static org.thingsboard.server.dao.service.ConstraintValidator.validateFields;
@Slf4j @Slf4j
@RuleNode( @RuleNode(
type = ComponentType.EXTERNAL, type = ComponentType.EXTERNAL,
@ -62,10 +65,9 @@ public class TbAwsLambdaNode extends TbAbstractExternalNode {
@Override @Override
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
config = TbNodeUtils.convert(configuration, TbAwsLambdaNodeConfiguration.class); config = TbNodeUtils.convert(configuration, TbAwsLambdaNodeConfiguration.class);
if (StringUtils.isBlank(config.getFunctionName())) { String errorPrefix = "'" + ctx.getSelf().getName() + "' node configuration is invalid: ";
throw new TbNodeException("Function name must be set!", true);
}
try { try {
validateFields(config, errorPrefix);
AWSCredentials awsCredentials = new BasicAWSCredentials(config.getAccessKey(), config.getSecretKey()); AWSCredentials awsCredentials = new BasicAWSCredentials(config.getAccessKey(), config.getSecretKey());
client = AWSLambdaAsyncClientBuilder.standard() client = AWSLambdaAsyncClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
@ -74,6 +76,8 @@ public class TbAwsLambdaNode extends TbAbstractExternalNode {
.withConnectionTimeout((int) TimeUnit.SECONDS.toMillis(config.getConnectionTimeout())) .withConnectionTimeout((int) TimeUnit.SECONDS.toMillis(config.getConnectionTimeout()))
.withRequestTimeout((int) TimeUnit.SECONDS.toMillis(config.getRequestTimeout()))) .withRequestTimeout((int) TimeUnit.SECONDS.toMillis(config.getRequestTimeout())))
.build(); .build();
} catch (DataValidationException e) {
throw new TbNodeException(e, true);
} catch (Exception e) { } catch (Exception e) {
throw new TbNodeException(e); throw new TbNodeException(e);
} }

8
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/lambda/TbAwsLambdaNodeConfiguration.java

@ -15,6 +15,8 @@
*/ */
package org.thingsboard.rule.engine.aws.lambda; package org.thingsboard.rule.engine.aws.lambda;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;
import org.thingsboard.rule.engine.api.NodeConfiguration; import org.thingsboard.rule.engine.api.NodeConfiguration;
@ -23,12 +25,18 @@ public class TbAwsLambdaNodeConfiguration implements NodeConfiguration<TbAwsLamb
public static final String DEFAULT_QUALIFIER = "$LATEST"; public static final String DEFAULT_QUALIFIER = "$LATEST";
@NotBlank
private String accessKey; private String accessKey;
@NotBlank
private String secretKey; private String secretKey;
@NotBlank
private String region; private String region;
@NotBlank
private String functionName; private String functionName;
private String qualifier; private String qualifier;
@Min(0)
private int connectionTimeout; private int connectionTimeout;
@Min(0)
private int requestTimeout; private int requestTimeout;
private boolean tellFailureIfFuncThrowsExc; private boolean tellFailureIfFuncThrowsExc;

65
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/aws/lambda/TbAwsLambdaNodeTest.java

@ -41,6 +41,7 @@ import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.TbMsgMetaData;
@ -50,8 +51,8 @@ import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Stream; import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@ -72,13 +73,17 @@ public class TbAwsLambdaNodeTest {
private AWSLambdaAsync clientMock; private AWSLambdaAsync clientMock;
@BeforeEach @BeforeEach
void setUp() { public void setUp() {
node = new TbAwsLambdaNode(); node = new TbAwsLambdaNode();
config = new TbAwsLambdaNodeConfiguration().defaultConfiguration(); config = new TbAwsLambdaNodeConfiguration().defaultConfiguration();
config.setAccessKey("accessKey");
config.setSecretKey("secretKey");
config.setFunctionName("new-function");
} }
@Test @Test
public void verifyDefaultConfig() { public void verifyDefaultConfig() {
config = new TbAwsLambdaNodeConfiguration().defaultConfiguration();
assertThat(config.getAccessKey()).isNull(); assertThat(config.getAccessKey()).isNull();
assertThat(config.getSecretKey()).isNull(); assertThat(config.getSecretKey()).isNull();
assertThat(config.getRegion()).isEqualTo(("us-east-1")); assertThat(config.getRegion()).isEqualTo(("us-east-1"));
@ -94,10 +99,43 @@ public class TbAwsLambdaNodeTest {
@ValueSource(strings = " ") @ValueSource(strings = " ")
public void givenInvalidFunctionName_whenInit_thenThrowsException(String funcName) { public void givenInvalidFunctionName_whenInit_thenThrowsException(String funcName) {
config.setFunctionName(funcName); config.setFunctionName(funcName);
var configuration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); verifyValidationExceptionOnInit();
assertThatThrownBy(() -> node.init(ctx, configuration)) }
.isInstanceOf(TbNodeException.class)
.hasMessage("Function name must be set!"); @ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = " ")
public void givenInvalidAccessKey_whenInit_thenThrowsException(String accessKey) {
config.setAccessKey(accessKey);
verifyValidationExceptionOnInit();
}
@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = " ")
public void givenInvalidSecretAccessKey_whenInit_thenThrowsException(String secretAccessKey) {
config.setSecretKey(secretAccessKey);
verifyValidationExceptionOnInit();
}
@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = " ")
public void givenInvalidRegion_whenInit_thenThrowsException(String region) {
config.setRegion(region);
verifyValidationExceptionOnInit();
}
@Test
public void givenInvalidConnectionTimeout_whenInit_thenThrowsException() {
config.setConnectionTimeout(-100);
verifyValidationExceptionOnInit();
}
@Test
public void givenInvalidRequestTimeout_whenInit_thenThrowsException() {
config.setRequestTimeout(-100);
verifyValidationExceptionOnInit();
} }
@ParameterizedTest @ParameterizedTest
@ -280,10 +318,19 @@ public class TbAwsLambdaNodeTest {
assertThat(throwableCaptor.getValue()).isInstanceOf(AWSLambdaException.class).hasMessageStartingWith(errorMsg); assertThat(throwableCaptor.getValue()).isInstanceOf(AWSLambdaException.class).hasMessageStartingWith(errorMsg);
} }
private void verifyValidationExceptionOnInit() {
RuleNode ruleNode = new RuleNode();
ruleNode.setName("test");
when(ctx.getSelf()).thenReturn(ruleNode);
String errorPrefix = "'test' node configuration is invalid: ";
assertThatThrownBy(() -> node.init(ctx, new TbNodeConfiguration(JacksonUtil.valueToTree(config))))
.isInstanceOf(TbNodeException.class)
.hasMessageContaining(errorPrefix)
.extracting(e -> ((TbNodeException) e).isUnrecoverable())
.isEqualTo(true);
}
private void init() { private void init() {
config.setAccessKey("accessKey");
config.setSecretKey("secretKey");
config.setFunctionName("new-function");
ReflectionTestUtils.setField(node, "client", clientMock); ReflectionTestUtils.setField(node, "client", clientMock);
ReflectionTestUtils.setField(node, "config", config); ReflectionTestUtils.setField(node, "config", config);
} }

Loading…
Cancel
Save