Skip to content

Commit

Permalink
Bug 5329 (#397)
Browse files Browse the repository at this point in the history
* Fixing tests

* Fixing tests

* Fixing tests still

* Fixed more tests
  • Loading branch information
mcasperson committed Feb 27, 2019
1 parent 7c99e45 commit 0d43bd7
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 12 deletions.
18 changes: 16 additions & 2 deletions source/Octo.Tests/Commands/ApiCommandFixtureBase.cs
Expand Up @@ -13,7 +13,8 @@
namespace Octo.Tests.Commands
{
public abstract class ApiCommandFixtureBase
{
{
protected const string ValidEnvironment = "Test Environment";
private static string _previousCurrentDirectory;

[OneTimeSetUp]
Expand Down Expand Up @@ -53,7 +54,20 @@ public void BaseSetup()
Repository.HasLink("Spaces").Returns(true);
Repository.HasLink(Arg.Is<string>(arg => arg != "Spaces")).Returns(async call => (await Repository.LoadRootDocument()).HasLink(call.Arg<string>()));
Repository.Link(Arg.Any<string>()).Returns(async call => (await Repository.LoadRootDocument()).Link(call.Arg<string>()));


Repository.Machines.FindByNames(Arg.Any<IEnumerable<string>>(), Arg.Any<string>(), Arg.Any<object>())
.Returns(new List<MachineResource>());
Repository.Environments.FindByNames(
Arg.Is<List<string>>(arg => arg.TrueForAll(arg2 => arg2 == ValidEnvironment)),
Arg.Any<string>(),
Arg.Any<object>())
.Returns(new List<EnvironmentResource>() {new EnvironmentResource() {Name = ValidEnvironment}});
Repository.Environments.FindByNames(
Arg.Is<List<string>>(arg => arg.TrueForAll(arg2 => arg2 != ValidEnvironment)),
Arg.Any<string>(),
Arg.Any<object>())
.Returns(new List<EnvironmentResource>());

ClientFactory = Substitute.For<IOctopusClientFactory>();

RepositoryFactory = Substitute.For<IOctopusAsyncRepositoryFactory>();
Expand Down
73 changes: 71 additions & 2 deletions source/Octo.Tests/Commands/CreateReleaseCommandFixture.cs
@@ -1,4 +1,4 @@
using NSubstitute;
using NSubstitute;
using NUnit.Framework;
using Octopus.Cli.Commands.Releases;
using Octopus.Cli.Infrastructure;
Expand All @@ -17,7 +17,7 @@ public class CreateReleaseCommandFixture : ApiCommandFixtureBase
public void SetUp()
{
versionResolver = Substitute.For<IPackageVersionResolver>();
releasePlanBuilder = Substitute.For<IReleasePlanBuilder>();
releasePlanBuilder = Substitute.For<IReleasePlanBuilder>();
}

[Test]
Expand All @@ -33,5 +33,74 @@ public void ShouldLoadOptionsFromFile()
Assert.AreEqual("1.0.0", createReleaseCommand.VersionNumber);
Assert.AreEqual("Test config file.", createReleaseCommand.ReleaseNotes);
}

[Test]
public void ShouldThrowForBadTag()
{
createReleaseCommand = new CreateReleaseCommand(RepositoryFactory, new OctopusPhysicalFileSystem(Log), versionResolver, releasePlanBuilder, ClientFactory, CommandOutputProvider);

CommandLineArgs.Add("--server=https://test-server-url/api/");
CommandLineArgs.Add("--apikey=API-test");
CommandLineArgs.Add("--project=Test Project");
CommandLineArgs.Add("--releaseNumber=1.0.0");
CommandLineArgs.Add("--tenantTag=bad");
CommandLineArgs.Add($"--deployto={ValidEnvironment}");
Assert.ThrowsAsync<CommandException>(async delegate
{
await createReleaseCommand.Execute(CommandLineArgs.ToArray());
});
}

[Test]
public void ShouldThrowForBadTenant()
{
createReleaseCommand = new CreateReleaseCommand(RepositoryFactory, new OctopusPhysicalFileSystem(Log), versionResolver, releasePlanBuilder, ClientFactory, CommandOutputProvider);

CommandLineArgs.Add("--server=https://test-server-url/api/");
CommandLineArgs.Add("--apikey=API-test");
CommandLineArgs.Add("--project=Test Project");
CommandLineArgs.Add("--releaseNumber=1.0.0");
CommandLineArgs.Add("--tenant=bad");
CommandLineArgs.Add($"--deployto={ValidEnvironment}");
Assert.ThrowsAsync<CommandException>(async delegate
{
await createReleaseCommand.Execute(CommandLineArgs.ToArray());
});
}

[Test]
public void ShouldThrowForBadMachine()
{
createReleaseCommand = new CreateReleaseCommand(RepositoryFactory, new OctopusPhysicalFileSystem(Log), versionResolver, releasePlanBuilder, ClientFactory, CommandOutputProvider);

CommandLineArgs.Add("--server=https://test-server-url/api/");
CommandLineArgs.Add("--apikey=API-test");
CommandLineArgs.Add("--project=Test Project");
CommandLineArgs.Add("--releaseNumber=1.0.0");
CommandLineArgs.Add("--specificmachines=bad");
CommandLineArgs.Add($"--deployto={ValidEnvironment}");
Assert.ThrowsAsync<CommandException>(async delegate
{
await createReleaseCommand.Execute(CommandLineArgs.ToArray());
});
}


[Test]
public void ShouldThrowForBadEnvironment()
{
createReleaseCommand = new CreateReleaseCommand(RepositoryFactory, new OctopusPhysicalFileSystem(Log), versionResolver, releasePlanBuilder, ClientFactory, CommandOutputProvider);

CommandLineArgs.Add("--server=https://test-server-url/api/");
CommandLineArgs.Add("--apikey=API-test");
CommandLineArgs.Add("--project=Test Project");
CommandLineArgs.Add("--releaseNumber=1.0.0");
CommandLineArgs.Add("--deployto=bad");
Assert.ThrowsAsync<CommandException>(async delegate
{
await createReleaseCommand.Execute(CommandLineArgs.ToArray());
});
}

}
}
14 changes: 10 additions & 4 deletions source/Octo.Tests/Commands/DeployReleaseCommandTestFixture.cs
Expand Up @@ -27,7 +27,7 @@ public void SetUp()
var project = new ProjectResource();
var release = new ReleaseResource { Version = "1.0.0" };
var releases = new ResourceCollection<ReleaseResource>(new[] { release }, new LinkCollection());
var deploymentPromotionTarget = new DeploymentPromotionTarget { Name = "TestEnvironment", Id = "Env-1" };
var deploymentPromotionTarget = new DeploymentPromotionTarget { Name = ValidEnvironment, Id = "Env-1" };
var promotionTargets = new List<DeploymentPromotionTarget> { deploymentPromotionTarget };
var tenantPromotionTarget1 = new DeploymentPromomotionTenant() { Id = "Tenant-1", PromoteTo = promotionTargets };
var tenantPromotionTarget2 = new DeploymentPromomotionTenant() { Id = "Tenant-2", PromoteTo = new List<DeploymentPromotionTarget>() };
Expand All @@ -42,6 +42,12 @@ public void SetUp()
Repository.Releases.GetTemplate(release).Returns(deploymentTemplate);
Repository.Deployments.Create(Arg.Any<DeploymentResource>()).Returns(deployment);
Repository.Tasks.Get(deployment.TaskId).Returns(taskResource);
Repository.Tenants.Get(Arg.Is<string[]>(arg => arg.All(arg2 => arg2 == "Tenant-1" || arg2 == "Tenant-2")))
.Returns(new List<TenantResource>()
{
new TenantResource() {Id = "Tenant-1"},
new TenantResource() {Id = "Tenant-2"},
});
}

