Skip to content

Commit

Permalink
Extract AWS specific rules engine functions
Browse files Browse the repository at this point in the history
This commit pulls the AWS specific rules engine functions into a new
package, smithy-aws-rules-engine. This includes parseArn, partition,
and isVirtualHostableS3Bucket. The partition loading has also moved
to this package, including its data types.

Relevant tests were migrated. Behavior that was only possible to
validate using the parseArn function have been moved, even if the
behavior is not AWS specific. Tests that used AWS functions but did
not require it were updated to be agnostic.
  • Loading branch information
kstich committed Jun 14, 2023
1 parent 8fc4e78 commit 78dda8d
Show file tree
Hide file tree
Showing 58 changed files with 184 additions and 127 deletions.
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ include ":smithy-aws-cloudformation-traits"
include ":smithy-aws-cloudformation"
include ":smithy-validation-model"
include ":smithy-rules-engine"
include ":smithy-aws-rules-engine"
17 changes: 17 additions & 0 deletions smithy-aws-rules-engine/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

description = "AWS specific components for the Smithy rules engine"

ext {
displayName = "Smithy :: AWS Rules Components"
moduleName = "software.amazon.smithy.aws.rulesengine"
}

dependencies {
api project(":smithy-rules-engine")
api project(":smithy-model")
api project(":smithy-utils")
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.impl;
package software.amazon.smithy.aws.rulesengine.language.functions;

import java.util.Arrays;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.stdlib;
package software.amazon.smithy.aws.rulesengine.language.functions;

import java.util.Arrays;
import java.util.List;
Expand All @@ -29,7 +29,7 @@
* An AWS rule-set function for determining whether a given string can be promoted to an S3 virtual bucket host label.
*/
@SmithyUnstableApi
public class AwsIsVirtualHostableS3Bucket extends LibraryFunction {
public final class AwsIsVirtualHostableS3Bucket extends LibraryFunction {
public static final String ID = "aws.isVirtualHostableS3Bucket";
private static final Definition DEFINITION = new Definition();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.stdlib;
package software.amazon.smithy.aws.rulesengine.language.functions;

import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -24,13 +24,13 @@
import java.util.Map;
import java.util.ServiceLoader;
import java.util.regex.Pattern;
import software.amazon.smithy.aws.rulesengine.language.functions.partition.Partition;
import software.amazon.smithy.aws.rulesengine.language.functions.partition.PartitionDataProvider;
import software.amazon.smithy.aws.rulesengine.language.functions.partition.PartitionOutputs;
import software.amazon.smithy.aws.rulesengine.language.functions.partition.Partitions;
import software.amazon.smithy.rulesengine.language.evaluation.type.RecordType;
import software.amazon.smithy.rulesengine.language.evaluation.type.Type;
import software.amazon.smithy.rulesengine.language.evaluation.value.Value;
import software.amazon.smithy.rulesengine.language.model.Partition;
import software.amazon.smithy.rulesengine.language.model.PartitionOutputs;
import software.amazon.smithy.rulesengine.language.model.Partitions;
import software.amazon.smithy.rulesengine.language.stdlib.partition.PartitionDataProvider;
import software.amazon.smithy.rulesengine.language.syntax.Identifier;
import software.amazon.smithy.rulesengine.language.syntax.expressions.ExpressionVisitor;
import software.amazon.smithy.rulesengine.language.syntax.expressions.functions.FunctionDefinition;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.stdlib;
package software.amazon.smithy.aws.rulesengine.language.functions;

import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -22,7 +22,6 @@
import software.amazon.smithy.rulesengine.language.evaluation.type.RecordType;
import software.amazon.smithy.rulesengine.language.evaluation.type.Type;
import software.amazon.smithy.rulesengine.language.evaluation.value.Value;
import software.amazon.smithy.rulesengine.language.impl.AwsArn;
import software.amazon.smithy.rulesengine.language.syntax.Identifier;
import software.amazon.smithy.rulesengine.language.syntax.expressions.ExpressionVisitor;
import software.amazon.smithy.rulesengine.language.syntax.expressions.functions.FunctionDefinition;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,17 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.stdlib.partition;
package software.amazon.smithy.aws.rulesengine.language.functions.partition;

import java.io.InputStream;
import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.rulesengine.language.model.Partitions;
import software.amazon.smithy.utils.SmithyUnstableApi;

@SmithyUnstableApi
public final class DefaultPartitionDataProvider implements PartitionDataProvider {
private static final String DEFAULT_PARTITIONS_DATA =
"/software/amazon/smithy/rulesengine/language/partitions.json";

@Override
public Partitions loadPartitions() {
InputStream json = DefaultPartitionDataProvider.class.getResourceAsStream(DEFAULT_PARTITIONS_DATA);
InputStream json = DefaultPartitionDataProvider.class.getResourceAsStream("partitions.json");
return Partitions.fromNode(Node.parse(json));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.model;
package software.amazon.smithy.aws.rulesengine.language.functions.partition;

import java.util.List;
import java.util.Map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.stdlib.partition;
package software.amazon.smithy.aws.rulesengine.language.functions.partition;

import software.amazon.smithy.rulesengine.language.model.Partitions;
import software.amazon.smithy.utils.SmithyUnstableApi;

@SmithyUnstableApi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.model;
package software.amazon.smithy.aws.rulesengine.language.functions.partition;

import java.util.List;
import java.util.Objects;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.model;
package software.amazon.smithy.aws.rulesengine.language.functions.partition;

import java.util.List;
import java.util.Objects;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.model;
package software.amazon.smithy.aws.rulesengine.language.functions.partition;

import software.amazon.smithy.model.FromSourceLocation;
import software.amazon.smithy.model.SourceLocation;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
software.amazon.smithy.aws.rulesengine.language.functions.partition.DefaultPartitionDataProvider
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
software.amazon.smithy.aws.rulesengine.language.functions.AwsIsVirtualHostableS3Bucket$Definition
software.amazon.smithy.aws.rulesengine.language.functions.AwsPartition$Definition
software.amazon.smithy.aws.rulesengine.language.functions.ParseArn$Definition
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.impl;
package software.amazon.smithy.aws.rulesengine.language.functions;

import static org.junit.jupiter.api.Assertions.assertEquals;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.functions;
package software.amazon.smithy.aws.rulesengine.language.functions;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
Expand All @@ -22,7 +22,6 @@
import org.junit.jupiter.api.Test;
import software.amazon.smithy.rulesengine.language.evaluation.RuleEvaluator;
import software.amazon.smithy.rulesengine.language.evaluation.value.RecordValue;
import software.amazon.smithy.rulesengine.language.stdlib.AwsPartition;
import software.amazon.smithy.rulesengine.language.syntax.expressions.Expression;
import software.amazon.smithy.rulesengine.language.syntax.expressions.functions.FunctionNode;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package software.amazon.smithy.aws.rulesengine.language.functions;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.rulesengine.language.EndpointRuleSet;
import software.amazon.smithy.rulesengine.language.error.RuleError;
import software.amazon.smithy.utils.IoUtils;
import software.amazon.smithy.utils.Pair;

public class IntegrationTest {
public static List<Pair<Node, String>> invalidRules() throws IOException {
try (Stream<Path> paths = Files.list(
Paths.get(IntegrationTest.class.getResource("invalid-rules").getPath()))
) {
return paths.map(path -> {
try {
String pathContents = IoUtils.toUtf8String(new FileInputStream(path.toFile()));
Node content = Node.parseJsonWithComments(pathContents,
path.subpath(path.getNameCount() - 2, path.getNameCount())
.toString().replace("\\", "/"));

List<String> commentLines = new ArrayList<>();
for (String line : pathContents.split(System.lineSeparator())) {
if (line.startsWith("//")) {
commentLines.add(line.substring(3));
}
}

return Pair.of(content, String.join("\n", commentLines));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toList());
}
}

@ParameterizedTest
@MethodSource("invalidRules")
public void checkInvalidRules(Pair<Node, String> validationTestCase) {
RuleError error = assertThrows(RuleError.class, () -> EndpointRuleSet.fromNode(validationTestCase.getLeft()));
assertEquals(validationTestCase.getRight(), error.toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package software.amazon.smithy.aws.rulesengine.language.functions;

import java.util.concurrent.Callable;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import software.amazon.smithy.model.validation.testrunner.SmithyTestCase;
import software.amazon.smithy.model.validation.testrunner.SmithyTestSuite;

public class TestRunnerTest {
public static Stream<?> source() {
return SmithyTestSuite.defaultParameterizedTestSource(TestRunnerTest.class);
}

@ParameterizedTest(name = "{0}")
@MethodSource("source")
public void testRunner(String filename, Callable<SmithyTestCase.Result> callable) throws Exception {
callable.call();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.rulesengine.language.model;
package software.amazon.smithy.aws.rulesengine.language.functions.partition;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
Expand All @@ -22,7 +22,6 @@
import software.amazon.smithy.model.node.Node;

public class PartitionsTest {

@Test
public void roundtripsPartitions() {
Node parsedNode = Node.parse(PartitionsTest.class.getResourceAsStream("complete-partitions.json"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import software.amazon.smithy.rulesengine.language.evaluation.type.Type;
import software.amazon.smithy.rulesengine.language.evaluation.value.Value;
import software.amazon.smithy.rulesengine.language.syntax.Identifier;
import software.amazon.smithy.rulesengine.language.syntax.expressions.ExpressionVisitor;
import software.amazon.smithy.utils.MapUtils;
import software.amazon.smithy.utils.SmithyUnstableApi;
import software.amazon.smithy.utils.StringUtils;

Expand Down Expand Up @@ -63,15 +64,13 @@ public List<Type> getArguments() {

@Override
public Type getReturnType() {
return Type.optionalType(Type.recordType(
MapUtils.of(
SCHEME, Type.stringType(),
AUTHORITY, Type.stringType(),
PATH, Type.stringType(),
NORMALIZED_PATH, Type.stringType(),
IS_IP, Type.booleanType()
)
));
Map<Identifier, Type> types = new LinkedHashMap<>();
types.put(SCHEME, Type.stringType());
types.put(AUTHORITY, Type.stringType());
types.put(PATH, Type.stringType());
types.put(NORMALIZED_PATH, Type.stringType());
types.put(IS_IP, Type.booleanType());
return Type.optionalType(Type.recordType(types));
}

@Override
Expand Down Expand Up @@ -119,13 +118,13 @@ public Value evaluate(List<Value> arguments) {
normalizedPath = builder.toString();
}

return Value.recordValue(MapUtils.of(
SCHEME, Value.stringValue(parsed.getProtocol()),
AUTHORITY, Value.stringValue(parsed.getAuthority()),
PATH, Value.stringValue(path),
NORMALIZED_PATH, Value.stringValue(normalizedPath),
IS_IP, Value.booleanValue(isIpAddr)
));
Map<Identifier, Value> values = new LinkedHashMap<>();
values.put(SCHEME, Value.stringValue(parsed.getProtocol()));
values.put(AUTHORITY, Value.stringValue(parsed.getAuthority()));
values.put(PATH, Value.stringValue(path));
values.put(NORMALIZED_PATH, Value.stringValue(normalizedPath));
values.put(IS_IP, Value.booleanValue(isIpAddr));
return Value.recordValue(values);
} catch (MalformedURLException e) {
return Value.emptyValue();
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
software.amazon.smithy.rulesengine.language.stdlib.AwsIsVirtualHostableS3Bucket$Definition
software.amazon.smithy.rulesengine.language.stdlib.AwsPartition$Definition
software.amazon.smithy.rulesengine.language.stdlib.ParseArn$Definition
software.amazon.smithy.rulesengine.language.syntax.expressions.functions.BooleanEquals$Definition
software.amazon.smithy.rulesengine.language.syntax.expressions.functions.GetAttr$Definition
software.amazon.smithy.rulesengine.language.syntax.expressions.functions.IsSet$Definition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ void introspectCorrectTypesForFunctions() {
void introspectCorrectTypesForGetAttr() {
EndpointRuleSet endpointRuleSet = EndpointRuleSet.fromNode(Node.parse(IoUtils.readUtf8Resource(
TypeIntrospectionTest.class, "get-attr-type-inference.json")));
// bucketArn.resourceId[2]
// bucketUrl.authority
Type actualType = endpointRuleSet.getRules().get(0).getConditions().get(2).getFn().type();
assertEquals(actualType, Type.optionalType(Type.stringType()));
assertEquals(Type.stringType(), actualType);
}
}
Loading

0 comments on commit 78dda8d

Please sign in to comment.