Skip to content

Commit

Permalink
remove ArnResource
Browse files Browse the repository at this point in the history
  • Loading branch information
aajtodd committed Nov 16, 2023
1 parent bd9c411 commit ec7d9bc
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 131 deletions.
108 changes: 3 additions & 105 deletions aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/arns/Arn.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ internal class Arn(
public val service: String,
public val region: String?,
public val accountId: String?,
public val resource: ArnResource,
public val resource: String,
) {
public companion object {

Expand All @@ -47,7 +47,7 @@ internal class Arn(
service = parts[2]
region = parts[3].takeIf(String::isNotBlank)
accountId = parts[4].takeIf(String::isNotBlank)
resource = ArnResource.parse(parts[5])
resource = parts[5]
}
}
}
Expand Down Expand Up @@ -101,11 +101,7 @@ internal class Arn(
public var service: String? = null
public var region: String? = null
public var accountId: String? = null
public var resource: ArnResource? = null

public fun resource(block: ArnResource.Builder.() -> Unit) {
resource = ArnResource.Builder().apply(block).build()
}
public var resource: String? = null

@PublishedApi
internal fun build(): Arn {
Expand All @@ -116,101 +112,3 @@ internal class Arn(
}
}
}

/**
* The separator to use between the `resource-type` and `resource-id` in an ARN
*/
internal enum class ArnResourceTypeSeparator(public val separator: String) {
SLASH("/"),
COLON(":"),
;

public companion object {
public fun fromValue(value: String): ArnResourceTypeSeparator =
checkNotNull(entries.find { it.separator == value }) {
"unknown ARN resource type separator `$value`, expected one of ${entries.map { it.separator }}"
}
}
}

/**
* Represents the resource portion of an Amazon Resource Name (ARN).
*
* Some ARNs use a `/` to separate `resource-type` and `resource-id`, others use a `:`. The following ARN formats
* are all valid.
*
* * `arn:partition:service:region:account-id:resource-type:resource-id`
* * `arn:partition:service:region:account-id:resource-type:resource-id:qualifier`
* * `arn:partition:service:region:account-id:resource-type:resource-id/qualifier`
*
* This is controlled by [resourceTypeSeparator].
*/
internal class ArnResource(
public val id: String,
public val type: String? = null,
public val resourceTypeSeparator: ArnResourceTypeSeparator = ArnResourceTypeSeparator.COLON,
) {
internal constructor(builder: Builder) : this(builder.id!!, builder.type, builder.resourceTypeSeparator)

init {
require(type == null || type.isNotBlank()) { "ARN resource type must not be blank" }
}

public companion object {
/**
* Parse an ARN resource from a string. ARN resources support multiple formats which may contain
* the same delimiters used to separate `<resource-type>` and `<resource-id>`. This may result in
* the parsed representation interpreting these parts as the resource type incorrectly.
*/
public fun parse(resource: String): ArnResource {
// <resource-id> || <resource-type>[:/]<resource-id>
require(resource.isNotEmpty()) { "ARN resource must not be empty" }

val delims = charArrayOf(':', '/')
val firstDelim = resource.indexOfAny(delims)

val builder = Builder()
when {
firstDelim != -1 -> {
val delim = resource[firstDelim]
val parts = resource.split(delim, limit = 2)
builder.type = parts[0]
builder.id = parts[1]
builder.resourceTypeSeparator = ArnResourceTypeSeparator.fromValue(delim.toString())
}
else -> builder.id = resource
}

return builder.build()
}
}

override fun toString(): String =
listOfNotNull(type, id).joinToString(resourceTypeSeparator.separator)

override fun hashCode(): Int {
var result = id.hashCode()
result = 31 * result + (type?.hashCode() ?: 0)
return result
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is ArnResource) return false
if (id != other.id) return false
if (resourceTypeSeparator != other.resourceTypeSeparator) return false
return type == other.type
}

public class Builder {
public var id: String? = null
public var type: String? = null
public var resourceTypeSeparator: ArnResourceTypeSeparator = ArnResourceTypeSeparator.COLON

@PublishedApi
internal fun build(): ArnResource {
require(!id.isNullOrBlank()) { "ARN resource id must not be null or blank" }
return ArnResource(this)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,60 +16,40 @@ class ArnTest {
partition = "aws"
service = "iam"
accountId = "123456789012"
resource {
id = "johndoe"
type = "user"
resourceTypeSeparator = ArnResourceTypeSeparator.SLASH
}
resource = "user/johndoe"
},
"arn:aws:sns:us-east-1:123456789012:example-sns-topic-name" to Arn {
partition = "aws"
service = "sns"
region = "us-east-1"
accountId = "123456789012"
resource {
id = "example-sns-topic-name"
}
resource = "example-sns-topic-name"
},
"arn:aws:ec2:us-east-1:123456789012:vpc/vpc-0e9801d129EXAMPLE" to Arn {
partition = "aws"
service = "ec2"
region = "us-east-1"
accountId = "123456789012"
resource {
id = "vpc-0e9801d129EXAMPLE"
type = "vpc"
resourceTypeSeparator = ArnResourceTypeSeparator.SLASH
}
resource = "vpc/vpc-0e9801d129EXAMPLE"
},
"arn:aws:s3:::bucket/key" to Arn {
partition = "aws"
service = "s3"
resource {
id = "key"
type = "bucket"
resourceTypeSeparator = ArnResourceTypeSeparator.SLASH
}
resource = "bucket/key"
},
"arn:aws:lambda:us-east-2:12345:function" to Arn {
partition = "aws"
service = "lambda"
region = "us-east-2"
accountId = "12345"
resource {
id = "function"
}
resource = "function"
},
"arn:aws:lambda:us-east-2:12345:function:version" to Arn {
partition = "aws"
service = "lambda"
region = "us-east-2"
accountId = "12345"
resource {
id = "version"
type = "function"
resourceTypeSeparator = ArnResourceTypeSeparator.COLON
}
resource = "function:version"
},
)

Expand Down

0 comments on commit ec7d9bc

Please sign in to comment.