[Test]
Expand All @@ -53,7 +59,7 @@ public void ShouldCancelDeploymentOnTimeoutIfRequested()

CommandLineArgs.Add("--project=" + ProjectName);
CommandLineArgs.Add("--deploymenttimeout=00:00:01");
CommandLineArgs.Add("--deployto=TestEnvironment");
CommandLineArgs.Add($"--deployto={ValidEnvironment}");
CommandLineArgs.Add("--version=latest");
CommandLineArgs.Add("--progress");
CommandLineArgs.Add("--cancelontimeout");
Expand All @@ -73,7 +79,7 @@ public void ShouldNotCancelDeploymentOnTimeoutIfNotRequested()

CommandLineArgs.Add("--project=" + ProjectName);
CommandLineArgs.Add("--deploymenttimeout=00:00:01");
CommandLineArgs.Add("--deployto=TestEnvironment");
CommandLineArgs.Add($"--deployto={ValidEnvironment}");
CommandLineArgs.Add("--version=latest");
CommandLineArgs.Add("--progress");

Expand Down Expand Up @@ -116,7 +122,7 @@ public void ShouldTryLoadTenant()

CommandLineArgs.Add("--project=" + ProjectName);
CommandLineArgs.Add("--deploymenttimeout=00:00:01");
CommandLineArgs.Add("--deployto=TestEnvironment");
CommandLineArgs.Add($"--deployto={ValidEnvironment}");
CommandLineArgs.Add("--tenant=*");
CommandLineArgs.Add("--version=latest");
CommandLineArgs.Add("--progress");
Expand Down
72 changes: 69 additions & 3 deletions source/Octopus.Cli/Commands/Deployment/DeploymentCommandBase.cs
Expand Up @@ -11,12 +11,12 @@
using Octopus.Client.Model;
using Octopus.Client.Model.Forms;
using Octostache;
using Serilog;

