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

refresh virtual file manually on config/credentials file op #4430

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ abstract class CredentialManager : SimpleModificationTracker() {
providerIds[identifier.id] = identifier

incModificationCount()
println("CredentialManager:: addProvider and is publishing CREDENTIALS_CHANGED event")
ApplicationManager.getApplication().messageBus.syncPublisher(CREDENTIALS_CHANGED).providerAdded(identifier)
}

Expand All @@ -53,6 +54,7 @@ abstract class CredentialManager : SimpleModificationTracker() {
providerIds[identifier.id] = identifier

incModificationCount()
println("CredentialManager:: modifyProvider")
ApplicationManager.getApplication().messageBus.syncPublisher(CREDENTIALS_CHANGED).providerModified(identifier)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ abstract class AwsConnectionManager(private val project: Project) : SimpleModifi
@Volatile
var connectionState: ConnectionState = ConnectionState.InitializingToolkit
internal set(value) {
println("AwsConnectionManager:: connectionState setter: set value to be ${value}")
field = value
incModificationCount()

AppUIExecutor.onWriteThread(ModalityState.any()).expireWith(this).execute {
println("AwsConnectionManager:: publishing AwsConnectionManager.CONNECTION_SETTINGS_STATE_CHANGED")
project.messageBus.syncPublisher(CONNECTION_SETTINGS_STATE_CHANGED).settingsStateChanged(value)
}
}
Expand All @@ -64,6 +66,11 @@ abstract class AwsConnectionManager(private val project: Project) : SimpleModifi
.subscribe(
CredentialManager.CREDENTIALS_CHANGED,
object : ToolkitCredentialsChangeListener {
override fun providerAdded(identifier: CredentialIdentifier) {
println("AwsConnectionManager:: receives CredentialManager.CREDENTIALS_CHANGED topic")
changeCredentialProvider(identifier)
}

override fun providerRemoved(identifier: CredentialIdentifier) {
if (selectedCredentialIdentifier == identifier) {
changeConnectionSettings(null, selectedRegion)
Expand All @@ -90,6 +97,7 @@ abstract class AwsConnectionManager(private val project: Project) : SimpleModifi
* Re-trigger validation of the current connection
*/
fun refreshConnectionState() {
println("AwsConnectionManager:: refreshConnectionState")
changeFieldsAndNotify { }
}

Expand All @@ -98,6 +106,7 @@ abstract class AwsConnectionManager(private val project: Project) : SimpleModifi
*/
protected fun changeConnectionSettings(identifier: CredentialIdentifier?, region: AwsRegion?) {
changeFieldsAndNotify {
println("AwsConnectionManager:: changeConnectionSettings")
identifier?.let {
recentlyUsedProfiles.add(it.id)
}
Expand All @@ -115,8 +124,10 @@ abstract class AwsConnectionManager(private val project: Project) : SimpleModifi
* Changes the credentials and then validates them. Notifies listeners of results
*/
fun changeCredentialProvider(identifier: CredentialIdentifier, passive: Boolean = false) {
println("AwsConnectionManager:: changeCredentialProvider")
changeFieldsAndNotify {
recentlyUsedProfiles.add(identifier.id)
println("AwsConnectionManager:: changeCredentialProvider: setting credential being used to ${identifier.id}")

selectedCredentialIdentifier = identifier

Expand Down Expand Up @@ -145,18 +156,22 @@ abstract class AwsConnectionManager(private val project: Project) : SimpleModifi

@Synchronized
private fun changeFieldsAndNotify(fieldUpdateBlock: () -> Unit) {
println("AwsConnectionManager:: changeFieldsAndNotify")
val isInitial = connectionState is ConnectionState.InitializingToolkit
connectionState = ConnectionState.ValidatingConnection

// Grab the current state stamp
val modificationStamp = this.modificationCount

println("AwsConnectionManager:: changeFieldsAndNotify: before updating fields")
fieldUpdateBlock()
println("AwsConnectionManager:: changeFieldsAndNotify: done updating fields")

val validateCredentialsResult = validateCredentials(selectedCredentialIdentifier, selectedRegion, isInitial)
validationJob.getAndSet(validateCredentialsResult)?.cancel()

validateCredentialsResult.onSuccess {
println("AwsConnectionManager:: changeFieldsAndNotify : validateOnSuccess")
// Validate we are still operating in the latest view of the world
if (modificationStamp == this.modificationCount) {
connectionState = it
Expand All @@ -168,25 +183,31 @@ abstract class AwsConnectionManager(private val project: Project) : SimpleModifi

private fun validateCredentials(credentialsIdentifier: CredentialIdentifier?, region: AwsRegion?, isInitial: Boolean): AsyncPromise<ConnectionState> {
val promise = AsyncPromise<ConnectionState>()
println("AwsConnectionManager:: validateCredentials: start validation in background thread")
ApplicationManager.getApplication().executeOnPooledThread {
if (credentialsIdentifier == null || region == null) {
promise.setResult(ConnectionState.IncompleteConfiguration(credentialsIdentifier, region))
println("AwsConnectionManager:: validateCredentials: return @ 1")
return@executeOnPooledThread
}

if (isInitial && credentialsIdentifier is InteractiveCredential && credentialsIdentifier.userActionRequired()) {
promise.setResult(ConnectionState.RequiresUserAction(credentialsIdentifier))
println("AwsConnectionManager:: validateCredentials: return @ 2")
return@executeOnPooledThread
}

var success = true
println("AwsConnectionManager:: Before validating credential...")
try {
val credentialsProvider = CredentialManager.getInstance().getAwsCredentialProvider(credentialsIdentifier, region)

validate(credentialsProvider, region)

println("AwsConnectionManager:: Done validating credential")
promise.setResult(ConnectionState.ValidConnection(credentialsProvider, region))
} catch (e: Exception) {
println("AwsConnectionManager:: Failed to switch to profile ${credentialsIdentifier.displayName}")
LOGGER.warn(e) { message("credentials.profile.validation_error", credentialsIdentifier.displayName) }
val result = if (credentialsIdentifier is PostValidateInteractiveCredential) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package software.aws.toolkits.jetbrains.core.credentials

import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.vfs.VirtualFileManager
import software.amazon.awssdk.profiles.Profile
import software.amazon.awssdk.profiles.ProfileFile
import software.amazon.awssdk.profiles.ProfileFileLocation
Expand Down Expand Up @@ -287,5 +288,12 @@ class DefaultConfigFilesFacade(
touch(restrictToOwner = true)
appendText(body)
}


// not sure why VirtualFileManager.getInstance().refreshAndFindFileByNioPath() not work as this
VirtualFileManager.getInstance().findFileByNioPath(path)?.let {
println("ConfigFilesFacade:: refreshing virtual file ${it.name}")
it.refresh(false, false)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

package software.aws.toolkits.jetbrains.core.credentials

import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFileManager
Expand Down Expand Up @@ -124,6 +125,7 @@ sealed interface Login {
}

if (callerIdentity == null) {
println("LoginUtil:: callerIdentity is null, return")
onConnectionValidationError()
return false
}
Expand All @@ -138,11 +140,9 @@ sealed interface Login {
)
.build()

println("LoginUtil:: before appendProfileToCredentials")
configFilesFacade.appendProfileToCredentials(profile)

// TODO: how to refresh partially?
// TODO: should it live in configFileFacade
VirtualFileManager.getInstance().refreshWithoutFileWatcher(false)
println("LoginUtil:: after appendProfileToCredentials")

return true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class ProfileCredentialsIdentifierSso @TestOnly constructor(
}

// true exception could be further up the chain
private inline fun<reified T : Throwable> findUpException(e: Throwable?): Boolean {
private inline fun <reified T : Throwable> findUpException(e: Throwable?): Boolean {
// inline fun can't use recursion
var throwable = e
while (throwable != null) {
Expand Down Expand Up @@ -156,6 +156,7 @@ class ProfileCredentialProviderFactory(private val ssoCache: SsoCache = diskCach
loadProfiles(credentialLoadCallback, true)

ProfileWatcher.getInstance().addListener {
println("ProfileWatcher:: loadProfiles...")
loadProfiles(credentialLoadCallback, false)
}
}
Expand All @@ -181,6 +182,7 @@ class ProfileCredentialProviderFactory(private val ssoCache: SsoCache = diskCach
val previousProfile = currentConfig.profiles.remove(it.key)
if (previousProfile == null) {
// It was not in the snapshot, so it must be new
println("ProfileCredentialProviderFactory:: loadProfiles: adding profile ${it.value.name()} to profilesAdded")
profilesAdded.add(it.value.asId(newProfiles.validProfiles))
} else {
// If the profile was modified, notify listeners, else do nothing
Expand Down Expand Up @@ -243,7 +245,14 @@ class ProfileCredentialProviderFactory(private val ssoCache: SsoCache = diskCach
credentialLoadCallback(CredentialsChangeEvent(profilesAdded, profilesModified, profilesRemoved, ssoAdded, ssoModified, ssoRemoved))

notifyUserOfResult(newProfiles, initialLoad)
println("ProfileCredentialProviderFactory:: notifyUserResult")

println("ProfileCredentialProviderFactory:: profilesAdded.isNotEmpty()=${profilesAdded.isNotEmpty()}; profilesAdded=${profilesAdded.map { it.profileName }}")
println("ProfileCredentialProviderFactory:: newProfiles.validProfiles.size=${newProfiles.validProfiles.size}; newProfiles.validProfiles=${newProfiles.validProfiles.values.map { it.name() }}")
println("ProfileCredentialProviderFactory:: newProfiles.invalidProfiles.size=${newProfiles.invalidProfiles.size}")

if (profilesAdded.isNotEmpty() && newProfiles.validProfiles.size == 1) {
println("ProfileCredentialProviderFactory:: send message NEW_PROFILE_ADDED")
ApplicationManager.getApplication().messageBus.syncPublisher(NEW_PROFILE_ADDED).changeConnection(profilesAdded.first())
}
}
Expand Down Expand Up @@ -352,10 +361,12 @@ class ProfileCredentialProviderFactory(private val ssoCache: SsoCache = diskCach
?: throw IllegalStateException("Profile $sourceProfileName looks to have been removed")
createAwsCredentialProvider(sourceProfile, region)
}

credentialSource.isPresent -> {
// Can we parse the credential_source
credentialSourceCredentialProvider(CredentialSourceType.parse(credentialSource.get()), profile)
}

else -> {
throw IllegalArgumentException(message("credentials.profile.assume_role.missing_source", profile.name()))
}
Expand All @@ -373,6 +384,7 @@ class ProfileCredentialProviderFactory(private val ssoCache: SsoCache = diskCach
.endpoint(profile.getEc2MedataEndpoint())
.build()
}

CredentialSourceType.ENVIRONMENT -> AwsCredentialsProviderChain.builder()
.addCredentialsProvider(SystemPropertyCredentialsProvider.create())
.addCredentialsProvider(EnvironmentVariableCredentialsProvider.create())
Expand Down Expand Up @@ -411,12 +423,14 @@ class ProfileCredentialProviderFactory(private val ssoCache: SsoCache = diskCach
this.traverseCredentialChain(profiles).map { it.property(ProfileProperty.SSO_START_URL) }.first { it.isPresent }.get(),
requestedProfileType
)

this.requiresSso() -> ProfileCredentialsIdentifierSso(
name,
requiredProperty(SsoSessionConstants.PROFILE_SSO_SESSION_PROPERTY),
defaultRegion,
requestedProfileType
)

else -> ProfileCredentialsIdentifier(name, defaultRegion, requestedProfileType)
}
}
Expand Down Expand Up @@ -456,6 +470,7 @@ private fun Profile.toCredentialType(): CredentialType? = when {
CredentialType.AssumeRoleProfile
}
}

this.propertyExists(ProfileProperty.AWS_SESSION_TOKEN) -> CredentialType.StaticSessionProfile
this.propertyExists(ProfileProperty.AWS_ACCESS_KEY_ID) -> CredentialType.StaticProfile
this.propertyExists(ProfileProperty.CREDENTIAL_PROCESS) -> CredentialType.CredentialProcessProfile
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ package software.aws.toolkits.jetbrains.core.credentials

import com.intellij.openapi.project.Project
import software.aws.toolkits.jetbrains.core.credentials.profiles.ProfileCredentialsIdentifier
import software.aws.toolkits.jetbrains.core.explorer.showExplorerTree

class RefreshExplorerCredentials(val project: Project) : ChangeConnectionSettingIfValid {

override fun changeConnection(profile: ProfileCredentialsIdentifier) {
super.changeConnection(profile)
println("RefreshExplorerCredentials:: ${profile.profileName}")
AwsConnectionManager.getInstance(project).changeCredentialProvider(profile)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class AwsToolkitExplorerFactory : ToolWindowFactory, DumbAware {
AwsConnectionManager.CONNECTION_SETTINGS_STATE_CHANGED,
object : ConnectionSettingsStateChangeNotifier {
override fun settingsStateChanged(newState: ConnectionState) {
println("AwsToolkitExplorererFactory:: received message AwsConnectionManager.CONNECTION_SETTINGS_STATE_CHANGED : ${newState}")
settingsStateChanged(project, newState)
}
}
Expand Down Expand Up @@ -165,6 +166,7 @@ class AwsToolkitExplorerFactory : ToolWindowFactory, DumbAware {
}

LOG.debug { "settingsStateChanged: ${newState::class.simpleName}; isToolkitConnected=$isToolkitConnected" }
println("settingsStateChanged: ${newState::class.simpleName}; isToolkitConnected=$isToolkitConnected")

if (!isToolkitConnected || shouldPromptToolkitReauth(project)) {
ToolkitWebviewPanel.getInstance(project).browser?.prepareBrowser(BrowserState(FeatureId.AwsExplorer))
Expand All @@ -181,10 +183,12 @@ class AwsToolkitExplorerFactory : ToolWindowFactory, DumbAware {
}

fun showWebview(project: Project) {
println("showing Toolkit webview")
AwsToolkitExplorerToolWindow.toolWindow(project).loadContent(ToolkitWebviewPanel.getInstance(project).component)
}

fun showExplorerTree(project: Project) {
println("showing AWS explorer tree")
AwsToolkitExplorerToolWindow.toolWindow(project).loadContent(AwsToolkitExplorerToolWindow.getInstance(project))
}

Expand Down