Skip to content

Commit

Permalink
Add declarative endpoints traits
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewFossAWS committed Oct 19, 2023
1 parent 37919ad commit 32ff2c3
Show file tree
Hide file tree
Showing 32 changed files with 1,691 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.rulesengine.aws.traits;

import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.node.ObjectNode;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.traits.AnnotationTrait;

/**
* An endpoints modifier trait that indicates a service has only dual stack endpoints,
* does not support IPV4 only endpoints, and should not have the useDualStackEndpoint endpoint parameter.
*/
public final class DualStackOnlyEndpointsTrait extends AnnotationTrait {
public static final ShapeId ID = ShapeId.from("aws.endpoints#dualStackOnlyEndpoints");

public DualStackOnlyEndpointsTrait(ObjectNode node) {
super(ID, node);
}

public DualStackOnlyEndpointsTrait() {
this(Node.objectNode());
}

public static final class Provider extends AnnotationTrait.Provider<DualStackOnlyEndpointsTrait> {
public Provider() {
super(ID, DualStackOnlyEndpointsTrait::new);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.rulesengine.aws.traits;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.knowledge.KnowledgeIndex;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.shapes.ToShapeId;
import software.amazon.smithy.model.traits.Trait;

/**
* Locates the endpoint modifier traits applied to services.
*
* Endpoint modifier traits are traits that are marked by {@link EndpointModifierTrait}
*/
public final class EndpointModifierIndex implements KnowledgeIndex {

private final Map<ShapeId, Map<ShapeId, Trait>> endpointModifierTraits = new HashMap<>();

public EndpointModifierIndex(Model model) {
for (ServiceShape serviceShape : model.getServiceShapes()) {
Map<ShapeId, Trait> result = new TreeMap<>();
for (Trait trait : serviceShape.getAllTraits().values()) {
Shape traitShape = model.getShape(trait.toShapeId()).get();
if (traitShape.hasTrait(EndpointModifierTrait.ID)) {
result.put(trait.toShapeId(), trait);
}
}
endpointModifierTraits.put(serviceShape.toShapeId(), result);
}
}

public static EndpointModifierIndex of(Model model) {
return model.getKnowledge(EndpointModifierIndex.class, EndpointModifierIndex::new);
}

/**
* Gets all endpoint modifier traits applied to a service.
*
* @param toShapeId Service shape to query
* @return Map of endpoint modifier trait ID to the trait
*/
public Map<ShapeId, Trait> getEndpointModifierTraits(ToShapeId toShapeId) {
return endpointModifierTraits.get(toShapeId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.rulesengine.aws.traits;

import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.node.ObjectNode;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.traits.AnnotationTrait;

/**
* A meta-trait that marks a trait as an endpoint modifier.
*
* Traits that are marked with this trait are applied to service shapes or operation shapes to
* indicate how a client can resolve endpoints for that service or operation.
*/
public final class EndpointModifierTrait extends AnnotationTrait {
public static final ShapeId ID = ShapeId.from("aws.endpoints#endpointsModifier");

public EndpointModifierTrait(ObjectNode node) {
super(ID, node);
}

public EndpointModifierTrait() {
this(Node.objectNode());
}

public static final class Provider extends AnnotationTrait.Provider<EndpointModifierTrait> {
public Provider() {
super(ID, EndpointModifierTrait::new);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.rulesengine.aws.traits;

import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.node.StringNode;

/**
* The pattern type to use for the partitional services.
*/
public enum EndpointPatternType {
/** An endpoint with pattern `{service}.{dnsSuffix}`.*/
SERVICE_DNSSUFFIX("service_dnsSuffix"),

/** An endpoint with pattern `{service}.{region}.{dnsSuffix}`. */
SERVICE_REGION_DNSSUFFI("service_region_dnsSuffix");

private final String name;

EndpointPatternType(String name) {
this.name = name;
}

/**
* Gets the name of a partitional service pattern type.
*
* @return Returns a partitional service pattern type name.
*/
public String getName() {
return name;
}

public static EndpointPatternType fromNode(Node node) {
StringNode value = node.expectStringNode();
for (EndpointPatternType type: EndpointPatternType.values()) {
if (type.name.equals(value.getValue())) {
return type;
}
}
throw new RuntimeException(String.format(
"Unable to find EndpointPatternType enum with value [%s]", value.getValue()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.rulesengine.aws.traits;

import java.util.Objects;
import software.amazon.smithy.model.FromSourceLocation;
import software.amazon.smithy.model.SourceLocation;
import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.node.ObjectNode;
import software.amazon.smithy.model.node.ToNode;
import software.amazon.smithy.utils.SmithyBuilder;
import software.amazon.smithy.utils.ToSmithyBuilder;

/**
* A special case that does not follow the services standard patterns
* or are located in a region other than the partition's default global region.
*/
public final class PartitionEndpointSpecialCase
implements FromSourceLocation, ToNode, ToSmithyBuilder<PartitionEndpointSpecialCase> {

private static final String ENDPOINT = "endpoint";
private static final String REGION = "region";
private static final String DUAL_STACK = "dualStack";
private static final String FIPS = "fips";
private final String endpoint;
private final String region;
private final Boolean dualStack;
private final Boolean fips;
private final SourceLocation sourceLocation;

private PartitionEndpointSpecialCase(Builder builder) {
this.endpoint = builder.endpoint;
this.region = builder.region;
this.dualStack = builder.dualStack;
this.fips = builder.fips;
this.sourceLocation = Objects.requireNonNull(builder.sourceLocation);
}

/**
* Gets the endpoint.
*
* @return Returns the endpoint
*/
public String getEndpoint() {
return endpoint;
}

/**
* Gets the dualStack.
*
* @return Returns the dualStack
*/
public Boolean getDualStack() {
return dualStack;
}

/**
* Gets the fips.
*
* @return Returns the fips
*/
public Boolean getFips() {
return fips;
}

/**
* Gets the region.
*
* @return Returns the region
*/
public String getRegion() {
return region;
}

@Override
public Node toNode() {
return Node.objectNodeBuilder()
.withMember(ENDPOINT, endpoint)
.withMember(REGION, region)
.withMember(DUAL_STACK, dualStack.toString())
.withMember(FIPS, fips.toString())
.build();
}

@Override
public SmithyBuilder<PartitionEndpointSpecialCase> toBuilder() {
return new Builder()
.endpoint(endpoint)
.region(region)
.dualStack(dualStack)
.fips(fips)
.sourceLocation(sourceLocation);
}

@Override
public SourceLocation getSourceLocation() {
return FromSourceLocation.super.getSourceLocation();
}

/**
* Creates a {@link PartitionEndpointSpecialCase} instance from the given Node information.
*
* @param node the node to deserialize.
* @return Returns a PartitionEndpointSpecialCase
*/
public static PartitionEndpointSpecialCase fromNode(Node node) {
ObjectNode objectNode = node.expectObjectNode();
return builder()
.sourceLocation(objectNode.getSourceLocation())
.endpoint(objectNode.expectStringMember(ENDPOINT).getValue())
.region(objectNode.expectStringMember(REGION).getValue())
.dualStack(objectNode.getBooleanMemberOrDefault(DUAL_STACK, null))
.fips(objectNode.getBooleanMemberOrDefault(FIPS, null))
.build();
}

public static Builder builder() {
return new Builder();
}

public static final class Builder implements SmithyBuilder<PartitionEndpointSpecialCase> {
private String endpoint;
private String region;
private Boolean dualStack;
private Boolean fips;
private SourceLocation sourceLocation = SourceLocation.none();

@Override
public PartitionEndpointSpecialCase build() {
return new PartitionEndpointSpecialCase(this);
}

/**
* Sets the special case endpoint template.
*
* @param endpoint Special case endpoint template to set.
* @return Returns the builder.
*/
public Builder endpoint(String endpoint) {
this.endpoint = endpoint;
return this;
}

/**
* Sets the dualstack.
*
* @param dualStack dualstack to set.
* @return Returns the builder.
*/
public Builder dualStack(Boolean dualStack) {
this.dualStack = dualStack;
return this;
}

/**
* Sets the fips.
*
* @param fips fips to set.
* @return Returns the builder.
*/
public Builder fips(Boolean fips) {
this.fips = fips;
return this;
}

/**
* Sets the region.
*
* @param region region to set.
* @return Returns the builder.
*/
public Builder region(String region) {
this.region = region;
return this;
}

Builder sourceLocation(SourceLocation sourceLocation) {
this.sourceLocation = sourceLocation;
return this;
}
}
}
Loading

0 comments on commit 32ff2c3

Please sign in to comment.