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

Timestream doesn't support running with localstack #1413

Open
1 task
yibo-long opened this issue Sep 20, 2024 · 5 comments
Open
1 task

Timestream doesn't support running with localstack #1413

yibo-long opened this issue Sep 20, 2024 · 5 comments
Labels
feature-request A feature should be added or improved.

Comments

@yibo-long
Copy link

Describe the bug

When running with localstack-pro for Timestream, it throws below errors:


http://localhost:4566 is not a valid inet host
java.lang.IllegalArgumentException: http://localhost:4566 is not a valid inet host
	at aws.smithy.kotlin.runtime.net.HostKt.hostParseImpl(Host.kt:35)
	at aws.smithy.kotlin.runtime.net.HostKt.access$hostParseImpl(Host.kt:1)
	at aws.smithy.kotlin.runtime.net.Host$Companion.parse(Host.kt:14)
	at aws.sdk.kotlin.services.timestreamwrite.endpoints.TimestreamWriteEndpointDiscoverer.discoverHost(TimestreamWriteEndpointDiscoverer.kt:48)
	at aws.sdk.kotlin.services.timestreamwrite.endpoints.TimestreamWriteEndpointDiscoverer.access$discoverHost(TimestreamWriteEndpointDiscoverer.kt:25)
	at aws.sdk.kotlin.services.timestreamwrite.endpoints.TimestreamWriteEndpointDiscoverer$discoverHost$1.invokeSuspend(TimestreamWriteEndpointDiscoverer.kt)
	at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt:42)
	at aws.smithy.kotlin.runtime.http.middleware.RetryMiddleware$handle$result$outcome$1.invokeSuspend(RetryMiddleware.kt:144)
	at aws.smithy.kotlin.runtime.retries.StandardRetryStrategy.doTryLoop(StandardRetryStrategy.kt:60)
	at aws.smithy.kotlin.runtime.retries.StandardRetryStrategy.retry$suspendImpl(StandardRetryStrategy.kt:40)
	at aws.smithy.kotlin.runtime.http.middleware.RetryMiddleware.handle(RetryMiddleware.kt:50)
	at aws.smithy.kotlin.runtime.io.middleware.ModifyRequestMiddleware.handle(ModifyRequest.kt:26)
	at aws.smithy.kotlin.runtime.io.middleware.ModifyRequestMiddleware.handle(ModifyRequest.kt:26)
	at aws.smithy.kotlin.runtime.io.middleware.ModifyRequestMiddleware.handle(ModifyRequest.kt:26)
	at aws.smithy.kotlin.runtime.http.operation.SerializeHandler.call(SdkOperationExecution.kt:251)
	at aws.smithy.kotlin.runtime.http.operation.OperationHandler.call(SdkOperationExecution.kt:207)
	at aws.smithy.kotlin.runtime.http.operation.SdkHttpOperationKt$execute$$inlined$withSpan$1.invokeSuspend(SdkHttpOperation.kt:76)
	at aws.smithy.kotlin.runtime.http.operation.SdkHttpOperationKt.execute(SdkHttpOperation.kt:219)
	at io.span.services.traithandlers.metering.TimestreamSeeder$seed$2.invokeSuspend(TimestreamSeeder.kt:277)
	at io.span.services.traithandlers.metering.MeteringTraitHandlerEndpointTest$beforeAll$1.invokeSuspend(MeteringTraitHandlerEndpointTest.kt:59)
Caused by: java.lang.IllegalArgumentException: http://localhost:4566 is not a valid inet host
	at aws.smithy.kotlin.runtime.net.HostKt.hostParseImpl(Host.kt:35)
	at aws.smithy.kotlin.runtime.net.HostKt.access$hostParseImpl(Host.kt:1)
	at aws.smithy.kotlin.runtime.net.Host$Companion.parse(Host.kt:14)
	at aws.sdk.kotlin.services.timestreamwrite.endpoints.TimestreamWriteEndpointDiscoverer.discoverHost(TimestreamWriteEndpointDiscoverer.kt:48)
	at aws.sdk.kotlin.services.timestreamwrite.endpoints.TimestreamWriteEndpointDiscoverer.access$discoverHost(TimestreamWriteEndpointDiscoverer.kt:25)
	at aws.sdk.kotlin.services.timestreamwrite.endpoints.TimestreamWriteEndpointDiscoverer$discoverHost$1.invokeSuspend(TimestreamWriteEndpointDiscoverer.kt)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.UndispatchedCoroutine.afterResume(CoroutineContext.kt:266)
	at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:99)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
	at kotlinx.coroutines.UndispatchedCoroutine.afterResume(CoroutineContext.kt:266)
	at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:99)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:111)
	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:99)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:811)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:715)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:702)

