Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type" : "bugfix",
"description" : "Amazon Q: Fix issue where context menu items are not available after re-opening projects or restarting the IDE"
}
Original file line number Diff line number Diff line change
Expand Up @@ -191,20 +191,6 @@ class QRegionProfileManagerTest {

@Test
fun `validateProfile should cross validate selected profile with latest API response for current project and remove it if its not longer accessible`() {
val client = clientRule.create<CodeWhispererRuntimeClient>()
val mockResponse: SdkIterable<Profile> = SdkIterable<Profile> {
listOf(
Profile.builder().profileName("foo").arn("foo-arn-v2").build(),
Profile.builder().profileName("bar").arn("bar-arn").build(),
).toMutableList().iterator()
}
val iterable: ListAvailableProfilesIterable = mock {
on { it.profiles() } doReturn mockResponse
}
client.stub {
onGeneric { listAvailableProfilesPaginator(any<Consumer<ListAvailableProfilesRequest.Builder>>()) } doReturn iterable
}

val activeConn =
ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance()) ?: fail("connection shouldn't be null")
val anotherConn = authRule.createConnection(ManagedSsoProfile(ssoRegion = "us-east-1", startUrl = "anotherUrl", scopes = Q_SCOPES))
Expand All @@ -214,6 +200,15 @@ class QRegionProfileManagerTest {
this.connectionIdToActiveProfile[activeConn.id] = fooProfile
this.connectionIdToActiveProfile[anotherConn.id] = barProfile
}
resourceCache.addEntry(
activeConn.getConnectionSettings(),
QProfileResources.LIST_REGION_PROFILES,
listOf(
QRegionProfile("foo", "foo-arn-v2"),
QRegionProfile("bar", "bar-arn"),
)
)

sut.loadState(state)
assertThat(sut.activeProfile(project)).isEqualTo(fooProfile)

Expand All @@ -222,6 +217,24 @@ class QRegionProfileManagerTest {
assertThat(sut.state.connectionIdToActiveProfile).isEqualTo(mapOf(anotherConn.id to barProfile))
}

@Test
fun `validateProfile does not clear profile if profiles cannot be listed`() {
val activeConn =
ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance()) ?: fail("connection shouldn't be null")
val anotherConn = authRule.createConnection(ManagedSsoProfile(ssoRegion = "us-east-1", startUrl = "anotherUrl", scopes = Q_SCOPES))
val fooProfile = QRegionProfile("foo", "foo-arn")
val barProfile = QRegionProfile("bar", "bar-arn")
val state = QProfileState().apply {
this.connectionIdToActiveProfile[activeConn.id] = fooProfile
this.connectionIdToActiveProfile[anotherConn.id] = barProfile
}
sut.loadState(state)
assertThat(sut.activeProfile(project)).isEqualTo(fooProfile)

sut.validateProfile(project)
assertThat(sut.activeProfile(project)).isEqualTo(fooProfile)
}

@Test
fun `clientSettings should return the region Q profile specify`() {
MockClientManager.useRealImplementations(disposableRule.disposable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
import com.intellij.util.xmlb.annotations.MapAnnotation
import com.intellij.util.xmlb.annotations.Property
import software.amazon.awssdk.core.SdkClient
import software.amazon.awssdk.services.codewhispererruntime.model.AccessDeniedException
import software.aws.toolkits.core.TokenConnectionSettings
import software.aws.toolkits.core.utils.debug
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.core.utils.tryOrNull
import software.aws.toolkits.core.utils.warn
import software.aws.toolkits.jetbrains.core.AwsClientManager
import software.aws.toolkits.jetbrains.core.AwsResourceCache
Expand Down Expand Up @@ -59,15 +59,28 @@
)
}

// should be call on project startup to validate if profile is still active
/**
* Called on project startup to validate if selected profile is still active
*/
@Deprecated("This is a giant hack and we are not handling all the cases")
@RequiresBackgroundThread
fun validateProfile(project: Project) {
val conn = getIdcConnectionOrNull(project)
val selected = activeProfile(project) ?: return
val profiles = tryOrNull {
val profiles = try {

Check warning on line 70 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt

View check run for this annotation

Codecov / codecov/patch

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

Added line #L70 was not covered by tests
listRegionProfiles(project)
} catch (e: Exception) {

Check warning on line 72 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt

View check run for this annotation

Codecov / codecov/patch

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

Added line #L72 was not covered by tests
if (e is AccessDeniedException) {
null

Check warning on line 74 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt

View check run for this annotation

Codecov / codecov/patch

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

Added line #L74 was not covered by tests
} else {
// if we can't list profiles assume it is valid
LOG.warn { "Continuing with $selected since listAvailableProfiles failed" }
return

Check warning on line 78 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileManager.kt

View check run for this annotation

Codecov / codecov/patch

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

Added lines #L77 - L78 were not covered by tests
}
}

// succeeded in listing profiles, but none match selected
// profiles should be null if access denied or connection is not IdC
if (profiles == null || profiles.none { it.arn == selected.arn }) {
invalidateProfile(selected.arn)
switchProfile(project, null, intent = QProfileSwitchIntent.Reload)
Expand All @@ -83,6 +96,7 @@

fun listRegionProfiles(project: Project): List<QRegionProfile>? {
val connection = getIdcConnectionOrNull(project) ?: return null

return try {
val connectionSettings = connection.getConnectionSettings()
val mappedProfiles = AwsResourceCache.getInstance().getResourceNow(
Expand Down
Loading