namespace Octopus.Cli.Commands.Deployment
{
public abstract class DeploymentCommandBase : ApiCommand
{
private const char Separator = '/';
readonly VariableDictionary variables = new VariableDictionary();
protected IReadOnlyList<DeploymentResource> deployments;
protected List<DeploymentPromotionTarget> promotionTargets;
Expand Down Expand Up @@ -81,11 +81,77 @@ protected override async Task ValidateParameters()
if (string.IsNullOrWhiteSpace(ProjectName)) throw new CommandException("Please specify a project name using the parameter: --project=XYZ");
if (IsTenantedDeployment && DeployToEnvironmentNames.Count > 1) throw new CommandException("Please specify only one environment at a time when deploying to tenants.");
if (Tenants.Contains("*") && (Tenants.Count > 1 || TenantTags.Count > 0)) throw new CommandException("When deploying to all tenants using --tenant=* wildcard no other tenant filters can be provided");

if (IsTenantedDeployment && !await Repository.SupportsTenants().ConfigureAwait(false))
throw new CommandException("Your Octopus Server does not support tenants, which was introduced in Octopus 3.4. Please upgrade your Octopus Server, enable the multi-tenancy feature or remove the --tenant and --tenanttag arguments.");
/*
* A create release operation can also optionally deploy the release, however any invalid options that
* are specific only to the deployment will fail after the release has been created. This can leave
* a deployment in a half finished state, so this validation ensures that the input relating to the
* deployment is valid so missing or incorrect input doesn't stop stop the deployment after a release is
* created.
*
* Note that certain validations still need to be done on the server. Permissions and lifecycle progression
* still rely on server side validation.
*/

// We might query the same tagset repeatedly, so store old queries here
var tagSetResources = new Dictionary<string, TagSetResource>();
// Make sure the tags are valid
foreach (var tenantTag in TenantTags)
{
// Verify the format of the tag
var parts = tenantTag.Split(Separator);
if (parts.Length != 2 || string.IsNullOrEmpty(parts[0]) || string.IsNullOrEmpty(parts[1]))
{
throw new CommandException(
$"Canonical Tag Name expected in the format of `TagSetName{Separator}TagName`");
}

// Query the api if the results were not previously found
if (!tagSetResources.ContainsKey(parts[0]))
{
tagSetResources.Add(parts[0], await Repository.TagSets.FindByName(parts[0]).ConfigureAwait(false));
}

// Verify the presence of the tag
if (tagSetResources[parts[0]]?.Tags?.All(tag => parts[1] != tag.Name) ?? true)
{
throw new CommandException(
$"Unable to find matching tag from canonical tag name `{tenantTag}`");
}
}

// Make sure the tenants are valid
foreach (var tenantName in Tenants)
{
if (tenantName != "*")
{
var tenant = await Repository.Tenants.FindByName(tenantName).ConfigureAwait(false);
if (tenant == null)
{
throw new CommandException(
$"Could not find the tenant {tenantName} on the Octopus Server");
}
}
}

// Make sure environment is valid
var environments = await Repository.Environments.FindByNames(DeployToEnvironmentNames).ConfigureAwait(false);
var missingEnvironment = DeployToEnvironmentNames
.Where(env => environments.All(env2 => env2.Name != env))
.ToList();
if (missingEnvironment.Count != 0)
{
throw new CommandException(
$"The environment{(missingEnvironment.Count == 1 ? "" : "s")} {string.Join(", ", missingEnvironment)} " +
$"do{(missingEnvironment.Count == 1 ? "es" : "")} not exist or {(missingEnvironment.Count == 1 ? "is" : "are")} misspelled");
}


// Make sure the machines are valid
await GetSpecificMachines();

base.ValidateParameters();
await base.ValidateParameters();
}

DateTimeOffset? ParseDeployAt(string v)
Expand Down
Expand Up @@ -62,7 +62,7 @@ protected override async Task ValidateParameters()
if (!string.IsNullOrWhiteSpace(ChannelName) && !await Repository.SupportsChannels().ConfigureAwait(false))
throw new CommandException("Your Octopus Server does not support channels, which was introduced in Octopus 3.2. Please upgrade your Octopus Server, or remove the --channel argument.");

base.ValidateParameters();
await base.ValidateParameters();
}

public async Task Request()
Expand Down

0 comments on commit 0d43bd7

Please sign in to comment.