Skip to content
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

Add declarative endpoints traits #1987

Merged
merged 1 commit into from
Oct 19, 2023
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,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