Skip to content

Commit

Permalink
IAM resource/action trait changes
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-fowler committed Dec 4, 2024
1 parent 4c3859d commit cf52db0
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 34 deletions.
47 changes: 34 additions & 13 deletions Sources/SotoSmithy/Shapes/AggregateShapes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,16 @@ public class MemberShape: Shape {
}

public func validate(using model: Model) throws {
guard let shape = model.shape(for: target) else { throw Smithy.ValidationError(reason: "Member of ** references non-existent shape \(self.target)") }
guard let shape = model.shape(for: target) else {
throw Smithy.ValidationError(
reason: "Member of ** references non-existent shape \(self.target)")
}
guard !(shape is OperationShape),
!(shape is ResourceShape),
!(shape is ServiceShape)
!(shape is ResourceShape),
!(shape is ServiceShape)
else {
throw Smithy.ValidationError(reason: "Member of ** references illegal shape \(self.target)")
throw Smithy.ValidationError(
reason: "Member of ** references illegal shape \(self.target)")
}
try self.validateTraits(using: model)
}
Expand Down Expand Up @@ -89,7 +93,7 @@ public class MapShape: Shape {
}
}

/// Protocol for shape holding a collection of member shapes
/// Protocol for shape holding a key/value collection of member shapes
public protocol CollectionShape: Shape {
var members: [String: MemberShape]? { get set }
}
Expand All @@ -107,7 +111,9 @@ extension CollectionShape {
try member.value.validate(using: model)
} catch let error as Smithy.ValidationError {
// replace "**" with name of shape
throw Smithy.ValidationError(reason: error.reason.replacingOccurrences(of: "**", with: "**$\(member.key)"))
throw Smithy.ValidationError(
reason: error.reason.replacingOccurrences(
of: "**", with: "**$\(member.key)"))
}
}
}
Expand Down Expand Up @@ -152,7 +158,9 @@ public class UnionShape: CollectionShape {
}

public func validate(using model: Model) throws {
guard let members = self.members, members.count > 0 else { throw Smithy.ValidationError(reason: "Union has no members") }
guard let members = self.members, members.count > 0 else {
throw Smithy.ValidationError(reason: "Union has no members")
}
try self.validateMembers(using: model)
try self.validateTraits(using: model)
}
Expand All @@ -170,12 +178,18 @@ public class EnumShape: CollectionShape {
}

