Skip to content

[WIP] Implement aws.IsVirtualHostableS3Bucket function. #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* 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.rulesengine.customize;

import software.amazon.smithy.rulesengine.language.EndpointRuleset;
import software.amazon.smithy.rulesengine.traits.EndpointTestsTrait;

/**
* Customize generated EndpointRulesets and EndpointTests.
* <p>
* To customize the Endpoint rules for a service, implement this interface
* and update the `rule-set-synthesis-configuration.json` to add the
* fully qualified classname of your implementation as `customization` on the service definition.
*/
public interface EndpointRulesetCustomization {

/**
* Customize the base, generated EndpointRuleset (the ruleset generated from endpoints.json).
* <p>
* Most Customizations will need to add additional rules and parameters. The generated rules
* contains a single, top level TreeRule which you can use to insert additional rules into:
* <pre>{@code
* public EndpointRuleset customizeRuleset(EndpointRuleset ruleset) {
* assert ruleset.getRules().size() == 1;
* TreeRule rootRule = (TreeRule) ruleset.getRules().get(0);
*
* List<Rule> subRules = new ArrayList<>();
* // Add our new custom rules first
* subRules.add(myNewCustomRules());
* // ensure the base/generated rule are added
* subRules.addAll(ruleset.getRules());
*
* // create a new root rule from the old rule (with our new subRules)
* Rule newRootRule = TreeRule.builder()
* .conditions(rootRule.getConditions())
* .treeRule(subRules);
*
* // add a new custom parameter
* Parameters newParameters = ruleset.getParameters().toBuilder()
* .addParameter(myNewParameter()).build();
*
* // use the Rulset builder with our modified parameters and rules
* return EndpointRuleset.builder()
* .parameters(newParameters)
* .addRule(newRootRule)
* .build();
* }
* }</pre>
*
* @param ruleset the base generated ruleset
* @return ruleset customized for the service
*/
default EndpointRuleset customizeRuleset(EndpointRuleset ruleset) {
return ruleset;
}

/**
* Customize the base, generated Test Suite (generated from endpoints.json).
* <p>
* Most customizations will simply need to add additional test cases:
* <pre>{@code
* public EndpointTestsTrait customizeTestSuite(EndpointTestsTrait testSuite) {
* List<EndpointTestCase> testCases = new ArrayList<>();
* testCases.addAll(testSuite.getTestCases());
* testCases.add(myCustomTestCase());
* return ((EndpointTestsTrait.Builder)testSuite.toBuilder()).testCases(testCases).build();
* }
* }</pre>
*
* @param testSuite the base generated test suite
* @return test suite customized for the service
*/
default EndpointTestsTrait customizeTestSuite(EndpointTestsTrait testSuite) {
return testSuite;
}

/**
* If a service has private/internal/development only features, return true.
* The {@link #developmentRuleset(EndpointRuleset)} developmentRuleset} and
* {@link #developmentTestSuite(EndpointTestsTrait)} methods will be called
* and the resulting rules/tests will be saved in a separate output folder.
*
* @return true if the service has development (internal only) endpoint rules
*/
default boolean hasDevelopmentFeatures() {
return false;
}

/**
* Called when hasDevelopmentFeatures is true to produce rules with internal/development
* features enabled.
* See {@link #customizeRuleset(EndpointRuleset)}
*
* @param ruleset the base generated ruleset
* @return ruleset customized for the service including development (internal) features
*/
default EndpointRuleset developmentRuleset(EndpointRuleset ruleset) {
return ruleset;
}

/**
* Called when hasDevelopmentFeatures is true to produce test cases with internal/development
* features enabled.
* See {@link #customizeTestSuite(EndpointTestsTrait)}
*
* @param testSuite the base generated test suite
* @return test suite customized for the service including development (internal) features
*/
default EndpointTestsTrait developmentTestSuite(EndpointTestsTrait testSuite) {
return testSuite;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* 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.rulesengine.language.stdlib;

import java.util.Arrays;
import java.util.List;
import software.amazon.smithy.rulesengine.language.eval.Type;
import software.amazon.smithy.rulesengine.language.eval.Value;
import software.amazon.smithy.rulesengine.language.syntax.fn.FunctionDefinition;
import software.amazon.smithy.utils.SmithyUnstableApi;

@SmithyUnstableApi
public class IsVirtualHostableS3Bucket extends FunctionDefinition {
public static final String ID = "aws.isVirtualHostableS3Bucket";

@Override
public String id() {
return ID;
}

@Override
public List<Type> arguments() {
return Arrays.asList(Type.str(), Type.bool());
}

@Override
public Type returnType() {
return Type.bool();
}

@Override
public Value eval(List<Value> arguments) {
String hostLabel = arguments.get(0).expectString();
boolean allowDots = arguments.get(1).expectBool();
if (allowDots) {
return Value.bool(hostLabel.matches("[a-z\\d][a-z\\d\\-.]{1,61}[a-z\\d]"));
} else {
return Value.bool(hostLabel.matches("[a-z\\d][a-z\\d\\-]{1,61}[a-z\\d]"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.HashMap;
import java.util.Optional;
import software.amazon.smithy.rulesengine.language.stdlib.IsValidHostLabel;
import software.amazon.smithy.rulesengine.language.stdlib.IsVirtualHostableS3Bucket;
import software.amazon.smithy.rulesengine.language.stdlib.ParseArn;
import software.amazon.smithy.rulesengine.language.stdlib.ParseUrl;
import software.amazon.smithy.rulesengine.language.stdlib.PartitionFn;
Expand All @@ -26,6 +27,7 @@
import software.amazon.smithy.rulesengine.language.util.LazyValue;
import software.amazon.smithy.utils.SmithyUnstableApi;


/**
* Collection of registered functions.
*/
Expand All @@ -40,6 +42,7 @@ public final class FunctionRegistry {
registry.registerFunction(new ParseUrl());
registry.registerFunction(new Substring());
registry.registerFunction(new UriEncode());
registry.registerFunction(new IsVirtualHostableS3Bucket());
return registry;
}).build();

Expand All @@ -48,6 +51,10 @@ public final class FunctionRegistry {
private FunctionRegistry() {
}

static FunctionRegistry getGlobalRegistry() {
return GLOBAL_REGISTRY.value();
}

public void registerFunction(FunctionDefinition definition) {
registry.put(definition.id(), definition);
}
Expand All @@ -59,8 +66,4 @@ public Optional<LibraryFunction> forNode(FnNode node) {
return Optional.empty();
}
}

static FunctionRegistry getGlobalRegistry() {
return GLOBAL_REGISTRY.value();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
{
"version": "1.0",
"testCases": [
{
"documentation": "bucket-name: isVirtualHostable",
"params": {
"BucketName": "bucket-name"
},
"expect": {
"endpoint": {
"url": "https://bucket-name.s3.amazonaws.com"
}
}
},
{
"documentation": "bucket-with-number-1: isVirtualHostable",
"params": {
"BucketName": "bucket-with-number-1"
},
"expect": {
"endpoint": {
"url": "https://bucket-with-number-1.s3.amazonaws.com"
}
}
},
{
"documentation": "BucketName: not isVirtualHostable (uppercase characters)",
"params": {
"BucketName": "BucketName"
},
"expect": {
"error": "not isVirtualHostableS3Bucket"
}
},
{
"documentation": "bucket_name: not isVirtualHostable (underscore)",
"params": {
"BucketName": "bucket_name"
},
"expect": {
"error": "not isVirtualHostableS3Bucket"
}
},
{
"documentation": "bucket.name: isVirtualHostable (http only)",
"params": {
"BucketName": "bucket.name"
},
"expect": {
"endpoint": {
"url": "http://bucket.name.s3.amazonaws.com"
}
}
},
{
"documentation": "bucket.name.multiple.dots1: isVirtualHostable (http only)",
"params": {
"BucketName": "bucket.name.multiple.dots1"
},
"expect": {
"endpoint": {
"url": "http://bucket.name.multiple.dots1.s3.amazonaws.com"
}
}
},
{
"documentation": "-bucket-name: not isVirtualHostable (leading dash)",
"params": {
"BucketName": "-bucket-name"
},
"expect": {
"error": "not isVirtualHostableS3Bucket"
}
},
{
"documentation": "bucket-name-: not isVirtualHostable (trailing dash)",
"params": {
"BucketName": "bucket-name-"
},
"expect": {
"error": "not isVirtualHostableS3Bucket"
}
},
{
"documentation": "aa: not isVirtualHostable (< 3 characters)",
"params": {
"BucketName": "aa"
},
"expect": {
"error": "not isVirtualHostableS3Bucket"
}
},
{
"documentation": "'a'*64: not isVirtualHostable (> 63 characters)",
"params": {
"BucketName": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
"expect": {
"error": "not isVirtualHostableS3Bucket"
}
},
{
"documentation": ".bucket-name: not isVirtualHostable (leading dot)",
"params": {
"BucketName": ".bucket-name"
},
"expect": {
"error": "not isVirtualHostableS3Bucket"
}
},
{
"documentation": "bucket-name.: not isVirtualHostable (trailing dot)",
"params": {
"BucketName": "bucket-name."
},
"expect": {
"error": "not isVirtualHostableS3Bucket"
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ valid-hostlabel.json
substring.json
uri-encode.json
fns.json
partition-fn.json
partition-fn.json
is-virtual-hostable-s3-bucket.json
Loading