This happens for both timestream-query and timestream-write

the client is created as:

TimestreamWriteClient {
        region = awsRegion
        timestreamEndpoint?.let {
            endpointUrl = Url.parse(it)
        }
    }

Regression Issue

  • Select this option if this issue appears to be a regression.

Expected behavior

it should be run correctly as similar codes with software.amazon.awssdk:timestreamwrite or software.amazon.awssdk:timestreamquery.

Current behavior

Throws the error.

Steps to Reproduce

run with the code below with localstack-pro testcontainer

val container: LocalStackContainer
// awsRegion and timestreamEndpoint are from localstack testcontainer
val client = TimestreamWriteClient {
    region = container.region
    endpointUrl = Url.parse(container.endpoint.toString())
}
client.createDatabase {
    databaseName = "test-db"
}

Possible Solution

It seems to be that kotlin sdk didn't disable endpoint discovery like aws-sdk-java-v2:
image

for those EndpointDiscoverer in kotlin sdk, it should not try to discover host with describeEndpoints if endpoint is already overriden.

Context

No response

AWS SDK for Kotlin version

1.3.21

Platform (JVM/JS/Native)

JDK21

Operating system and version

linux/mac

@yibo-long yibo-long added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Sep 20, 2024
@0marperez
Copy link
Contributor

Hi, thanks for the report. Have you tried using a custom endpoint provider with a fixed endpoint. There's an example of that here in our documentation.

It would look something like this:

S3Client.fromEnvironment {
    endpointProvider = object : S3EndpointProvider {
        override suspend fun resolveEndpoint(params: S3EndpointParameters): Endpoint = Endpoint("https://endpoint.example")
    }
}

@0marperez 0marperez added feature-request A feature should be added or improved. and removed needs-triage This issue or PR still needs to be triaged. bug This issue is a bug. labels Sep 25, 2024
@yibo-long
Copy link
Author

@0marperez thanks for the suggestion,I tried that it still running with endpoint discoverer:

TimestreamWriteClient {
        region = awsRegion
        timestreamEndpoint?.let { endpoint ->
            endpointProvider = TimestreamWriteEndpointProvider {
                Endpoint(endpoint)
            }
        }
    }

As far as I can see the code won't skip discovery:
image
which will always try calling describeEndpoints regardless of TimestreamWriteEndpointProvider:
image

With that said, I think it will be great either providing the similar logic with endpointDiscoveryEnabled (which is mentioned to work in https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoint-discovery.html, however I couldn't find a way to set it in kotlin clients), or allowing overriding TimestreamWriteEndpointDiscoverer, which is currently a final class.

@0marperez
Copy link
Contributor

@yibo-long I am able to override TimestreamWriteEndpointDiscoverer using this code:

TimestreamWriteClient.fromEnvironment {
    region = "..."
    endpointProvider = object : TimestreamWriteEndpointProvider {
        override suspend fun resolveEndpoint(params: TimestreamWriteEndpointParameters): Endpoint = Endpoint("https://endpoint.example")
    }
}

It's a bit different to what you have currently.
In regards to disabling endpoint discovery, I see the issue you're having and I'll be working on correcting the documentation in the meantime and working on seeing how we can add the functionality

@0marperez
Copy link
Contributor

Hi @yibo-long just checking in, did the code above help you become unblocked?

@yibo-long
Copy link
Author

Hi @0marperez, unfortunately no.

As you can see from my screenshot of the generated SDK code, val discoveredHost = cache.get(cacheKey) { discoverHost(client) } is run before val originalEndpoint = delegate.resolve(request), and then delegate.resolve calls endpointProvider.resolveEndpoint(params). discoverHost will still throw error for java.lang.IllegalArgumentException: http://localhost:4566 is not a valid inet host

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request A feature should be added or improved.
Projects
None yet
Development

No branches or pull requests

2 participants