public async Task SaveChanges_SmallTemplate_SubmitsDirectly() { // arrange var alarm = Alarm(); var group = Group(); var stackName = ExpectedStackName(group); SetupListStacksToReturnStackNames(); SetupStackStatusSequence(stackName, new List <string> { "CREATE_COMPLETE" }); var s3Location = new S3Location("bucket", "s3/path"); var deployer = MakeDeployer(s3Location, TimeSpan.Zero, TimeSpan.FromMinutes(1)); var sut = new CloudFormationAlarmCreator(deployer, new ConsoleAlarmLogger(false)); // act sut.AddAlarms(group, new[] { alarm }); await sut.SaveChanges(false); // assert _s3Mock .Verify(x => x.PutObjectAsync( It.IsAny <PutObjectRequest>(), It.IsAny <CancellationToken>()), Times.Never); _cloudFormationMock .Verify(x => x.CreateStackAsync( It.Is <CreateStackRequest>(s => s.StackName == stackName && s.TemplateURL == null && !string.IsNullOrWhiteSpace(s.TemplateBody)), It.IsAny <CancellationToken>()), Times.Exactly(1)); }
public async Task SaveChanges_StackDoesNotExist_StackIsCreated() { // arrange var alarm = Alarm(); var group = Group(); var stackName = ExpectedStackName(group); SetupListStacksToReturnStackNames(); SetStatusForStackName(stackName, "CREATE_COMPLETE"); var deployer = MakeDeployer(null, TimeSpan.FromMilliseconds(5), TimeSpan.FromMilliseconds(5)); var sut = new CloudFormationAlarmCreator(deployer, new ConsoleAlarmLogger(false)); sut.AddAlarms(group, new[] { alarm }); // act await sut.SaveChanges(false); // assert _cloudFormationMock .Verify(x => x.CreateStackAsync( It.Is <CreateStackRequest>(s => s.StackName == stackName), It.IsAny <CancellationToken>())); }
public async Task SaveChanges_DryRun_NoStackChangesMade() { // arrange var alarm = Alarm(); SetupListStacksToReturnStackNames(); var sut = new CloudFormationAlarmCreator( new CloudformationStackDeployer( new ConsoleAlarmLogger(false), _cloudFormationMock.Object, _s3Mock.Object, null)); sut.AddAlarm(alarm); // act await sut.SaveChanges(true); // assert _cloudFormationMock .Verify(x => x.CreateStackAsync( It.IsAny <CreateStackRequest>(), It.IsAny <CancellationToken>()), Times.Never()); }
public async Task SaveChanges_NoAlarms_NoStackChangesMade() { // arrange var sut = new CloudFormationAlarmCreator( new CloudformationStackDeployer( new ConsoleAlarmLogger(false), _cloudFormationMock.Object, _s3Mock.Object, null )); // act await sut.SaveChanges(false); // assert _cloudFormationMock .Verify(x => x.CreateStackAsync( It.IsAny <CreateStackRequest>(), It.IsAny <CancellationToken>()), Times.Never); _cloudFormationMock .Verify(x => x.UpdateStackAsync( It.IsAny <UpdateStackRequest>(), It.IsAny <CancellationToken>()), Times.Never); }
public async Task SaveChanges_StackExists_StackIsUpdated() { // arrange var alarm = Alarm(); var stackName = ExpectedStackName(alarm.AlertingGroup); SetupListStacksToReturnStackNames(stackName); SetStatusForStackName(stackName, "UPDATE_COMPLETE"); var sut = new CloudFormationAlarmCreator( new CloudformationStackDeployer( new ConsoleAlarmLogger(false), _cloudFormationMock.Object, _s3Mock.Object, null, TimeSpan.FromMilliseconds(5), TimeSpan.FromMilliseconds(5)) ); sut.AddAlarm(alarm); // act await sut.SaveChanges(false); // assert _cloudFormationMock .Verify(x => x.UpdateStackAsync( It.Is <UpdateStackRequest>(s => s.StackName == stackName), It.IsAny <CancellationToken>())); }
public async Task IgnoresNamedEntitiesThatDoNotExist() { // arrange var stack = new Mock <ICloudformationStackDeployer>(); var dynamoClient = CreateDynamoClientForTables(new[] { new TableDescription() { TableName = "first-dynamo-table", ProvisionedThroughput = new ProvisionedThroughputDescription() { ReadCapacityUnits = 10, WriteCapacityUnits = 10 } } }); var source = new TableDescriptionSource(dynamoClient); var creator = new CloudFormationAlarmCreator(stack.Object, new ConsoleAlarmLogger(true)); var config = ConfigHelper.CreateBasicConfiguration("test", "group-suffix", "DynamoDb", new List <ResourceThresholds>() { new ResourceThresholds() { Name = "non-existant-table" } }); var sut = IoCHelper.CreateSystemUnderTest( source, new DynamoDbDataProvider(), new DynamoDbDataProvider(), WatchmanServiceConfigurationMapper.MapDynamoDb, creator, ConfigHelper.ConfigLoaderFor(config) ); // act await sut.LoadAndGenerateAlarms(RunMode.GenerateAlarms); // assert stack .Verify(x => x.DeployStack( It.IsAny <string>(), It.IsAny <string>(), It.IsAny <bool>() ), Times.Never); }
public async Task SaveChanges_LargeTemplate_SubmitsViaS3() { // arrange var alarms = Enumerable.Range(0, 120) .Select(x => Alarm($"alarm-{x}")) .ToList(); var stackName = ExpectedStackName(alarms.First().AlertingGroup); SetupListStacksToReturnStackNames(); SetupStackStatusSequence(stackName, new List <string> { "CREATE_COMPLETE" }); var s3Location = new S3Location("bucket", "s3/path"); var sut = new CloudFormationAlarmCreator( new CloudformationStackDeployer( new ConsoleAlarmLogger(false), _cloudFormationMock.Object, _s3Mock.Object, s3Location, TimeSpan.Zero, TimeSpan.FromMinutes(1) )); foreach (var alarm in alarms) { sut.AddAlarm(alarm); } // act await sut.SaveChanges(false); // assert var s3Path = $"{s3Location.Path}/{stackName}.json"; _s3Mock .Verify(x => x.PutObjectAsync( It.Is <PutObjectRequest>(r => r.BucketName == s3Location.BucketName && r.Key == s3Path), It.IsAny <CancellationToken>())); var expectedStackUrl = $"https://s3.amazonaws.com/{s3Location.BucketName}/{s3Path}"; _cloudFormationMock .Verify(x => x.CreateStackAsync( It.Is <CreateStackRequest>(s => s.StackName == stackName && s.TemplateURL == expectedStackUrl && s.TemplateBody == null), It.IsAny <CancellationToken>()), Times.Exactly(1)); }
public async Task SaveChanges_ChangesToStackSubmitted_WaitsForTargetStatus() { // arrange var alarm = Alarm(); var stackName = ExpectedStackName(alarm.AlertingGroup); SetupListStacksToReturnStackNames(); SetupStackStatusSequence(stackName, new List <string> { "CREATE_IN_PROGRESS", "CREATE_IN_PROGRESS", "CREATE_COMPLETE" }); var statusCheckDelay = TimeSpan.FromMilliseconds(200); var sut = new CloudFormationAlarmCreator( new CloudformationStackDeployer( new ConsoleAlarmLogger(false), _cloudFormationMock.Object, _s3Mock.Object, null, statusCheckDelay, TimeSpan.FromMinutes(5))); sut.AddAlarm(alarm); var start = DateTime.UtcNow; // act await sut.SaveChanges(false); // assert var actualWaitMillis = (DateTime.UtcNow - start).TotalMilliseconds; var expectedDelayMillis = statusCheckDelay.TotalMilliseconds * 3; Assert.That(actualWaitMillis, Is.GreaterThanOrEqualTo(expectedDelayMillis)); // this is pretty rough because other parts of the method takes a while, just want to check the time isn't stupidly long var maxDelayMillis = expectedDelayMillis * 4; Assert.That(actualWaitMillis, Is.LessThanOrEqualTo(maxDelayMillis)); _cloudFormationMock .Verify(x => x.DescribeStacksAsync( It.Is <DescribeStacksRequest>(s => s.StackName == stackName), It.IsAny <CancellationToken>()), Times.Exactly(3)); }
public void SaveChanges_CloudformationFails_Throws() { // arrange var alarm = Alarm(); SetupListStacksToReturnStackNames(); SetupCreateStackAsyncToFail(); var deployer = MakeDeployer(); var sut = new CloudFormationAlarmCreator(deployer, new ConsoleAlarmLogger(false)); sut.AddAlarms(Group(), new[] { alarm }); // act var ex = Assert.ThrowsAsync <WatchmanException>(() => sut.SaveChanges(false)); Assert.That(ex.Message, Is.EqualTo("1 stacks failed to deploy")); }
public async Task SaveChanges_ConfigResultsInMultipleStacks_Aborts() { //arrange var alarm1 = Alarm("alarm 1"); var alarm2 = Alarm("alarm 2"); // two groups with the same name but different suffix, so that the equality/hash compares will fail // but would result in two cloudformation stacks with the same name var group1 = Group("name", "suffix1"); var group2 = Group("name", "suffix2"); SetupListStacksToReturnStackNames(); SetupStackStatusSequence(ExpectedStackName(group1), new List <string> { "CREATE_COMPLETE", "CREATE_COMPLETE" }); var s3Location = new S3Location("bucket", "s3/path"); var deployer = MakeDeployer(s3Location, TimeSpan.Zero, TimeSpan.FromMinutes(1)); var sut = new CloudFormationAlarmCreator(deployer, new ConsoleAlarmLogger(false)); //act Exception caught = null; try { sut.AddAlarms(group1, new[] { alarm1 }); sut.AddAlarms(group2, new[] { alarm2 }); await sut.SaveChanges(false);; } catch (Exception ex) { caught = ex; } //assert Assert.That(caught, Is.Not.Null); Assert.That(caught.Message, Contains.Substring("Cannot deploy: multiple stacks would be created with the same name")); }
public async Task UsesDelayedScalingThresholdFromCloudWatch() { // arrange var stack = new FakeStackDeployer(); var autoScalingClient = FakeAwsClients.CreateAutoScalingClientForGroups(new[] { new AutoScalingGroup() { AutoScalingGroupName = "group-delay-20" }, new AutoScalingGroup() { AutoScalingGroupName = "group-delay-100" } }); var source = new AutoScalingGroupSource(autoScalingClient); var creator = new CloudFormationAlarmCreator(stack, new ConsoleAlarmLogger(true)); var config = ConfigHelper.CreateBasicConfiguration("test", "group-suffix", new AlertingGroupServices() { AutoScaling = new AwsServiceAlarms <AutoScalingResourceConfig>() { Resources = new List <ResourceThresholds <AutoScalingResourceConfig> >() { new ResourceThresholds <AutoScalingResourceConfig>() { Name = "group-delay-20", Options = new AutoScalingResourceConfig() { InstanceCountIncreaseDelayMinutes = 20 } }, new ResourceThresholds <AutoScalingResourceConfig>() { Name = "group-delay-100" } }, Options = new AutoScalingResourceConfig() { InstanceCountIncreaseDelayMinutes = 100 } } }); var now = DateTime.Parse("2018-01-26"); var fakeTime = new Mock <ICurrentTimeProvider>(); fakeTime.Setup(f => f.UtcNow).Returns(now); var cloudWatch = new Mock <IAmazonCloudWatch>(); SetupCloudWatchDesiredMetric(cloudWatch, 100 * 60, now, "group-delay-100", 90); SetupCloudWatchDesiredMetric(cloudWatch, 20 * 60, now, "group-delay-20", 80); var provider = new AutoScalingGroupAlarmDataProvider(cloudWatch.Object, fakeTime.Object); var sut = IoCHelper.CreateSystemUnderTest( source, provider, provider, WatchmanServiceConfigurationMapper.MapAutoScaling, creator, ConfigHelper.ConfigLoaderFor(config) ); // act await sut.LoadAndGenerateAlarms(RunMode.GenerateAlarms); // assert var alarms = stack .Stack("Watchman-test") .AlarmsByDimension("AutoScalingGroupName"); var alarm100 = alarms["group-delay-100"].Single(a => a.Properties["AlarmName"].ToString().Contains("InService")); var alarm20 = alarms["group-delay-20"].Single(a => a.Properties["AlarmName"].ToString().Contains("InService")); var defaultAlarmThreshold = 0.5m; Assert.That((decimal)alarm100.Properties["Threshold"], Is.EqualTo(90 * defaultAlarmThreshold)); Assert.That((decimal)alarm20.Properties["Threshold"], Is.EqualTo(80 * defaultAlarmThreshold)); }
public async Task TimesSuppliedToCloudWatchAreUtc() { // arrange var stack = new FakeStackDeployer(); var autoScalingClient = FakeAwsClients.CreateAutoScalingClientForGroups(new[] { new AutoScalingGroup() { AutoScalingGroupName = "group-1", DesiredCapacity = 40 } }); var source = new AutoScalingGroupSource(autoScalingClient); var creator = new CloudFormationAlarmCreator(stack, new ConsoleAlarmLogger(true)); var config = ConfigHelper.CreateBasicConfiguration("test", "group-suffix", new AlertingGroupServices() { AutoScaling = new AwsServiceAlarms <AutoScalingResourceConfig>() { Resources = new List <ResourceThresholds <AutoScalingResourceConfig> >() { new ResourceThresholds <AutoScalingResourceConfig>() { Name = "group-1", Options = new AutoScalingResourceConfig() { InstanceCountIncreaseDelayMinutes = 5 } } } } }); var cloudWatch = new Mock <IAmazonCloudWatch>(); cloudWatch .Setup(c => c.GetMetricStatisticsAsync(It.IsAny <GetMetricStatisticsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new GetMetricStatisticsResponse() { Datapoints = new List <Datapoint>() { new Datapoint() { Minimum = 5 } } }); var provider = new AutoScalingGroupAlarmDataProvider(cloudWatch.Object, new CurrentTimeProvider()); var sut = IoCHelper.CreateSystemUnderTest( source, provider, provider, WatchmanServiceConfigurationMapper.MapAutoScaling, creator, ConfigHelper.ConfigLoaderFor(config) ); // act await sut.LoadAndGenerateAlarms(RunMode.GenerateAlarms); // assert cloudWatch.Verify(x => x.GetMetricStatisticsAsync( It.Is <GetMetricStatisticsRequest>( r => r.StartTime.Kind == DateTimeKind.Utc && r.EndTime.Kind == DateTimeKind.Utc ), It.IsAny <CancellationToken>()) ); }
public async Task UsesDesiredInstancesForThresholdByDefault() { // arrange var stack = new FakeStackDeployer(); var autoScalingClient = FakeAwsClients.CreateAutoScalingClientForGroups(new[] { new AutoScalingGroup() { AutoScalingGroupName = "group-1", DesiredCapacity = 40 } }); var source = new AutoScalingGroupSource(autoScalingClient); var creator = new CloudFormationAlarmCreator(stack, new ConsoleAlarmLogger(true)); var config = ConfigHelper.CreateBasicConfiguration("test", "group-suffix", new AlertingGroupServices() { AutoScaling = new AwsServiceAlarms <AutoScalingResourceConfig>() { Resources = new List <ResourceThresholds <AutoScalingResourceConfig> >() { new ResourceThresholds <AutoScalingResourceConfig>() { Name = "group-1" } } } }); var fakeTime = new Mock <ICurrentTimeProvider>(); var cloudWatch = new Mock <IAmazonCloudWatch>(); var provider = new AutoScalingGroupAlarmDataProvider(cloudWatch.Object, fakeTime.Object); var sut = IoCHelper.CreateSystemUnderTest( source, provider, provider, WatchmanServiceConfigurationMapper.MapAutoScaling, creator, ConfigHelper.ConfigLoaderFor(config) ); // act await sut.LoadAndGenerateAlarms(RunMode.GenerateAlarms); // assert var alarms = stack .Stack("Watchman-test") .AlarmsByDimension("AutoScalingGroupName"); var alarm = alarms["group-1"].Single(a => a.Properties["AlarmName"].ToString().Contains("InService")); var defaultAlarmThreshold = 0.5m; Assert.That((decimal)alarm.Properties["Threshold"], Is.EqualTo(40 * defaultAlarmThreshold)); }
public async Task ContinuesWhenAlarmGenerationFailsForOneAlertingGroup() { // arrange var stack = new FakeStackDeployer(); var autoScalingClient = FakeAwsClients.CreateAutoScalingClientForGroups(new[] { new AutoScalingGroup() { AutoScalingGroupName = "group-1", DesiredCapacity = 40 }, new AutoScalingGroup() { AutoScalingGroupName = "group-2", DesiredCapacity = 10 } }); var source = new AutoScalingGroupSource(autoScalingClient); var creator = new CloudFormationAlarmCreator(stack, new ConsoleAlarmLogger(true)); var config1 = new AlertingGroup() { Name = "group-1", AlarmNameSuffix = "suffix-1", Targets = new List <AlertTarget>() { new AlertEmail("*****@*****.**") }, Services = new AlertingGroupServices() { AutoScaling = new AwsServiceAlarms <AutoScalingResourceConfig>() { Resources = new List <ResourceThresholds <AutoScalingResourceConfig> >() { new ResourceThresholds <AutoScalingResourceConfig>() { Name = "group-1", Options = new AutoScalingResourceConfig() { // this will trigger the failure InstanceCountIncreaseDelayMinutes = 5 } } } } } }; var config2 = new AlertingGroup() { Name = "group-2", AlarmNameSuffix = "suffix-2", Targets = new List <AlertTarget>() { new AlertEmail("*****@*****.**") }, Services = new AlertingGroupServices() { AutoScaling = new AwsServiceAlarms <AutoScalingResourceConfig>() { Resources = new List <ResourceThresholds <AutoScalingResourceConfig> >() { new ResourceThresholds <AutoScalingResourceConfig>() { Name = "group-2" } } } } }; var cloudWatch = new Mock <IAmazonCloudWatch>(); cloudWatch .Setup(c => c.GetMetricStatisticsAsync(It.IsAny <GetMetricStatisticsRequest>(), It.IsAny <CancellationToken>())) .ThrowsAsync(new Exception("something bad")); var provider = new AutoScalingGroupAlarmDataProvider(cloudWatch.Object, new CurrentTimeProvider()); var sut = IoCHelper.CreateSystemUnderTest( source, provider, provider, WatchmanServiceConfigurationMapper.MapAutoScaling, creator, ConfigHelper.ConfigLoaderFor(config1, config2) ); Exception caught = null; // act try { await sut.LoadAndGenerateAlarms(RunMode.GenerateAlarms); } catch (Exception ex) { caught = ex; } // assert Assert.That(stack.StackWasDeployed("Watchman-group-1"), Is.EqualTo(false)); Assert.That(stack.StackWasDeployed("Watchman-group-2"), Is.EqualTo(true)); Assert.That(caught, Is.Not.Null); }
public async Task AlarmCreatedWithCorrectProperties() { // arrange var stack = new FakeStackDeployer(); var dynamoClient = CreateDynamoClientForTables(new[] { new TableDescription() { TableName = "first-dynamo-table", ProvisionedThroughput = new ProvisionedThroughputDescription() { ReadCapacityUnits = 100, WriteCapacityUnits = 200 } } }); var source = new TableDescriptionSource(dynamoClient); var creator = new CloudFormationAlarmCreator(stack, new ConsoleAlarmLogger(true)); var config = ConfigHelper.CreateBasicConfiguration("test", "group-suffix", "DynamoDb", new List <ResourceThresholds>() { new ResourceThresholds() { Name = "first-dynamo-table" } }); var sut = IoCHelper.CreateSystemUnderTest( source, new DynamoDbDataProvider(), new DynamoDbDataProvider(), WatchmanServiceConfigurationMapper.MapDynamoDb, creator, ConfigHelper.ConfigLoaderFor(config) ); // act await sut.LoadAndGenerateAlarms(RunMode.GenerateAlarms); // assert const decimal defaultCapacityThresholdFraction = 0.8m; const int defaultThrottleThreshold = 2; var alarmsByTable = stack .Stack("Watchman-test") .AlarmsByDimension("TableName"); Assert.That(alarmsByTable.ContainsKey("first-dynamo-table"), Is.True); var alarms = alarmsByTable["first-dynamo-table"]; Assert.That(alarms.Exists( alarm => alarm.Properties["MetricName"].Value <string>() == "ConsumedReadCapacityUnits" && alarm.Properties["AlarmName"].Value <string>().Contains("ConsumedReadCapacityUnitsHigh") && alarm.Properties["Threshold"].Value <int>() == 100 * defaultCapacityThresholdFraction && alarm.Properties["Period"].Value <int>() == 60 && alarm.Properties["ComparisonOperator"].Value <string>() == "GreaterThanOrEqualToThreshold" && alarm.Properties["Statistic"].Value <string>() == "Sum" && alarm.Properties["Namespace"].Value <string>() == AwsNamespace.DynamoDb ) ); Assert.That(alarms.Exists( alarm => alarm.Properties["MetricName"].Value <string>() == "ConsumedWriteCapacityUnits" && alarm.Properties["AlarmName"].Value <string>().Contains("ConsumedWriteCapacityUnitsHigh") && alarm.Properties["Threshold"].Value <int>() == 200 * defaultCapacityThresholdFraction && alarm.Properties["Period"].Value <int>() == 60 && alarm.Properties["ComparisonOperator"].Value <string>() == "GreaterThanOrEqualToThreshold" && alarm.Properties["Statistic"].Value <string>() == "Sum" && alarm.Properties["Namespace"].Value <string>() == AwsNamespace.DynamoDb ) ); Assert.That(alarms.Exists( alarm => alarm.Properties["MetricName"].Value <string>() == "ThrottledRequests" && alarm.Properties["AlarmName"].Value <string>().Contains("ThrottledRequestsHigh") && alarm.Properties["Threshold"].Value <int>() == defaultThrottleThreshold && alarm.Properties["Period"].Value <int>() == 60 && alarm.Properties["ComparisonOperator"].Value <string>() == "GreaterThanOrEqualToThreshold" && alarm.Properties["Statistic"].Value <string>() == "Sum" && alarm.Properties["Namespace"].Value <string>() == AwsNamespace.DynamoDb ) ); }
public async Task AlarmCreatedWithCorrectProperties() { // arrange var fakeStackDeployer = new FakeStackDeployer(); var dynamoClient = FakeAwsClients.CreateDynamoClientForTables(new[] { new TableDescription() { TableName = "first-dynamo-table", ProvisionedThroughput = new ProvisionedThroughputDescription() { ReadCapacityUnits = 100, WriteCapacityUnits = 200 } } }); var lambdaClient = FakeAwsClients.CreateLambdaClientForFunctions(new[] { new FunctionConfiguration() { FunctionName = "first-lambda-function" } }); var creator = new CloudFormationAlarmCreator(fakeStackDeployer, new ConsoleAlarmLogger(true)); var config = ConfigHelper.CreateBasicConfiguration( "test", "group-suffix", new AlertingGroupServices() { DynamoDb = new AwsServiceAlarms <ResourceConfig>() { Resources = new List <ResourceThresholds <ResourceConfig> >() { new ResourceThresholds <ResourceConfig>() { Name = "first-dynamo-table" } } }, Lambda = new AwsServiceAlarms <ResourceConfig>() { Resources = new List <ResourceThresholds <ResourceConfig> >() { new ResourceThresholds <ResourceConfig>() { Name = "first-lambda-function" } } } } ); var sutBuilder = new Builder(ConfigHelper.ConfigLoaderFor(config), creator); sutBuilder.AddService( new TableDescriptionSource(dynamoClient), new DynamoDbDataProvider(), new DynamoDbDataProvider(), WatchmanServiceConfigurationMapper.MapDynamoDb ); sutBuilder.AddService( new LambdaSource(lambdaClient), new LambdaAlarmDataProvider(), new LambdaAlarmDataProvider(), WatchmanServiceConfigurationMapper.MapLambda ); var sut = sutBuilder.Build(); // act await sut.LoadAndGenerateAlarms(RunMode.GenerateAlarms); // assert var alarmsByTable = fakeStackDeployer .Stack("Watchman-test") .AlarmsByDimension("TableName"); Assert.That(alarmsByTable.ContainsKey("first-dynamo-table"), Is.True); var alarmsByFunction = fakeStackDeployer .Stack("Watchman-test") .AlarmsByDimension("FunctionName"); Assert.That(alarmsByFunction.ContainsKey("first-lambda-function"), Is.True); }
public async Task SaveChanges_ConfigSetsNumberOfStacksGreaterThan1_DeploysMultipleStacks() { // arrange var alarms = new List <Alarm>(); for (int i = 0; i < 20; i++) { alarms.Add(Alarm($"Test alarm {i}")); } var group = Group(numberOfStacks: 2); var stackName1 = $"Watchman-{group.Name.ToLowerInvariant()}"; var stackName2 = $"Watchman-{group.Name.ToLowerInvariant()}-1"; SetupListStacksToReturnStackNames(); _cloudFormationMock.Setup(x => x.DescribeStacksAsync( It.Is <DescribeStacksRequest>(s => s.StackName == stackName1), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeStacksResponse { Stacks = new List <Stack> { new Stack { StackStatus = "CREATE_COMPLETE", StackName = stackName1 } } }); _cloudFormationMock.Setup(x => x.DescribeStacksAsync( It.Is <DescribeStacksRequest>(s => s.StackName == stackName2), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeStacksResponse { Stacks = new List <Stack> { new Stack { StackStatus = "CREATE_COMPLETE", StackName = stackName2 } } }); var deployer = MakeDeployer(null, TimeSpan.FromMilliseconds(5), TimeSpan.FromMilliseconds(5)); var sut = new CloudFormationAlarmCreator(deployer, new ConsoleAlarmLogger(false)); sut.AddAlarms(group, alarms); // act await sut.SaveChanges(false); // assert _cloudFormationMock .Verify(x => x.CreateStackAsync( It.Is <CreateStackRequest>(s => s.StackName == stackName1), It.IsAny <CancellationToken>())); _cloudFormationMock .Verify(x => x.CreateStackAsync( It.Is <CreateStackRequest>(s => s.StackName == stackName2), It.IsAny <CancellationToken>())); }
public async Task CanSetExtendedStatisticAtResourceOrServiceLevel() { // arrange var fakeStackDeployer = new FakeStackDeployer(); var elbClient = FakeAwsClients.CreateElbClientForLoadBalancers(new[] { new LoadBalancerDescription() { LoadBalancerName = "elb-1" }, new LoadBalancerDescription() { LoadBalancerName = "elb-2" } }); var creator = new CloudFormationAlarmCreator(fakeStackDeployer, new ConsoleAlarmLogger(true)); var config = ConfigHelper.CreateBasicConfiguration( "test", "group-suffix", new AlertingGroupServices() { Elb = new AwsServiceAlarms <ResourceConfig>() { Resources = new List <ResourceThresholds <ResourceConfig> >() { new ResourceThresholds <ResourceConfig>() { Name = "elb-1", Values = new Dictionary <string, AlarmValues>() { { "LatencyHigh", new AlarmValues(null, null, "p97") } } }, new ResourceThresholds <ResourceConfig>() { Name = "elb-2" } }, // set default for whole group Values = new Dictionary <string, AlarmValues>() { { "LatencyHigh", new AlarmValues(null, null, "p99") } } } } ); var sutBuilder = new Builder(ConfigHelper.ConfigLoaderFor(config), creator); sutBuilder.AddService( new ElbSource(elbClient), new ElbAlarmDataProvider(), new ElbAlarmDataProvider(), WatchmanServiceConfigurationMapper.MapElb ); var sut = sutBuilder.Build(); // act await sut.LoadAndGenerateAlarms(RunMode.GenerateAlarms); // assert var alarmsByElb = fakeStackDeployer .Stack("Watchman-test") .AlarmsByDimension("LoadBalancerName"); // should take override var alarm = alarmsByElb["elb-1"].FirstOrDefault(a => a.Properties["AlarmName"].ToString().Contains("LatencyHigh")); Assert.That(alarm, Is.Not.Null); Assert.That(alarm.Properties["ExtendedStatistic"].ToString(), Is.EqualTo("p97")); // should take default of p99 var alarm2 = alarmsByElb["elb-2"].FirstOrDefault(a => a.Properties["AlarmName"].ToString().Contains("LatencyHigh")); Assert.That(alarm2, Is.Not.Null); Assert.That(alarm2.Properties["ExtendedStatistic"].ToString(), Is.EqualTo("p99")); }