Skip to content

Commit

Permalink
fix: Correctly set deployment ResourceType during re-deployments via …
Browse files Browse the repository at this point in the history
…server mode
  • Loading branch information
96malhar committed Feb 14, 2022
1 parent 0682ce3 commit cbd161a
Show file tree
Hide file tree
Showing 8 changed files with 610 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ public async Task<IActionResult> SetDeploymentTarget(string sessionId, [FromBody
state.ApplicationDetails.Name = existingDeployment.Name;
state.ApplicationDetails.UniqueIdentifier = existingDeployment.UniqueIdentifier;
state.ApplicationDetails.RecipeId = existingDeployment.RecipeId;
state.ApplicationDetails.ResourceType = existingDeployment.ResourceType;
await orchestrator.ApplyAllReplacementTokens(state.SelectedRecommendation, existingDeployment.Name);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using AWS.Deploy.CLI.IntegrationTests.Extensions;
using Xunit;

namespace AWS.Deploy.CLI.IntegrationTests.BeanstalkBackwardsCompatibilityTests
{
[Collection(nameof(TestContextFixture))]
public class CLITests
{
private readonly TestContextFixture _fixture;

public CLITests(TestContextFixture fixture)
{
_fixture = fixture;
}

[Fact]
public async Task DeployToExistingBeanstalkEnvironment()
{
var projectPath = _fixture.TestAppManager.GetProjectPath(Path.Combine("testapps", "WebAppNoDockerFile", "WebAppNoDockerFile.csproj"));
var deployArgs = new[] { "deploy", "--project-path", projectPath, "--application-name", _fixture.EnvironmentName, "--diagnostics", "--silent" };
Assert.Equal(CommandReturnCodes.SUCCESS, await _fixture.App.Run(deployArgs));

var environmentDescription = await _fixture.AWSResourceQueryer.DescribeElasticBeanstalkEnvironment(_fixture.EnvironmentName);

// URL could take few more minutes to come live, therefore, we want to wait and keep trying for a specified timeout
await _fixture.HttpHelper.WaitUntilSuccessStatusCode(environmentDescription.CNAME, TimeSpan.FromSeconds(5), TimeSpan.FromMinutes(5));

var successMessagePrefix = $"The Elastic Beanstalk Environment {_fixture.EnvironmentName} has been successfully updated";
var deployStdOutput = _fixture.InteractiveService.StdOutReader.ReadAllLines();
var successMessage = deployStdOutput.First(line => line.Trim().StartsWith(successMessagePrefix));
Assert.False(string.IsNullOrEmpty(successMessage));

var expectedVersionLabel = successMessage.Split(" ").Last();
Assert.True(await _fixture.EBHelper.VerifyEnvironmentVersionLabel(_fixture.EnvironmentName, expectedVersionLabel));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Amazon.Runtime;
using AWS.Deploy.CLI.Commands;
using AWS.Deploy.CLI.IntegrationTests.Helpers;
using AWS.Deploy.ServerMode.Client;
using Xunit;

namespace AWS.Deploy.CLI.IntegrationTests.BeanstalkBackwardsCompatibilityTests
{
[Collection(nameof(TestContextFixture))]
public class ServerModeTests
{
private readonly TestContextFixture _fixture;
private const string BEANSTALK_ENVIRONMENT_RECIPE_ID = "AspNetAppExistingBeanstalkEnvironment";

public ServerModeTests(TestContextFixture fixture)
{
_fixture = fixture;
}

[Fact]
public async Task DeployToExistingBeanstalkEnvironment()
{
var projectPath = _fixture.TestAppManager.GetProjectPath(Path.Combine("testapps", "WebAppNoDockerFile", "WebAppNoDockerFile.csproj"));
var portNumber = 4001;
using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ResolveCredentials);

var serverCommand = new ServerModeCommand(_fixture.ToolInteractiveService, portNumber, null, true);
var cancelSource = new CancellationTokenSource();

var serverTask = serverCommand.ExecuteAsync(cancelSource.Token);
try
{
var baseUrl = $"http://localhost:{portNumber}/";
var restClient = new RestAPIClient(baseUrl, httpClient);

await WaitTillServerModeReady(restClient);

var startSessionOutput = await restClient.StartDeploymentSessionAsync(new StartDeploymentSessionInput
{
AwsRegion = "us-west-2",
ProjectPath = projectPath
});

var sessionId = startSessionOutput.SessionId;
Assert.NotNull(sessionId);

var existingDeployments = await restClient.GetExistingDeploymentsAsync(sessionId);
var existingDeployment = existingDeployments.ExistingDeployments.First(x => string.Equals(_fixture.EnvironmentName, x.Name));

Assert.Equal(_fixture.EnvironmentName, existingDeployment.Name);
Assert.Equal(BEANSTALK_ENVIRONMENT_RECIPE_ID, existingDeployment.RecipeId);
Assert.Equal(_fixture.EnvironmentId, existingDeployment.ExistingDeploymentId);
Assert.Equal(DeploymentTypes.BeanstalkEnvironment, existingDeployment.DeploymentType);

var signalRClient = new DeploymentCommunicationClient(baseUrl);
await signalRClient.JoinSession(sessionId);

var logOutput = new StringBuilder();
signalRClient.ReceiveLogAllLogAction = (line) =>
{
logOutput.AppendLine(line);
};

await restClient.SetDeploymentTargetAsync(sessionId, new SetDeploymentTargetInput
{
ExistingDeploymentId = _fixture.EnvironmentId
});

await restClient.StartDeploymentAsync(sessionId);

await WaitForDeployment(restClient, sessionId);

Assert.True(logOutput.Length > 0);
var successMessagePrefix = $"The Elastic Beanstalk Environment {_fixture.EnvironmentName} has been successfully updated";
var deployStdOutput = logOutput.ToString().Split(Environment.NewLine);
var successMessage = deployStdOutput.First(line => line.Trim().StartsWith(successMessagePrefix));
Assert.False(string.IsNullOrEmpty(successMessage));

var expectedVersionLabel = successMessage.Split(" ").Last();
Assert.True(await _fixture.EBHelper.VerifyEnvironmentVersionLabel(_fixture.EnvironmentName, expectedVersionLabel));
}
finally
{
cancelSource.Cancel();
}
}

private async Task<DeploymentStatus> WaitForDeployment(RestAPIClient restApiClient, string sessionId)
{
// Do an initial delay to avoid a race condition of the status being checked before the deployment has kicked off.
await Task.Delay(TimeSpan.FromSeconds(3));

await WaitUntilHelper.WaitUntil(async () =>
{
DeploymentStatus status = (await restApiClient.GetDeploymentStatusAsync(sessionId)).Status; ;
return status != DeploymentStatus.Executing;
}, TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(15));

return (await restApiClient.GetDeploymentStatusAsync(sessionId)).Status;
}

private async Task WaitTillServerModeReady(RestAPIClient restApiClient)
{
await WaitUntilHelper.WaitUntil(async () =>
{
SystemStatus status = SystemStatus.Error;
try
{
status = (await restApiClient.HealthAsync()).Status;
}
catch (Exception)
{
}

return status == SystemStatus.Ready;
}, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(10));
}

private Task<AWSCredentials> ResolveCredentials()
{
var testCredentials = FallbackCredentialsFactory.GetCredentials();
return Task.FromResult<AWSCredentials>(testCredentials);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Amazon.ElasticBeanstalk;
using Amazon.IdentityManagement;
using AWS.Deploy.CLI.Common.UnitTests.IO;
using AWS.Deploy.CLI.Extensions;
using AWS.Deploy.CLI.IntegrationTests.Extensions;
using AWS.Deploy.CLI.IntegrationTests.Helpers;
using AWS.Deploy.CLI.IntegrationTests.Services;
using AWS.Deploy.Common.IO;
using AWS.Deploy.Orchestration.Data;
using AWS.Deploy.Orchestration.Utilities;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

namespace AWS.Deploy.CLI.IntegrationTests.BeanstalkBackwardsCompatibilityTests
{
public class TestContextFixture : IAsyncLifetime
{
public readonly App App;
public readonly HttpHelper HttpHelper;
public readonly IAWSResourceQueryer AWSResourceQueryer;
public readonly TestAppManager TestAppManager;
public readonly IDirectoryManager DirectoryManager;
public readonly ICommandLineWrapper CommandLineWrapper;
public readonly IZipFileManager ZipFileManager;
public readonly IToolInteractiveService ToolInteractiveService;
public readonly InMemoryInteractiveService InteractiveService;
public readonly ElasticBeanstalkHelper EBHelper;
public readonly IAMHelper IAMHelper;

public readonly string ApplicationName;
public readonly string EnvironmentName;
public readonly string VersionLabel;
public string EnvironmentId;

public TestContextFixture()
{
var serviceCollection = new ServiceCollection();

serviceCollection.AddCustomServices();
serviceCollection.AddTestServices();

var serviceProvider = serviceCollection.BuildServiceProvider();

App = serviceProvider.GetService<App>();
Assert.NotNull(App);

InteractiveService = serviceProvider.GetService<InMemoryInteractiveService>();
Assert.NotNull(InteractiveService);

ToolInteractiveService = serviceProvider.GetService<IToolInteractiveService>();

AWSResourceQueryer = serviceProvider.GetService<IAWSResourceQueryer>();
Assert.NotNull(AWSResourceQueryer);

CommandLineWrapper = serviceProvider.GetService<ICommandLineWrapper>();
Assert.NotNull(CommandLineWrapper);

ZipFileManager = serviceProvider.GetService<IZipFileManager>();
Assert.NotNull(ZipFileManager);

DirectoryManager = serviceProvider.GetService<IDirectoryManager>();
Assert.NotNull(DirectoryManager);

HttpHelper = new HttpHelper(InteractiveService);
TestAppManager = new TestAppManager();

var suffix = Guid.NewGuid().ToString().Split('-').Last();
ApplicationName = $"application{suffix}";
EnvironmentName = $"environment{suffix}";
VersionLabel = $"v-{suffix}";

EBHelper = new ElasticBeanstalkHelper(new AmazonElasticBeanstalkClient(), AWSResourceQueryer, ToolInteractiveService);
IAMHelper = new IAMHelper(new AmazonIdentityManagementServiceClient(), AWSResourceQueryer, ToolInteractiveService);
}

public async Task InitializeAsync()
{
await IAMHelper.CreateRoleForBeanstalkEnvionmentDeployment("aws-elasticbeanstalk-ec2-role");

var projectPath = TestAppManager.GetProjectPath(Path.Combine("testapps", "WebAppNoDockerFile", "WebAppNoDockerFile.csproj"));
var publishDirectoryInfo = DirectoryManager.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
var zipFilePath = $"{publishDirectoryInfo.FullName}.zip";

var publishCommand =
$"dotnet publish \"{projectPath}\"" +
$" -o \"{publishDirectoryInfo}\"" +
$" -c release";

var result = await CommandLineWrapper.TryRunWithResult(publishCommand, streamOutputToInteractiveService: true);
Assert.Equal(0, result.ExitCode);

await ZipFileManager.CreateFromDirectory(publishDirectoryInfo.FullName, zipFilePath);

await EBHelper.CreateApplicationAsync(ApplicationName);
await EBHelper.CreateApplicationVersionAsync(ApplicationName, VersionLabel, zipFilePath);
var success = await EBHelper.CreateEnvironmentAsync(ApplicationName, EnvironmentName, VersionLabel);
Assert.True(success);

var environmentDescription = await AWSResourceQueryer.DescribeElasticBeanstalkEnvironment(EnvironmentName);
EnvironmentId = environmentDescription.EnvironmentId;

// URL could take few more minutes to come live, therefore, we want to wait and keep trying for a specified timeout
await HttpHelper.WaitUntilSuccessStatusCode(environmentDescription.CNAME, TimeSpan.FromSeconds(5), TimeSpan.FromMinutes(5));
}

public async Task DisposeAsync()
{
var success = await EBHelper.DeleteApplication(ApplicationName, EnvironmentName);
Assert.True(success);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using Xunit;

namespace AWS.Deploy.CLI.IntegrationTests.BeanstalkBackwardsCompatibilityTests
{
[CollectionDefinition(nameof(TestContextFixture), DisableParallelization = true)]
public class TestContextFixtureCollection : ICollectionFixture<TestContextFixture>
{
}
}
Loading

0 comments on commit cbd161a

Please sign in to comment.