// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using AWS.Deploy.Common.Extensions;
using AWS.Deploy.Orchestration.Utilities;
namespace AWS.Deploy.Orchestration.CDK
{
///
/// Makes sure that a compatible version of CDK CLI is installed either in the global node_modules
/// or local node_modules.
///
public interface ICDKManager
{
///
/// Detects whether CDK CLI is installed or not in global node_modules.
/// If global node_modules don't contain, it checks in local node_modules
/// If local npm package isn't initialized, it initializes a npm package at .
/// If local node_modules don't contain, it installs CDK CLI version in local modules.
///
/// Directory used for local node app
/// Version of CDK CLI
Task EnsureCompatibleCDKExists(string workingDirectory, Version cdkVersion);
}
public class CDKManager : ICDKManager
{
private static readonly SemaphoreSlim s_cdkManagerSemaphoreSlim = new(1,1);
private readonly ICDKInstaller _cdkInstaller;
private readonly INPMPackageInitializer _npmPackageInitializer;
private readonly IOrchestratorInteractiveService _interactiveService;
public CDKManager(ICDKInstaller cdkInstaller, INPMPackageInitializer npmPackageInitializer, IOrchestratorInteractiveService interactiveService)
{
_cdkInstaller = cdkInstaller;
_npmPackageInitializer = npmPackageInitializer;
_interactiveService = interactiveService;
}
public async Task EnsureCompatibleCDKExists(string workingDirectory, Version cdkVersion)
{
await s_cdkManagerSemaphoreSlim.WaitAsync();
try
{
var installedCdkVersion = await _cdkInstaller.GetVersion(workingDirectory);
if (installedCdkVersion.Success && installedCdkVersion.Result?.CompareTo(cdkVersion) >= 0)
{
_interactiveService.LogDebugMessage($"CDK version {installedCdkVersion.Result} found in global node_modules.");
return;
}
var isNPMPackageInitialized = _npmPackageInitializer.IsInitialized(workingDirectory);
if (!isNPMPackageInitialized)
{
await _npmPackageInitializer.Initialize(workingDirectory, cdkVersion);
return; // There is no need to install CDK CLI explicitly, npm install takes care of first time bootstrap.
}
await _cdkInstaller.Install(workingDirectory, cdkVersion);
}
finally
{
s_cdkManagerSemaphoreSlim.Release();
}
}
}
}