From 8e3b25e60683375100e463850fe83b23bea515fe Mon Sep 17 00:00:00 2001 From: Vincent Liu <5900509+onecent1101@users.noreply.github.com> Date: Fri, 6 Aug 2021 12:03:36 -0700 Subject: [PATCH] [LYN-5268] Copy resource mapping tool to install target and add argument for log path (#2819) Updates to make resource mapping tool work with the installer. Ensure correct log path. --- Gems/AWSCore/Code/CMakeLists.txt | 6 + .../Code/Include/Private/AWSCoreInternalBus.h | 5 - .../Configuration/AWSCoreConfiguration.h | 1 - .../UI/AWSCoreResourceMappingToolAction.h | 22 +-- .../Configuration/AWSCoreConfiguration.cpp | 13 -- .../Source/Editor/UI/AWSCoreEditorMenu.cpp | 4 +- .../UI/AWSCoreResourceMappingToolAction.cpp | 134 ++++++------------ .../AWSDefaultCredentialHandlerTest.cpp | 1 - .../Tests/Editor/AWSCoreEditorManagerTest.cpp | 2 - .../AWSCoreEditorSystemComponentTest.cpp | 2 - .../Tests/Editor/UI/AWSCoreEditorMenuTest.cpp | 11 -- .../AWSCoreResourceMappingToolActionTest.cpp | 16 +-- .../AWSResourceMappingManagerTest.cpp | 1 - .../Code/Tools/ResourceMappingTool/README.md | 10 ++ .../resource_mapping_tool.py | 15 +- .../tests/unit/utils/test_file_utils.py | 17 +++ .../ResourceMappingTool/utils/file_utils.py | 13 +- 17 files changed, 119 insertions(+), 154 deletions(-) diff --git a/Gems/AWSCore/Code/CMakeLists.txt b/Gems/AWSCore/Code/CMakeLists.txt index 71271eb7ee..8489e38550 100644 --- a/Gems/AWSCore/Code/CMakeLists.txt +++ b/Gems/AWSCore/Code/CMakeLists.txt @@ -166,3 +166,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ) endif() endif() + +install(DIRECTORY "Tools/ResourceMappingTool" + DESTINATION "Gems/AWSCore/Code/Tools" + COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} + PATTERN "__pycache__" EXCLUDE +) diff --git a/Gems/AWSCore/Code/Include/Private/AWSCoreInternalBus.h b/Gems/AWSCore/Code/Include/Private/AWSCoreInternalBus.h index 243d40c974..b24fe8f898 100644 --- a/Gems/AWSCore/Code/Include/Private/AWSCoreInternalBus.h +++ b/Gems/AWSCore/Code/Include/Private/AWSCoreInternalBus.h @@ -34,11 +34,6 @@ namespace AWSCore //! @return The path of AWS resource mapping config file virtual AZStd::string GetResourceMappingConfigFilePath() const = 0; - //! GetResourceMappingConfigFolderPath - //! Get the path of AWS resource mapping config folder - //! @return The path of AWS resource mapping config folder - virtual AZStd::string GetResourceMappingConfigFolderPath() const = 0; - //! ReloadConfiguration //! Reload AWSCore configuration without restarting application virtual void ReloadConfiguration() = 0; diff --git a/Gems/AWSCore/Code/Include/Private/Configuration/AWSCoreConfiguration.h b/Gems/AWSCore/Code/Include/Private/Configuration/AWSCoreConfiguration.h index 1c4bb84cad..9834f9ca38 100644 --- a/Gems/AWSCore/Code/Include/Private/Configuration/AWSCoreConfiguration.h +++ b/Gems/AWSCore/Code/Include/Private/Configuration/AWSCoreConfiguration.h @@ -50,7 +50,6 @@ namespace AWSCore // AWSCoreInternalRequestBus interface implementation AZStd::string GetResourceMappingConfigFilePath() const override; - AZStd::string GetResourceMappingConfigFolderPath() const override; AZStd::string GetProfileName() const override; void ReloadConfiguration() override; diff --git a/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreResourceMappingToolAction.h b/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreResourceMappingToolAction.h index d462e2d435..1a4c428e68 100644 --- a/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreResourceMappingToolAction.h +++ b/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreResourceMappingToolAction.h @@ -7,9 +7,11 @@ */ #pragma once +#include #include #include +#include namespace AWSCore { @@ -17,22 +19,26 @@ namespace AWSCore : public QAction { public: + static constexpr const char AWSCoreResourceMappingToolActionName[] = "AWSCoreResourceMappingToolAction"; static constexpr const char ResourceMappingToolDirectoryPath[] = "Gems/AWSCore/Code/Tools/ResourceMappingTool"; + static constexpr const char ResourceMappingToolLogDirectoryPath[] = "user/log/"; static constexpr const char EngineWindowsPythonEntryScriptPath[] = "python/python.cmd"; - AWSCoreResourceMappingToolAction(const QString& text); + AWSCoreResourceMappingToolAction(const QString& text, QObject* parent = nullptr); + + void InitAWSCoreResourceMappingToolAction(); AZStd::string GetToolLaunchCommand() const; - AZStd::string GetToolLogPath() const; + AZStd::string GetToolLogFilePath() const; AZStd::string GetToolReadMePath() const; private: bool m_isDebug; - AZStd::string m_enginePythonEntryPath; - AZStd::string m_toolScriptPath; - AZStd::string m_toolQtBinDirectoryPath; - - AZStd::string m_toolLogPath; - AZStd::string m_toolReadMePath; + AZ::IO::Path m_enginePythonEntryPath; + AZ::IO::Path m_toolScriptPath; + AZ::IO::Path m_toolQtBinDirectoryPath; + AZ::IO::Path m_toolLogDirectoryPath; + AZ::IO::Path m_toolConfigDirectoryPath; + AZ::IO::Path m_toolReadMePath; }; } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Source/Configuration/AWSCoreConfiguration.cpp b/Gems/AWSCore/Code/Source/Configuration/AWSCoreConfiguration.cpp index 46bce001e1..4653975a52 100644 --- a/Gems/AWSCore/Code/Source/Configuration/AWSCoreConfiguration.cpp +++ b/Gems/AWSCore/Code/Source/Configuration/AWSCoreConfiguration.cpp @@ -56,19 +56,6 @@ namespace AWSCore return configFilePath; } - AZStd::string AWSCoreConfiguration::GetResourceMappingConfigFolderPath() const - { - if (m_sourceProjectFolder.empty()) - { - AZ_Warning(AWSCoreConfigurationName, false, ProjectSourceFolderNotFoundErrorMessage); - return ""; - } - AZStd::string configFolderPath = AZStd::string::format( - "%s/%s", m_sourceProjectFolder.c_str(), AWSCoreResourceMappingConfigFolderName); - AzFramework::StringFunc::Path::Normalize(configFolderPath); - return configFolderPath; - } - void AWSCoreConfiguration::InitConfig() { InitSourceProjectFolderPath(); diff --git a/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp b/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp index 02dc30d887..a2c89a5af3 100644 --- a/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp +++ b/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp @@ -80,7 +80,7 @@ namespace AWSCore { #ifdef AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED AWSCoreResourceMappingToolAction* resourceMappingTool = - new AWSCoreResourceMappingToolAction(QObject::tr(AWSResourceMappingToolActionText)); + new AWSCoreResourceMappingToolAction(QObject::tr(AWSResourceMappingToolActionText), this); QObject::connect(resourceMappingTool, &QAction::triggered, this, [resourceMappingTool, this]() { AZStd::string launchCommand = resourceMappingTool->GetToolLaunchCommand(); @@ -109,7 +109,7 @@ namespace AWSCore if (!m_resourceMappingToolWatcher || !m_resourceMappingToolWatcher->IsProcessRunning()) { - AZStd::string resourceMappingToolLogPath = resourceMappingTool->GetToolLogPath(); + AZStd::string resourceMappingToolLogPath = resourceMappingTool->GetToolLogFilePath(); AZStd::string message = AZStd::string::format(AWSResourceMappingToolLogWarningText, resourceMappingToolLogPath.c_str()); QMessageBox::warning(QApplication::activeWindow(), "Warning", message.c_str(), QMessageBox::Ok); } diff --git a/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreResourceMappingToolAction.cpp b/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreResourceMappingToolAction.cpp index 2519ab87c3..858d30fa40 100644 --- a/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreResourceMappingToolAction.cpp +++ b/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreResourceMappingToolAction.cpp @@ -6,133 +6,89 @@ * */ -#include #include -#include #include +#include #include namespace AWSCore { - AWSCoreResourceMappingToolAction::AWSCoreResourceMappingToolAction(const QString& text) - : QAction(text) + AWSCoreResourceMappingToolAction::AWSCoreResourceMappingToolAction(const QString& text, QObject* parent) + : QAction(text, parent) , m_isDebug(false) - , m_enginePythonEntryPath("") - , m_toolScriptPath("") - , m_toolQtBinDirectoryPath("") - , m_toolLogPath("") - , m_toolReadMePath("") { - auto engineRootPath = AZ::IO::FileIOBase::GetInstance()->GetAlias("@engroot@"); - if (!engineRootPath) - { - AZ_Error("AWSCoreEditor", false, "Failed to determine engine root path."); - } - else - { - m_enginePythonEntryPath = AZStd::string::format("%s/%s", engineRootPath, EngineWindowsPythonEntryScriptPath); - AzFramework::StringFunc::Path::Normalize(m_enginePythonEntryPath); - if (!AZ::IO::SystemFile::Exists(m_enginePythonEntryPath.c_str())) - { - AZ_Error("AWSCoreEditor", false, "Failed to find engine python entry at %s.", m_enginePythonEntryPath.c_str()); - m_enginePythonEntryPath.clear(); - } - - m_toolScriptPath = AZStd::string::format("%s/%s/resource_mapping_tool.py", engineRootPath, ResourceMappingToolDirectoryPath); - AzFramework::StringFunc::Path::Normalize(m_toolScriptPath); - if (!AZ::IO::SystemFile::Exists(m_toolScriptPath.c_str())) - { - AZ_Error("AWSCoreEditor", false, "Failed to find ResourceMappingTool python script at %s.", m_toolScriptPath.c_str()); - m_toolScriptPath.clear(); - } - - m_toolLogPath = AZStd::string::format("%s/%s/resource_mapping_tool.log", engineRootPath, ResourceMappingToolDirectoryPath); - AzFramework::StringFunc::Path::Normalize(m_toolLogPath); - if (!AZ::IO::SystemFile::Exists(m_toolLogPath.c_str())) - { - AZ_Error("AWSCoreEditor", false, "Failed to find ResourceMappingTool log file at %s.", m_toolLogPath.c_str()); - m_toolLogPath.clear(); - } + InitAWSCoreResourceMappingToolAction(); + } - m_toolReadMePath = AZStd::string::format("%s/%s/README.md", engineRootPath, ResourceMappingToolDirectoryPath); - AzFramework::StringFunc::Path::Normalize(m_toolReadMePath); - if (!AZ::IO::SystemFile::Exists(m_toolReadMePath.c_str())) - { - AZ_Error("AWSCoreEditor", false, "Failed to find ResourceMappingTool README file at %s.", m_toolReadMePath.c_str()); - m_toolReadMePath.clear(); - } + void AWSCoreResourceMappingToolAction::InitAWSCoreResourceMappingToolAction() + { + AZ::IO::Path engineRootPath = AZ::IO::PathView(AZ::Utils::GetEnginePath()); + m_enginePythonEntryPath = (engineRootPath / EngineWindowsPythonEntryScriptPath).LexicallyNormal(); + m_toolScriptPath = (engineRootPath / ResourceMappingToolDirectoryPath / "resource_mapping_tool.py").LexicallyNormal(); + m_toolReadMePath = (engineRootPath / ResourceMappingToolDirectoryPath / "README.md").LexicallyNormal(); - char executablePath[AZ_MAX_PATH_LEN]; - auto result = AZ::Utils::GetExecutablePath(executablePath, AZ_MAX_PATH_LEN); - if (result.m_pathStored != AZ::Utils::ExecutablePathResult::Success) - { - AZ_Error("AWSCoreEditor", false, "Failed to find engine executable path."); - } - else - { - if (result.m_pathIncludesFilename) - { - // Remove the file name if it exists, and keep the parent folder only - char* lastSeparatorAddress = strrchr(executablePath, AZ_CORRECT_FILESYSTEM_SEPARATOR); - if (lastSeparatorAddress) - { - *lastSeparatorAddress = '\0'; - } - } - } + AZ::IO::Path projectPath = AZ::IO::PathView(AZ::Utils::GetProjectPath()); + m_toolLogDirectoryPath = (projectPath / ResourceMappingToolLogDirectoryPath).LexicallyNormal(); + m_toolConfigDirectoryPath = (projectPath / AWSCoreConfiguration::AWSCoreResourceMappingConfigFolderName).LexicallyNormal(); - AZStd::string binDirectoryPath(executablePath); - auto lastSeparator = binDirectoryPath.find_last_of(AZ_CORRECT_FILESYSTEM_SEPARATOR); - if (lastSeparator != AZStd::string::npos) - { - m_isDebug = binDirectoryPath.substr(lastSeparator).contains("debug"); - } + AZ::IO::Path executablePath = AZ::IO::PathView(AZ::Utils::GetExecutableDirectory()); + m_toolQtBinDirectoryPath = (executablePath / "AWSCoreEditorQtBin").LexicallyNormal(); - m_toolQtBinDirectoryPath = AZStd::string::format("%s/%s", binDirectoryPath.c_str(), "AWSCoreEditorQtBin"); - AzFramework::StringFunc::Path::Normalize(m_toolQtBinDirectoryPath); - if (!AZ::IO::SystemFile::Exists(m_toolQtBinDirectoryPath.c_str())) - { - AZ_Error("AWSCoreEditor", false, "Failed to find ResourceMappingTool Qt binaries at %s.", m_toolQtBinDirectoryPath.c_str()); - m_toolQtBinDirectoryPath.clear(); - } - } + m_isDebug = AZStd::string_view(AZ_BUILD_CONFIGURATION_TYPE) == "debug"; } AZStd::string AWSCoreResourceMappingToolAction::GetToolLaunchCommand() const { - if (m_enginePythonEntryPath.empty() || m_toolScriptPath.empty() || m_toolQtBinDirectoryPath.empty()) + if (!AZ::IO::SystemFile::Exists(m_enginePythonEntryPath.c_str()) || + !AZ::IO::SystemFile::Exists(m_toolScriptPath.c_str()) || + !AZ::IO::SystemFile::Exists(m_toolQtBinDirectoryPath.c_str()) || + !AZ::IO::SystemFile::Exists(m_toolConfigDirectoryPath.c_str()) || + !AZ::IO::SystemFile::Exists(m_toolLogDirectoryPath.c_str())) { + AZ_Error(AWSCoreResourceMappingToolActionName, false, + "Expected parameter for tool launch command is invalid, engine python path: %s, tool script path: %s, tool qt binaries path: %s, tool config path: %s, tool log path: %s", + m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(), m_toolConfigDirectoryPath.c_str(), m_toolLogDirectoryPath.c_str()); return ""; } AZStd::string profileName = "default"; AWSCoreInternalRequestBus::BroadcastResult(profileName, &AWSCoreInternalRequests::GetProfileName); - AZStd::string configPath = ""; - AWSCoreInternalRequestBus::BroadcastResult(configPath, &AWSCoreInternalRequests::GetResourceMappingConfigFolderPath); - if (m_isDebug) { return AZStd::string::format( - "%s debug %s --binaries_path %s --debug --profile %s --config_path %s", m_enginePythonEntryPath.c_str(), - m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(), profileName.c_str(), configPath.c_str()); + "\"%s\" debug -B \"%s\" --binaries-path \"%s\" --debug --profile \"%s\" --config-path \"%s\" --log-path \"%s\"", + m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(), + profileName.c_str(), m_toolConfigDirectoryPath.c_str(), m_toolLogDirectoryPath.c_str()); } else { return AZStd::string::format( - "%s %s --binaries_path %s --profile %s --config_path %s", m_enginePythonEntryPath.c_str(), - m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(), profileName.c_str(), configPath.c_str()); + "\"%s\" -B \"%s\" --binaries-path \"%s\" --profile \"%s\" --config-path \"%s\" --log-path \"%s\"", + m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(), + profileName.c_str(), m_toolConfigDirectoryPath.c_str(), m_toolLogDirectoryPath.c_str()); } } - AZStd::string AWSCoreResourceMappingToolAction::GetToolLogPath() const + AZStd::string AWSCoreResourceMappingToolAction::GetToolLogFilePath() const { - return m_toolLogPath; + AZ::IO::Path toolLogFilePath = (m_toolLogDirectoryPath / "resource_mapping_tool.log").LexicallyNormal(); + if (!AZ::IO::SystemFile::Exists(toolLogFilePath.c_str())) + { + AZ_Error(AWSCoreResourceMappingToolActionName, false, "Invalid tool log file path: %s", toolLogFilePath.c_str()); + return ""; + } + return toolLogFilePath.Native(); } AZStd::string AWSCoreResourceMappingToolAction::GetToolReadMePath() const { - return m_toolReadMePath; + if (!AZ::IO::SystemFile::Exists(m_toolReadMePath.c_str())) + { + AZ_Error(AWSCoreResourceMappingToolActionName, false, "Invalid tool readme path: %s", m_toolReadMePath.c_str()); + return ""; + } + return m_toolReadMePath.Native(); } } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Tests/Credential/AWSDefaultCredentialHandlerTest.cpp b/Gems/AWSCore/Code/Tests/Credential/AWSDefaultCredentialHandlerTest.cpp index e1acd3e3d9..b3e2ec5738 100644 --- a/Gems/AWSCore/Code/Tests/Credential/AWSDefaultCredentialHandlerTest.cpp +++ b/Gems/AWSCore/Code/Tests/Credential/AWSDefaultCredentialHandlerTest.cpp @@ -73,7 +73,6 @@ public: // AWSCoreInternalRequestBus interface implementation AZStd::string GetProfileName() const override { return m_profileName; } AZStd::string GetResourceMappingConfigFilePath() const override { return ""; } - AZStd::string GetResourceMappingConfigFolderPath() const override { return ""; } void ReloadConfiguration() override {} std::shared_ptr m_environmentCredentialsProviderMock; diff --git a/Gems/AWSCore/Code/Tests/Editor/AWSCoreEditorManagerTest.cpp b/Gems/AWSCore/Code/Tests/Editor/AWSCoreEditorManagerTest.cpp index e2ace4212f..9a0063e5a9 100644 --- a/Gems/AWSCore/Code/Tests/Editor/AWSCoreEditorManagerTest.cpp +++ b/Gems/AWSCore/Code/Tests/Editor/AWSCoreEditorManagerTest.cpp @@ -34,8 +34,6 @@ class AWSCoreEditorManagerTest TEST_F(AWSCoreEditorManagerTest, AWSCoreEditorManager_Constructor_HaveExpectedUIResourcesCreated) { - AZ_TEST_START_TRACE_SUPPRESSION; AWSCoreEditorManager testManager; - AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error EXPECT_TRUE(testManager.GetAWSCoreEditorMenu()); } diff --git a/Gems/AWSCore/Code/Tests/Editor/AWSCoreEditorSystemComponentTest.cpp b/Gems/AWSCore/Code/Tests/Editor/AWSCoreEditorSystemComponentTest.cpp index b722c83950..07a6c8ae08 100644 --- a/Gems/AWSCore/Code/Tests/Editor/AWSCoreEditorSystemComponentTest.cpp +++ b/Gems/AWSCore/Code/Tests/Editor/AWSCoreEditorSystemComponentTest.cpp @@ -41,9 +41,7 @@ class AWSCoreEditorSystemComponentTest m_entity = aznew AZ::Entity(); m_coreEditorSystemsComponent.reset(m_entity->CreateComponent()); - AZ_TEST_START_TRACE_SUPPRESSION; m_entity->Init(); - AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error m_entity->Activate(); } diff --git a/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreEditorMenuTest.cpp b/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreEditorMenuTest.cpp index 295818c44c..40ed5b53b5 100644 --- a/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreEditorMenuTest.cpp +++ b/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreEditorMenuTest.cpp @@ -42,18 +42,9 @@ class AWSCoreEditorMenuTest } }; -TEST_F(AWSCoreEditorMenuTest, AWSCoreEditorMenu_NoEngineRootFolder_ExpectOneError) -{ - AZ_TEST_START_TRACE_SUPPRESSION; - AWSCoreEditorMenu testMenu("dummy title"); - AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error -} - TEST_F(AWSCoreEditorMenuTest, AWSCoreEditorMenu_GetAllActions_GetExpectedNumberOfActions) { - AZ_TEST_START_TRACE_SUPPRESSION; AWSCoreEditorMenu testMenu("dummy title"); - AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error QList actualActions = testMenu.actions(); #ifdef AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED @@ -65,9 +56,7 @@ TEST_F(AWSCoreEditorMenuTest, AWSCoreEditorMenu_GetAllActions_GetExpectedNumberO TEST_F(AWSCoreEditorMenuTest, AWSCoreEditorMenu_BroadcastFeatureGemsAreEnabled_CorrespondingActionsAreEnabled) { - AZ_TEST_START_TRACE_SUPPRESSION; AWSCoreEditorMenu testMenu("dummy title"); - AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error AWSCoreEditorRequestBus::Broadcast(&AWSCoreEditorRequests::SetAWSClientAuthEnabled); AWSCoreEditorRequestBus::Broadcast(&AWSCoreEditorRequests::SetAWSMetricsEnabled); diff --git a/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreResourceMappingToolActionTest.cpp b/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreResourceMappingToolActionTest.cpp index 4a027ec920..81e7eda21e 100644 --- a/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreResourceMappingToolActionTest.cpp +++ b/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreResourceMappingToolActionTest.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include @@ -24,7 +25,6 @@ class AWSCoreResourceMappingToolActionTest { AWSCoreEditorUIFixture::SetUp(); AWSCoreFixture::SetUp(); - m_localFileIO->SetAlias("@engroot@", "dummy engine root"); } void TearDown() override @@ -34,20 +34,12 @@ class AWSCoreResourceMappingToolActionTest } }; -TEST_F(AWSCoreResourceMappingToolActionTest, AWSCoreResourceMappingToolAction_NoEngineRootFolder_ExpectOneError) +TEST_F(AWSCoreResourceMappingToolActionTest, AWSCoreResourceMappingToolAction_NoEngineRootPath_ExpectErrorsAndResult) { - m_localFileIO->ClearAlias("@engroot@"); - AZ_TEST_START_TRACE_SUPPRESSION; AWSCoreResourceMappingToolAction testAction("dummy title"); - AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error -} - -TEST_F(AWSCoreResourceMappingToolActionTest, AWSCoreResourceMappingToolAction_UnableToFindExpectedFileOrFolder_ExpectFiveErrorsAndEmptyResult) -{ AZ_TEST_START_TRACE_SUPPRESSION; - AWSCoreResourceMappingToolAction testAction("dummy title"); - AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT; EXPECT_TRUE(testAction.GetToolLaunchCommand() == ""); - EXPECT_TRUE(testAction.GetToolLogPath() == ""); + EXPECT_TRUE(testAction.GetToolLogFilePath() == ""); EXPECT_TRUE(testAction.GetToolReadMePath() == ""); + AZ_TEST_STOP_TRACE_SUPPRESSION(3); } diff --git a/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp b/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp index ebd13fbcb8..557fbc820c 100644 --- a/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp +++ b/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp @@ -115,7 +115,6 @@ public: // AWSCoreInternalRequestBus interface implementation AZStd::string GetProfileName() const override { return ""; } AZStd::string GetResourceMappingConfigFilePath() const override { return m_normalizedConfigFilePath; } - AZStd::string GetResourceMappingConfigFolderPath() const override { return m_normalizedConfigFolderPath; } void ReloadConfiguration() override { m_reloadConfigurationCounter++; } AZStd::unique_ptr m_resourceMappingManager; diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/README.md b/Gems/AWSCore/Code/Tools/ResourceMappingTool/README.md index 78a8856288..e09ecc281f 100644 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/README.md +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/README.md @@ -89,3 +89,13 @@ you can create the virtualenv manually. ``` $ python3 resource_mapping_tool.py ``` +## Tool Arguments +* `--binaries-path` **[Optional]** Path to QT Binaries necessary for PySide, + required if launching tool with engine python environment. +* `--config-path` **[Optional]** Path to resource mapping config directory, + if not provided tool will use current directory. +* `--debug` **[Optional]** Execute on debug mode to enable DEBUG logging level. +* `--log-path` **[Optional]** Path to resource mapping tool logging directory, + if not provided tool will store logging under tool source code directory. +* `--profile` **[Optional]** Named AWS profile to use for querying AWS resources, + if not provided tool will use `default` aws profile. \ No newline at end of file diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/resource_mapping_tool.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/resource_mapping_tool.py index ec27fb3cf7..2351fd001b 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/resource_mapping_tool.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/resource_mapping_tool.py @@ -9,15 +9,16 @@ from argparse import (ArgumentParser, Namespace) import logging import sys -from utils import aws_utils from utils import environment_utils from utils import file_utils # arguments setup argument_parser: ArgumentParser = ArgumentParser() -argument_parser.add_argument('--binaries_path', help='Path to QT Binaries necessary for PySide.') -argument_parser.add_argument('--config_path', help='Path to resource mapping config directory.') +argument_parser.add_argument('--binaries-path', help='Path to QT Binaries necessary for PySide.') +argument_parser.add_argument('--config-path', help='Path to resource mapping config directory.') argument_parser.add_argument('--debug', action='store_true', help='Execute on debug mode to enable DEBUG logging level') +argument_parser.add_argument('--log-path', help='Path to resource mapping tool logging directory ' + '(if not provided, logging file will be located at tool directory)') argument_parser.add_argument('--profile', default='default', help='Named AWS profile to use for querying AWS resources') arguments: Namespace = argument_parser.parse_args() @@ -25,8 +26,11 @@ arguments: Namespace = argument_parser.parse_args() logging_level: int = logging.INFO if arguments.debug: logging_level = logging.DEBUG -logging_path: str = file_utils.join_path(file_utils.get_parent_directory_path(__file__), - 'resource_mapping_tool.log') +logging_path: str = file_utils.join_path(file_utils.get_parent_directory_path(__file__), 'resource_mapping_tool.log') +if arguments.log_path: + normalized_logging_path: str = file_utils.normalize_file_path(arguments.log_path, False) + if normalized_logging_path and file_utils.create_directory(normalized_logging_path): + logging_path = file_utils.join_path(normalized_logging_path, 'resource_mapping_tool.log') logging.basicConfig(filename=logging_path, filemode='w', level=logging_level, format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s', datefmt='%H:%M:%S') logging.getLogger('boto3').setLevel(logging.CRITICAL) @@ -34,6 +38,7 @@ logging.getLogger('botocore').setLevel(logging.CRITICAL) logging.getLogger('s3transfer').setLevel(logging.CRITICAL) logging.getLogger('urllib3').setLevel(logging.CRITICAL) logger = logging.getLogger(__name__) +logger.info(f"Using {logging_path} for logging.") if __name__ == "__main__": if arguments.binaries_path and not environment_utils.is_qt_linked(): diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_file_utils.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_file_utils.py index ea0630af49..fe0f1754f3 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_file_utils.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/tests/unit/utils/test_file_utils.py @@ -44,6 +44,23 @@ class TestFileUtils(TestCase): mocked_path.exists.assert_called_once() assert not actual_result + def test_create_directory_return_true(self) -> None: + mocked_path: MagicMock = self._mock_path.return_value + + actual_result: bool = file_utils.create_directory("dummy") + self._mock_path.assert_called_once() + mocked_path.mkdir.assert_called_once() + assert actual_result + + def test_create_directory_return_false_when_exception_raised(self) -> None: + mocked_path: MagicMock = self._mock_path.return_value + mocked_path.mkdir.side_effect = FileExistsError() + + actual_result: bool = file_utils.create_directory("dummy") + self._mock_path.assert_called_once() + mocked_path.mkdir.assert_called_once() + assert not actual_result + def test_get_current_directory_path_return_expected_path_name(self) -> None: self._mock_path.cwd.return_value = TestFileUtils._expected_path_name diff --git a/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/file_utils.py b/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/file_utils.py index 024c620948..9e5dd9617b 100755 --- a/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/file_utils.py +++ b/Gems/AWSCore/Code/Tools/ResourceMappingTool/utils/file_utils.py @@ -20,6 +20,15 @@ def check_path_exists(file_path: str) -> bool: return pathlib.Path(file_path).exists() +def create_directory(dir_path: str) -> bool: + try: + pathlib.Path(dir_path).mkdir(parents=True, exist_ok=True) + return True + except FileExistsError: + logger.warning(f"Failed to create directory at {dir_path}") + return False + + def get_current_directory_path() -> str: return str(pathlib.Path.cwd()) @@ -40,10 +49,10 @@ def find_files_with_suffix_under_directory(dir_path: str, suffix: str) -> List[s return results -def normalize_file_path(file_path: str) -> str: +def normalize_file_path(file_path: str, strict: bool = True) -> str: if file_path: try: - return str(pathlib.Path(file_path).resolve(True)) + return str(pathlib.Path(file_path).resolve(strict)) except (FileNotFoundError, RuntimeError): logger.warning(f"Failed to normalize file path {file_path}, return empty string instead") return ""