public func validate(using model: Model) throws {
guard let version = Double(model.version), version >= 2.0 else { throw Smithy.ValidationError(reason: "Enum Shapes are only available in Smithy 2.0 or later") }
guard let members = self.members, members.count > 0 else { throw Smithy.ValidationError(reason: "Enum has no members") }
guard let version = Double(model.version), version >= 2.0 else {
throw Smithy.ValidationError(
reason: "Enum Shapes are only available in Smithy 2.0 or later")
}
guard let members = self.members, members.count > 0 else {
throw Smithy.ValidationError(reason: "Enum has no members")
}
try members.forEach {
if let valueTrait = $0.value.trait(type: EnumValueTrait.self) {
guard case .string = valueTrait.value else {
throw Smithy.ValidationError(reason: "String based Enum has none string enum value trait")
throw Smithy.ValidationError(
reason: "String based Enum has none string enum value trait")
}
}
}
Expand All @@ -196,10 +210,17 @@ public class IntEnumShape: CollectionShape {
}

public func validate(using model: Model) throws {
guard let version = Double(model.version), version >= 2.0 else { throw Smithy.ValidationError(reason: "Enum Shapes are only available in Smithy 2.0 or later") }
guard let members = self.members, members.count > 0 else { throw Smithy.ValidationError(reason: "Enum has no members") }
guard let version = Double(model.version), version >= 2.0 else {
throw Smithy.ValidationError(
reason: "Enum Shapes are only available in Smithy 2.0 or later")
}
guard let members = self.members, members.count > 0 else {
throw Smithy.ValidationError(reason: "Enum has no members")
}
try members.forEach {
guard let valueTrait = $0.value.trait(type: EnumValueTrait.self) else { throw Smithy.ValidationError(reason: "IntEnum members require a enumValue trait") }
guard let valueTrait = $0.value.trait(type: EnumValueTrait.self) else {
throw Smithy.ValidationError(reason: "IntEnum members require a enumValue trait")
}
guard case .integer = valueTrait.value else {
throw Smithy.ValidationError(reason: "IntEnum has none integer enum value trait")
}
Expand Down
43 changes: 28 additions & 15 deletions Sources/SotoSmithyAWS/Traits/AwsCoreTraits.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,20 @@ import SotoSmithy
/// like the name used to generate AWS SDK client classes and the namespace used in ARNs.
public struct AwsServiceTrait: StaticTrait {
public static let staticName: ShapeId = "aws.api#service"
public var selector: Selector { return TypeSelector<ServiceShape>() }
public var selector: Selector { TypeSelector<ServiceShape>() }
public let sdkId: String
public let arnNamespace: String?
public let cloudFormationName: String?
public let cloudTrailEventSource: String?
public let endpointPrefix: String?

public init(sdkId: String, arnNamespace: String?, cloudFormationName: String?, cloudTrailEventSource: String?, endpointPrefix: String?) {
public init(
sdkId: String,
arnNamespace: String?,
cloudFormationName: String?,
cloudTrailEventSource: String?,
endpointPrefix: String?
) {
self.sdkId = sdkId
self.arnNamespace = arnNamespace
self.cloudFormationName = cloudFormationName
Expand All @@ -39,7 +45,7 @@ public struct AwsServiceTrait: StaticTrait {
/// Defines an ARN of a Smithy resource shape.
public struct AwsArnTrait: StaticTrait {
public static let staticName: ShapeId = "aws.api#arn"
public var selector: Selector { return TypeSelector<ResourceShape>() }
public var selector: Selector { TypeSelector<ResourceShape>() }
public let template: String
public let absolute: Bool?
public let noAccount: Bool?
Expand All @@ -56,7 +62,7 @@ public struct AwsArnTrait: StaticTrait {
/// Specifies that a string shape contains a fully formed AWS ARN.
public struct AwsArnReferenceTrait: StaticTrait {
public static let staticName: ShapeId = "aws.api#arnReference"
public var selector: Selector { return TypeSelector<StringShape>() }
public var selector: Selector { TypeSelector<StringShape>() }
public let type: String?
public let service: ShapeId?
public let resource: ShapeId?
Expand All @@ -72,7 +78,7 @@ public struct AwsArnReferenceTrait: StaticTrait {
public struct AwsDataTrait: SingleValueTrait {
public static let staticName: ShapeId = "aws.api#data"
public var selector: Selector {
return OrSelector(
OrSelector(
SimpleTypeSelector(),
TypeSelector<ListShape>(),
TypeSelector<StructureShape>(),
Expand Down Expand Up @@ -100,7 +106,7 @@ public struct AwsDataTrait: SingleValueTrait {
public struct AwsControlPlaneTrait: StaticTrait {
public static let staticName: ShapeId = "aws.api#controlPlane"
public var selector: Selector {
return OrSelector(
OrSelector(
TypeSelector<ServiceShape>(),
TypeSelector<ResourceShape>(),
TypeSelector<OperationShape>()
Expand All @@ -112,7 +118,7 @@ public struct AwsControlPlaneTrait: StaticTrait {
public struct AwsDataPlaneTrait: StaticTrait {
public static let staticName: ShapeId = "aws.api#dataPlane"
public var selector: Selector {
return OrSelector(
OrSelector(
TypeSelector<ServiceShape>(),
TypeSelector<ResourceShape>(),
TypeSelector<OperationShape>()
Expand All @@ -124,7 +130,7 @@ public struct AwsDataPlaneTrait: StaticTrait {
/// for the service and the error returned when the endpoint being accessed has expired.
public struct AwsClientEndpointDiscoveryTrait: StaticTrait {
public static let staticName: ShapeId = "aws.api#clientEndpointDiscovery"
public var selector: Selector { return TypeSelector<ServiceShape>() }
public var selector: Selector { TypeSelector<ServiceShape>() }
public let operation: ShapeId
public let error: ShapeId
}
Expand All @@ -133,24 +139,26 @@ public struct AwsClientEndpointDiscoveryTrait: StaticTrait {
/// discovery logic.
public struct AwsClientDiscoveredEndpointTrait: StaticTrait {
public static let staticName: ShapeId = "aws.api#clientDiscoveredEndpoint"
public var selector: Selector { return TypeSelector<OperationShape>() }
public var selector: Selector { TypeSelector<OperationShape>() }
public let required: Bool?
}

/// The clientEndpointDiscoveryId trait indicates which member(s) of the operation input should be used to
/// discover an endpoint for the service.
public struct AwsClientEndpointDiscoveryIdTrait: StaticTrait {
public static let staticName: ShapeId = "aws.api#clientEndpointDiscoveryId"
public var selector: Selector { return AndSelector(
TypeSelector<OperationShape>(),
TraitSelector<AwsClientEndpointDiscoveryTrait>()
) }
public var selector: Selector {
AndSelector(
TypeSelector<OperationShape>(),
TraitSelector<AwsClientEndpointDiscoveryTrait>()
)
}
}

/// Specifies that a string shape contains a fully formed AWS ARN.
public struct AwsHttpChecksumTrait: StaticTrait {
public static let staticName: ShapeId = "aws.protocols#httpChecksum"
public var selector: Selector { return TypeSelector<OperationShape>() }
public var selector: Selector { TypeSelector<OperationShape>() }
public enum Algorithm: String, Codable {
case crc32c = "CRC32C"
case crc32 = "CRC32"
Expand All @@ -163,7 +171,12 @@ public struct AwsHttpChecksumTrait: StaticTrait {
public let requestValidationModeMember: String?
public let responseAlgorithms: Set<Algorithm>?

public init(requestAlgorithmMember: String?, requestChecksumRequired: Bool?, requestValidationModeMember: String?, responseAlgorithms: Set<Algorithm>?) {
public init(
requestAlgorithmMember: String?,
requestChecksumRequired: Bool?,
requestValidationModeMember: String?,
responseAlgorithms: Set<Algorithm>?
) {
self.requestAlgorithmMember = requestAlgorithmMember
self.requestChecksumRequired = requestChecksumRequired
self.requestValidationModeMember = requestValidationModeMember
Expand Down
18 changes: 12 additions & 6 deletions Sources/SotoSmithyAWS/Traits/AwsIAMTraits.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import SotoSmithy
/// Indicates properties of a Smithy operation in AWS IAM.
public struct AwsIAMAction: StaticTrait {
public struct ActionResource: Codable {
let conditionKeys: [String]
let conditionKeys: [String]?
}

public struct ActionResources: Codable {
let required: [String: ActionResource]
let optional: [String: ActionResource]
let required: [String: ActionResource]?
let optional: [String: ActionResource]?
}

public static let staticName: ShapeId = "aws.iam#iamAction"
Expand Down Expand Up @@ -58,7 +58,9 @@ public struct AwsIAMActionPermissionDescriptionTrait: SingleValueTrait {
/// Applies condition keys, by name, to a resource or operation.
public struct AwsIAMConditionKeysTrait: SingleValueTrait {
public static let staticName: ShapeId = "aws.iam#conditionKeys"
public var selector: Selector { OrSelector(TypeSelector<OperationShape>(), TypeSelector<ResourceShape>()) }
public var selector: Selector {
OrSelector(TypeSelector<OperationShape>(), TypeSelector<ResourceShape>())
}
public let value: [String]
public init(value: [String]) {
self.value = value
Expand Down Expand Up @@ -124,7 +126,9 @@ public struct AwsIAMConditionKeyValueTrait: SingleValueTrait {
/// Declares that the condition keys of a resource should not be inferred.
public struct AwsIAMDisableConditionKeyInferenceTrait: StaticTrait {
public static let staticName: ShapeId = "aws.iam#disableConditionKeyInference"
public var selector: Selector { OrSelector(TypeSelector<ResourceShape>(), TypeSelector<ServiceShape>()) }
public var selector: Selector {
OrSelector(TypeSelector<ResourceShape>(), TypeSelector<ServiceShape>())
}
}

/// Other actions that the invoker must be authorized to perform when executing the targeted operation.
Expand All @@ -147,7 +151,9 @@ public struct AwsIAMSupportPrincipalTypesTrait: SingleValueTrait {
}

public static let staticName: ShapeId = "aws.iam#supportedPrincipalTypes"
public var selector: Selector { OrSelector(TypeSelector<ServiceShape>(), TypeSelector<OperationShape>()) }
public var selector: Selector {
OrSelector(TypeSelector<ServiceShape>(), TypeSelector<OperationShape>())
}
public let value: [PrincipalType]
public init(value: [PrincipalType]) {
self.value = value
Expand Down

0 comments on commit cf52db0

Please sign in to comment.