/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #pragma once #include #include #include #include #include #include #include "PythonWorker.h" struct IEditor; class CloudCanvasLogger; class AWSImporterModel; class AWSProfileModel; class AWSDeploymentModel; class AWSProjectModel; class CloudFormationTemplateModel; class ProjectStatusModel; class DeploymentStatusModel; class ResourceGroupStatusModel; class DeploymentListStatusModel; class ResourceGroupListStatusModel; class IFileSourceControlModel; class AWSResourceManager : public IAWSResourceManager { Q_OBJECT public: AWSResourceManager(IEditor* editor); ~AWSResourceManager(); QSharedPointer GetImporterModel() override; QSharedPointer GetDeploymentModel() override; QSharedPointer GetProfileModel() override; QSharedPointer GetProjectModel() override; QSharedPointer GetProjectModelInternal(); QSharedPointer GetProjectStatusModel(); QSharedPointer GetDeploymentStatusModel(const QString& deployment); QSharedPointer GetResourceGroupStatusModel(const QString& resourceGroup); QSharedPointer GetDeploymentListStatusModel(); QSharedPointer GetResourceGroupListStatusModel(); QSharedPointer GetActiveDeploymentStatusModel(); void OnInit(); void OnBeginGameMode(); void CheckGameConfigurations(); void RefreshGameConfigurations(); bool IsProjectInitialized() const override { return m_initializationState == InitializedState; } InitializationState GetInitializationState() override { return m_initializationState; } QString GetErrorString() const override; void RetryLoading() override; // The ExecuteAsync and ExecuteAsyncWithRetry methods can be used to submit // commands to the resource manager's Python implementation. // // There are two ways to get output. The preferred (and newer) way is to provide an // ExecuteAsyncCallback function when submitting the request. // // Alternatively you can provide a requestId produce by calling AllocateRequestId and // wire up a handler to the CommandOutput signal. In this case YOU MUST IGNORE // all invocations where the resourceId is not the one provided when submitting the // request. // // The callback or signal function will be called once for each output produced by the // operation. This may include output data with a key value unique to the command. It // may also include progress messages where key is "message". If the operation succeeds, // the function will be called for a final time with key == "success". If the // operation fails, the function will be called for a final time with key == "error". // // You can also submit commands with retry enabled. If these command fail, they are // put in failed command list and the project's state is set to ErrorLoadingState. The // failed command can then be retried by calling RetryLoading. When retry is enabled, // the callback or signal function will not be called with key == "error". using RequestId = PythonWorkerRequestId; RequestId AllocateRequestId() { return m_pythonWorker->AllocateRequestId(); } void ExecuteAsync(RequestId requestId, const char* command, const QVariantMap& args = QVariantMap{}, bool failOnLoadError = false); void ExecuteAsyncWithRetry(RequestId requestId, const char* command, const QVariantMap& args = QVariantMap{}); using ExecuteAsyncCallback = AZStd::function; void ExecuteAsync(ExecuteAsyncCallback callback, const char* command, const QVariantMap& args = QVariantMap{}, bool failOnLoadError = false); void ExecuteAsyncWithRetry(ExecuteAsyncCallback callback, const char* command, const QVariantMap& args = QVariantMap{}); void GetRegionList() override; bool InitializeProject(const QString& region, const QString& stackName, const QString& accessKey, const QString& secretKey, bool createAdminRoles) override; void RequestEditProjectSettings() override; void RequestEditDeploymentTemplate() override; void RequestEditGemsFile() override; void RequestAddFile(const QString& path) override; void RequestDeleteFile(const QString& path) override; static void RequestUpdateSourceModel(QSharedPointer sourceModel, QSharedPointer contentModel); static void RequestEditSourceModel(QSharedPointer sourceModel, QSharedPointer contentModel); bool ProjectSettingsNeedsCheckout() const override; bool DeploymentTemplateNeedsCheckout() const override; bool GemsFileNeedsCheckout() const override; QSharedPointer GetProjectSettingsSourceModel() override { return m_projectSettingsSourceControlModel; } QSharedPointer GetDeploymentTemplateSourceModel() override { return m_deploymentTemplateSourceControlModel; } QSharedPointer GetGemsFileSourceModel() override { return m_gemsFileSourceControlModel; } // Status void UpdateSourceControlStates() override; bool IsOperationInProgress() override; void OperationStarted(); void OperationFinished(); /// Returns true if resource groups have been created locally. If not, it's likely that the stack contains no deployments. bool HasResourcGroups() { return m_hasResourceGroups; } /// This gets called when a stack resource model updates and makes sure HasResourceGroups returns the correct value void RefreshHasResourceGroupsStatus(); /// Pointer to Cloud Canvas specific logger QSharedPointer GetLogger() { return m_logger; } void RefreshDeploymentList(); void RefreshProjectDescription(); void RefreshResourceGroupList(); void RefreshProfileList(); void RefreshMappingsList(); void RefreshMappings(); AZStd::string GetIdentityId(); signals: void ProcessOutputResourceList(RequestId requestId, const QVariant& value); void CommandOutput(RequestId requestId, const char* key, const QVariant& value); void ActiveDeploymentChanged(const QString& activeDeploymentName); private slots: void ProcessPythonOutput(PythonWorkerRequestId requestId, const QString& key, const QVariant& value); void OnFileChanged(FileChangeMonitor::MonitoredFileType fileType, QString fileName); private: // Editor IEditor* m_editor; static AZStd::string GetRootDirectoryPath(); static AZStd::string GetGameDirectoryPath(); static AZStd::string GetUserDirectoryPath(IEditor* editor); // Python QSharedPointer m_pythonWorker; void ProcessOutputMessage(RequestId requestId, const QVariant& value); void ProcessOutputError(RequestId requestId, const QVariant& value, bool log = true); void ProcessOutputErrorWithLogging(RequestId requestId, const QVariant& value); void ProcessProjectStackExists(RequestId requestId, const QVariant& value); void ProcessFrameworkNotEnabledError(RequestId requestId, const QVariant& value); void ProcessOutputSuccess(RequestId requestId, const QVariant& value); void ProcessOutputProjectDescription(RequestId requestId, const QVariant& value); void ProcessOutputMappingList(RequestId requestId, const QVariant& value); void ProcessOutputResourceGroupList(RequestId requestId, const QVariant& value); void ProcessOutputDeploymentList(RequestId requestId, const QVariant& value); void ProcessOutputProfileList(RequestId requestId, const QVariant& value); void ProcessOutputImportableResourceList(RequestId requestId, const QVariant& value); void ProcessOutputProjectStackDescription(RequestId requestId, const QVariant& value); void ProcessOutputDeploymentStackDescription(RequestId requestId, const QVariant& value); void ProcessOutputResourceGroupStackDescription(RequestId requestId, const QVariant& value); void ProcessOutputStackEventErrors(RequestId requestId, const QVariant& value); void ProcessOutputSupportedRegionList(RequestId requestId, const QVariant& value); void ProcessOutputCreateAdmin(RequestId requestId, const QVariant& value); void ProcessOutputDeploymentUpdated(RequestId requestId, const QVariant& value); QVariant m_lastProjectDescription; QVariant m_lastResourceGroupList; QVariant m_lastDeploymentList; QVariant m_lastProfileList; using PythonOutputHandlerMap = QMap; static PythonOutputHandlerMap s_PythonOutputHandlers; bool m_startupComplete; bool m_hasResourceGroups = false; using PythonCallbackMap = QMap; PythonCallbackMap m_pythonCallbacks; void SetProjectInitialized(bool isInitialized, bool isInitializing, const QString& defaultAWSProfile); InitializationState m_initializationState; // File Monitoring and Refresh QSharedPointer m_fileMonitor; // Logging QSharedPointer m_logger; // Models QSharedPointer m_importerModel; QSharedPointer m_profileModel; QSharedPointer m_deploymentModel; QSharedPointer m_projectModel; QSharedPointer m_projectStatusModel; QMap > m_deploymentStatusModels; QMap > m_resourceGroupStatusModels; QSharedPointer m_deploymentListStatusModel; QSharedPointer m_resourceGroupListStatusModel; QSharedPointer m_placeholderDeploymentStatusModel; QSharedPointer m_projectSettingsSourceControlModel; QSharedPointer m_deploymentTemplateSourceControlModel; QSharedPointer m_gemsFileSourceControlModel; QString m_defaultDeploymentName; int m_operationsInProgress {0}; struct RetryableRequest { const char* command; QVariantMap args; }; QMap m_retryableRequestMap; struct FailedRequest { QString errorMessage; }; QMap m_failedRequestMap; RequestId m_listDeploymentsRequestId; RequestId m_describeProjectRequestId; RequestId m_listResourceGroupsRequestId; RequestId m_listProfilesRequestId; RequestId m_listMappingsRequestId; RequestId m_updateMappingsRequestId; };