public async Task <string> BuildDockerImage(CloudApplication cloudApplication, Recommendation recommendation) { _interactiveService.LogMessageLine(string.Empty); _interactiveService.LogMessageLine("Building the docker image..."); var dockerExecutionDirectory = GetDockerExecutionDirectory(recommendation); var tagSuffix = DateTime.UtcNow.Ticks; var imageTag = $"{cloudApplication.StackName.ToLower()}:{tagSuffix}"; var dockerFile = GetDockerFilePath(recommendation); var buildArgs = GetDockerBuildArgs(recommendation); var dockerBuildCommand = $"docker build -t {imageTag} -f \"{dockerFile}\"{buildArgs} ."; _interactiveService.LogMessageLine($"Docker Execution Directory: {Path.GetFullPath(dockerExecutionDirectory)}"); _interactiveService.LogMessageLine($"Docker Build Command: {dockerBuildCommand}"); recommendation.DeploymentBundle.DockerExecutionDirectory = dockerExecutionDirectory; var result = await _commandLineWrapper.TryRunWithResult(dockerBuildCommand, dockerExecutionDirectory, redirectIO : false); if (result.ExitCode != 0) { throw new DockerBuildFailedException(result.StandardError ?? ""); } return(imageTag); }
/// <summary> /// Checks if the location of the saved CDK deployment project is monitored by a source control system. /// </summary> /// <param name="saveCdkDirectoryPath">Relative or absolute path of the directory at which the CDK deployment project will be saved.</param> /// <returns></returns> private async Task <bool> IsDirectoryUnderSourceControl(string saveCdkDirectoryPath) { var gitStatusResult = await _commandLineWrapper.TryRunWithResult("git status", saveCdkDirectoryPath); var svnStatusResult = await _commandLineWrapper.TryRunWithResult("svn status", saveCdkDirectoryPath); return(gitStatusResult.Success || svnStatusResult.Success); }
/// <summary> /// Helper method to find if the directory is monitored by a source control system. /// </summary> /// <param name="directoryPath">An absolute directory path.</param> /// <returns></returns> private async Task <bool> IsDirectoryUnderSourceControl(string?directoryPath) { if (!string.IsNullOrEmpty(directoryPath)) { var gitStatusResult = await _commandLineWrapper.TryRunWithResult(GIT_STATUS_COMMAND, directoryPath); var svnStatusResult = await _commandLineWrapper.TryRunWithResult(SVN_STATUS_COMMAND, directoryPath); return(gitStatusResult.Success || svnStatusResult.Success); } return(false); }
/// <summary> /// Use the native zip utility if it exist which will maintain linux/osx file permissions. /// </summary> private async Task BuildZipForLinux(string sourceDirectoryName, string destinationArchiveFileName) { var zipCLI = FindExecutableInPath("zip"); if (string.IsNullOrEmpty(zipCLI)) { throw new FailedToCreateZipFileException("Failed to find the \"zip\" utility program in path. This program is required to maintain Linux file permissions in the zip archive."); } var args = new StringBuilder($"\"{destinationArchiveFileName}\""); var allFiles = GetFilesToIncludeInArchive(sourceDirectoryName); foreach (var kvp in allFiles) { args.AppendFormat(" \"{0}\"", kvp.Key); } var command = $"{zipCLI} {args}"; var result = await _commandLineWrapper.TryRunWithResult(command, sourceDirectoryName); if (result.ExitCode != 0) { throw new FailedToCreateZipFileException("\"zip\" utility program has failed to create a zip archive."); } }
public async Task DeployCdkProject(OrchestratorSession session, string cdkProjectPath, Recommendation recommendation) { var recipeInfo = $"{recommendation.Recipe.Id}_{recommendation.Recipe.Version}"; var environmentVariables = new Dictionary <string, string> { { EnvironmentVariableKeys.AWS_EXECUTION_ENV, recipeInfo } }; _interactiveService.LogMessageLine("Starting deployment of CDK Project"); // Ensure region is bootstrapped await _commandLineWrapper.Run($"npx cdk bootstrap aws://{session.AWSAccountId}/{session.AWSRegion}", needAwsCredentials : true); var appSettingsFilePath = Path.Combine(cdkProjectPath, "appsettings.json"); // Handover to CDK command line tool // Use a CDK Context parameter to specify the settings file that has been serialized. var cdkDeploy = await _commandLineWrapper.TryRunWithResult($"npx cdk deploy --require-approval never -c {Constants.CloudFormationIdentifier.SETTINGS_PATH_CDK_CONTEXT_PARAMETER}=\"{appSettingsFilePath}\"", workingDirectory : cdkProjectPath, environmentVariables : environmentVariables, needAwsCredentials : true, streamOutputToInteractiveService : true); if (cdkDeploy.ExitCode != 0) { throw new FailedToDeployCDKAppException("We had an issue deploying your application to AWS. Check the deployment output for more details."); } }
/// <summary> /// From https://docs.aws.amazon.com/cdk/latest/guide/work-with.html#work-with-prerequisites, /// min version is 10.3 /// </summary> private async Task <bool> HasMinVersionNodeJs() { // run node --version to get the version var result = await _commandLineWrapper.TryRunWithResult("node --version"); var versionString = result.StandardOut; if (versionString.StartsWith("v", StringComparison.OrdinalIgnoreCase)) { versionString = versionString.Substring(1, versionString.Length - 1); } if (!result.Success || !Version.TryParse(versionString, out var version)) { return(false); } return(version.Major > 10 || version.Major == 10 && version.Minor >= 3); }
private async Task <TryGetResult <Version> > GetVersion(string workingDirectory, bool checkGlobal) { var command = new StringBuilder("npm list aws-cdk"); if (checkGlobal) { command.Append(" --global"); } TryRunResult result; try { result = await _commandLineWrapper.TryRunWithResult(command.ToString(), workingDirectory, false); } catch (Exception exception) { throw new NPMCommandFailedException($"Failed to execute {command}", exception); } /* * A typical Standard out looks like with version information in line 2 * * > npm list aws-cdk --global * C:\Users\user\AppData\Roaming\npm * `-- [email protected] */ var standardOut = result.StandardOut ?? ""; var lines = standardOut.Split('\n'); // Environment.NewLine doesn't work here. if (lines.Length < 2) { return(TryGetResult.Failure <Version>()); } var versionLine = lines[1]; /* * Split line 2 in parts so that we have package name and version in separate parts * * part 0: `-- * part 1: aws-cdk * part 2: 0.0.0 * * It could be possible we have more than 3 parts with more information but they can be ignored. */ var parts = versionLine.Split(' ', '@'); if (parts.Length < 3) { return(TryGetResult.Failure <Version>()); } /* * Make sure that we are checking aws-cdk only * If a customer has plugin which depends on aws-cdk and then customer removes aws-cdk * Plugin version information is shown which can lead to a false positive. * * > npm list aws-cdk --global * C:\Users\user\AppData\Roaming\npm * `-- [email protected] (git+https://github.com/aws-samples/cdk-assume-role-credential-plugin.git#5167c798a50bc9c96a9d660b28306428be4e99fb) */ if (!parts[1].Equals("aws-cdk")) { return(TryGetResult.Failure <Version>()); } if (Version.TryParse(parts[2], out var version)) { return(TryGetResult.FromResult(version)); } return(TryGetResult.Failure <Version>()); }