Reference: AWS: Instance Metadata Service
dependencies {
implementation(platform("org.http4k:http4k-bom:6.36.0.0"))
implementation("org.http4k:http4k-connect-amazon-instancemetadata")
implementation("org.http4k:http4k-connect-amazon-instancemetadata-fake")
}
The Instance Metadata Service V1 connector provides the following Actions:
* GetAmiId
* GetHostName
* GetInstanceIdentityDocument
* GetInstanceType
* GetLocalHostName
* GetLocalIpv4
* GetPublicHostName
* GetPublicIpv4
* GetSecurityCredentials
* ListSecurityCredentials
Example usage
Kotlin
example.kt
package content.ecosystem.connect.reference.amazon.instancemetadata
import org.http4k.client.JavaHttpClient
import org.http4k.connect.amazon.instancemetadata.FakeInstanceMetadataService
import org.http4k.connect.amazon.instancemetadata.Http
import org.http4k.connect.amazon.instancemetadata.InstanceMetadataService
import org.http4k.connect.amazon.instancemetadata.getInstanceIdentityDocument
import org.http4k.connect.amazon.instancemetadata.getLocalIpv4
import org.http4k.core.HttpHandler
import org.http4k.filter.debug
const val USE_REAL_CLIENT = false
fun main() {
// we can connect to the real service or the fake (drop in replacement)
val http: HttpHandler = if (USE_REAL_CLIENT) JavaHttpClient() else FakeInstanceMetadataService()
// create a client
val client = InstanceMetadataService.Http(http.debug())
// get local ip address
val localIp = client.getLocalIpv4()
println(localIp)
// get identity document
val identityDocument = client.getInstanceIdentityDocument()
println(identityDocument)
}
Credentials Provider
The Instance Metadata Service also offers a CredentialsProvider.
If the application is running inside an Amazon EC2 environment,
this provider can authorize AWS requests using credentials from the instance profile.
Kotlin
example.kt
package content.ecosystem.connect.reference.amazon.instancemetadata
import org.http4k.client.JavaHttpClient
import org.http4k.connect.amazon.instancemetadata.FakeInstanceMetadataService
import org.http4k.connect.amazon.instancemetadata.Http
import org.http4k.connect.amazon.instancemetadata.InstanceMetadataService
import org.http4k.connect.amazon.instancemetadata.getInstanceIdentityDocument
import org.http4k.connect.amazon.instancemetadata.getLocalIpv4
import org.http4k.core.HttpHandler
import org.http4k.filter.debug
const val USE_REAL_CLIENT = false
fun main() {
// we can connect to the real service or the fake (drop in replacement)
val http: HttpHandler = if (USE_REAL_CLIENT) JavaHttpClient() else FakeInstanceMetadataService()
// create a client
val client = InstanceMetadataService.Http(http.debug())
// get local ip address
val localIp = client.getLocalIpv4()
println(localIp)
// get identity document
val identityDocument = client.getInstanceIdentityDocument()
println(identityDocument)
}
Ec2InstanceProfile provider should always be last in the chain,
since it will time out if not in an Amazon EC2 environment.Region Provider
The Instance Metadata Service also offers a RegionProvider.
If the application is running inside an Amazon EC2 environment,
this provider can detect the current AWS region.
Kotlin
region_provider.kt
package content.ecosystem.connect.reference.amazon.instancemetadata
import org.http4k.aws.AwsCredentials
import org.http4k.client.JavaHttpClient
import org.http4k.config.Environment
import org.http4k.connect.amazon.Environment
import org.http4k.connect.amazon.Profile
import org.http4k.connect.amazon.RegionProvider
import org.http4k.connect.amazon.core.model.Region
import org.http4k.connect.amazon.instancemetadata.Ec2InstanceProfile
import org.http4k.connect.amazon.instancemetadata.FakeInstanceMetadataService
import org.http4k.connect.amazon.sns.FakeSNS
import org.http4k.connect.amazon.sns.Http
import org.http4k.connect.amazon.sns.SNS
import org.http4k.connect.amazon.sns.listTopics
import org.http4k.core.HttpHandler
fun main() {
// we can connect to the real service or the fake (drop in replacement)
val imdsHttp: HttpHandler = if (USE_REAL_CLIENT) JavaHttpClient() else FakeInstanceMetadataService()
val snsHttp: HttpHandler = if (USE_REAL_CLIENT) JavaHttpClient() else FakeSNS()
/*
* Build a RegionProvider chain with the following steps:
* 1. Try to get region from AWS_REGION environment variable
* 2. Try to get region from profile credentials file
* 3. Try to get region from EC2 Instance Metadata Service
*/
val regionProviderChain = RegionProvider.Environment(Environment.ENV) orElse
RegionProvider.Profile(Environment.ENV) orElse
RegionProvider.Ec2InstanceProfile(imdsHttp)
// Invoking the chain will return a region if one was found
val optionalRegion: Region? = regionProviderChain()
println(optionalRegion)
// orElseThrow will return a region or throw an exception if onr was not found
val region: Region = regionProviderChain.orElseThrow()
println(region)
// create and use an Amazon client with the resolved region
val sns = SNS.Http(region, { AwsCredentials("accessKeyId", "secretKey") }, snsHttp)
val topics = sns.listTopics()
println(topics)
}
:warning: The Ec2InstanceProfile provider should always be last in the chain,
since it will time out if not in an Amazon EC2 environment.
Default Fake port: 63407
To start:
Kotlin
fake.kt
package content.ecosystem.connect.reference.amazon.instancemetadata
import org.http4k.chaos.start
import org.http4k.connect.amazon.instancemetadata.FakeInstanceMetadataService
val instanceMetadataService = FakeInstanceMetadataService().start()
