Skip to content

Commit f16b345

Browse files
authored
fix(amazonq): make amazon.q.endpoints.json more maintainable (#5543)
* fix(amazonq): make amazon.q.endpoints.json more maintainable We do not need to stuff the prod configuration into the plugin.xml. Additionally we should gracefully handle invalid configuration instead of giving up * lint
1 parent e86b9bf commit f16b345

File tree

5 files changed

+45
-20
lines changed

5 files changed

+45
-20
lines changed

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/util/CodeWhispererEndpointCustomizer.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import software.amazon.awssdk.services.codewhispererruntime.CodeWhispererRuntime
2222
import software.amazon.awssdk.services.codewhispererstreaming.CodeWhispererStreamingAsyncClientBuilder
2323
import software.aws.toolkits.core.ToolkitClientCustomizer
2424
import software.aws.toolkits.core.utils.tryOrNull
25+
import software.aws.toolkits.jetbrains.services.amazonq.profile.QDefaultServiceConfig
2526
import software.aws.toolkits.jetbrains.services.amazonq.profile.QEndpoints
2627
import software.aws.toolkits.jetbrains.settings.CodeWhispererSettings
2728
import java.net.Proxy
@@ -42,7 +43,7 @@ class CodeWhispererEndpointCustomizer : ToolkitClientCustomizer {
4243
if (builder is CodeWhispererRuntimeClientBuilder || builder is CodeWhispererStreamingAsyncClientBuilder) {
4344
val endpoint = tryOrNull { QEndpoints.getQEndpointWithRegion(regionId) }
4445
?.let { URI.create(it) }
45-
?: URI.create(QEndpoints.Q_DEFAULT_SERVICE_CONFIG.ENDPOINT)
46+
?: URI.create(QDefaultServiceConfig.ENDPOINT)
4647
builder
4748
.endpointOverride(endpoint)
4849
.region(Region.of(regionId))

plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/QEndpointsTest.kt

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@
44
package software.aws.toolkits.jetbrains.services.codewhisperer
55

66
import com.intellij.testFramework.ApplicationExtension
7-
import com.intellij.testFramework.fixtures.BasePlatformTestCase
7+
import org.assertj.core.api.Assertions.assertThat
88
import org.junit.jupiter.api.Test
99
import org.junit.jupiter.api.extension.ExtendWith
1010
import org.junit.jupiter.api.extension.RegisterExtension
11+
import software.aws.toolkits.jetbrains.services.amazonq.profile.QDefaultServiceConfig
1112
import software.aws.toolkits.jetbrains.services.amazonq.profile.QEndpoints
13+
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionEndpoint
1214
import software.aws.toolkits.jetbrains.utils.rules.RegistryExtension
15+
import software.aws.toolkits.jetbrains.utils.satisfiesKt
1316

1417
@ExtendWith(ApplicationExtension::class)
15-
class QEndpointsTest : BasePlatformTestCase() {
18+
class QEndpointsTest {
1619

1720
@JvmField
1821
@RegisterExtension
@@ -30,12 +33,28 @@ class QEndpointsTest : BasePlatformTestCase() {
3033
registryExtension.setValue("amazon.q.endpoints.json", testJson)
3134

3235
val parsed = QEndpoints.listRegionEndpoints()
33-
assertEquals(2, parsed.size)
36+
assertThat(parsed).hasSize(2)
37+
.satisfiesKt { endpoints ->
38+
assertThat(endpoints).satisfiesExactlyInAnyOrder(
39+
{ assertThat(it).isEqualTo(QRegionEndpoint("us-east-1", "https://codewhisperer.us-east-1.amazonaws.com/")) },
40+
{ assertThat(it).isEqualTo(QRegionEndpoint("eu-central-1", "https://rts.prod-eu-central-1.codewhisperer.ai.aws.dev/")) },
41+
)
42+
}
43+
}
3444

35-
val iad = parsed.first { it.region == "us-east-1" }
36-
assertEquals("https://codewhisperer.us-east-1.amazonaws.com/", iad.endpoint)
45+
@Test
46+
fun `uses default entries if blank`() {
47+
registryExtension.setValue("amazon.q.endpoints.json", "")
3748

38-
val fra = parsed.first { it.region == "eu-central-1" }
39-
assertEquals("https://rts.prod-eu-central-1.codewhisperer.ai.aws.dev/", fra.endpoint)
49+
assertThat(QEndpoints.listRegionEndpoints()).isEqualTo(QDefaultServiceConfig.ENDPOINT_MAP.toEndpointList())
4050
}
51+
52+
@Test
53+
fun `uses default entries if invalid`() {
54+
registryExtension.setValue("amazon.q.endpoints.json", "asdfadfkajdklf32.4;'2l4;234l23.424';1l1!!@#!")
55+
56+
assertThat(QEndpoints.listRegionEndpoints()).isEqualTo(QDefaultServiceConfig.ENDPOINT_MAP.toEndpointList())
57+
}
58+
59+
private fun Map<String, String>.toEndpointList() = map { (region, endpoint) -> QRegionEndpoint(region, endpoint) }
4160
}

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QEndpoints.kt

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,29 @@ import com.intellij.openapi.util.registry.Registry
88
import software.aws.toolkits.core.utils.getLogger
99
import software.aws.toolkits.core.utils.warn
1010

11-
object QEndpoints {
12-
private val LOG = getLogger<QRegionEndpoint>()
13-
data class QRegionEndpoint(val region: String, val endpoint: String)
11+
data class QRegionEndpoint(val region: String, val endpoint: String)
1412

15-
object Q_DEFAULT_SERVICE_CONFIG {
16-
const val REGION = "us-east-1"
17-
const val ENDPOINT = "https://codewhisperer.us-east-1.amazonaws.com/"
18-
}
13+
object QDefaultServiceConfig {
14+
const val REGION = "us-east-1"
15+
const val ENDPOINT = "https://codewhisperer.us-east-1.amazonaws.com/"
16+
17+
val ENDPOINT_MAP = mapOf(
18+
"us-east-1" to "https://q.us-east-1.amazonaws.com/",
19+
"eu-central-1" to "https://q.eu-central-1.amazonaws.com/"
20+
)
21+
}
22+
23+
object QEndpoints {
24+
private val LOG = getLogger<QEndpoints>()
1925

2026
private fun parseEndpoints(): Map<String, String> {
21-
val rawJson = Registry.get("amazon.q.endpoints.json").asString().takeIf { it.isNotBlank() } ?: return emptyMap()
27+
val rawJson = Registry.get("amazon.q.endpoints.json").asString().takeIf { it.isNotBlank() } ?: return QDefaultServiceConfig.ENDPOINT_MAP
2228
return try {
2329
val regionList: List<QRegionEndpoint> = jacksonObjectMapper().readValue(rawJson)
2430
regionList.associate { it.region to it.endpoint }
2531
} catch (e: Exception) {
2632
LOG.warn(e) { "Failed to parse amazon.q.endpoints.json: $rawJson" }
27-
emptyMap()
33+
QDefaultServiceConfig.ENDPOINT_MAP
2834
}
2935
}
3036

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ class QRegionProfileManager : PersistentStateComponent<QProfileState>, Disposabl
188188
}
189189

190190
val settings = conn.getConnectionSettings()
191-
val awsRegion = AwsRegionProvider.getInstance()[QEndpoints.Q_DEFAULT_SERVICE_CONFIG.REGION] ?: error("unknown region from Q default service config")
191+
val awsRegion = AwsRegionProvider.getInstance()[QDefaultServiceConfig.REGION] ?: error("unknown region from Q default service config")
192192

193193
// TODO: different window should be able to select different profile
194194
return activeProfile(project)?.let { profile ->

plugins/amazonq/src/main/resources/META-INF/plugin.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,7 @@
8787
<registryKey key="amazon.q.endpoint" description="Endpoint to use for Amazon Q"
8888
defaultValue="" restartRequired="true"/>
8989
<registryKey key="amazon.q.endpoints.json" description="List of region-endpoint pairs in JSON array form"
90-
defaultValue="[{&quot;region&quot;:&quot;us-east-1&quot;,&quot;endpoint&quot;:&quot;https://q.us-east-1.amazonaws.com/&quot;},
91-
{&quot;region&quot;:&quot;eu-central-1&quot;,&quot;endpoint&quot;:&quot;https://q.eu-central-1.amazonaws.com/&quot;}]"
90+
defaultValue=""
9291
restartRequired="true"/>
9392
<registryKey key="inline.completion.rem.dev.use.rhizome" description="Defined by IntelliJ. Used for Amazon Q to display suggestions on remote."
9493
defaultValue="false" restartRequired="true"/>

0 commit comments

Comments
 (0)