这是indexloc提供的服务,不要输入任何密码
Skip to content
This repository was archived by the owner on Mar 4, 2021. It is now read-only.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.amazonaws.services.autoscaling.model.SuspendedProcess;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.netflix.simianarmy.MonkeyConfiguration;
import com.netflix.simianarmy.client.aws.AWSClient;
import com.netflix.simianarmy.conformity.Cluster;
Expand All @@ -33,6 +34,7 @@

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* The class implementing a crawler that gets the auto scaling groups from AWS.
Expand Down Expand Up @@ -75,11 +77,13 @@ public List<Cluster> clusters(String... clusterNames) {
for (Map.Entry<String, AWSClient> entry : regionToAwsClient.entrySet()) {
String region = entry.getKey();
AWSClient awsClient = entry.getValue();
Set<String> asgInstances = Sets.newHashSet();
LOGGER.info(String.format("Crawling clusters in region %s", region));
for (AutoScalingGroup asg : awsClient.describeAutoScalingGroups(clusterNames)) {
List<String> instances = Lists.newArrayList();
for (Instance instance : asg.getInstances()) {
instances.add(instance.getInstanceId());
asgInstances.add(instance.getInstanceId());
}
com.netflix.simianarmy.conformity.AutoScalingGroup conformityAsg =
new com.netflix.simianarmy.conformity.AutoScalingGroup(
Expand All @@ -94,21 +98,40 @@ public List<Cluster> clusters(String... clusterNames) {
}
}
Cluster cluster = new Cluster(asg.getAutoScalingGroupName(), region, conformityAsg);
updateCluster(cluster);
list.add(cluster);
updateExcludedConformityRules(cluster);
cluster.setOwnerEmail(getOwnerEmailForCluster(cluster));
String prop = String.format("simianarmy.conformity.cluster.%s.optedOut", cluster.getName());
if (cfg.getBoolOrElse(prop, false)) {
LOGGER.info(String.format("Cluster %s is opted out of Conformity Monkey.", cluster.getName()));
cluster.setOptOutOfConformity(true);
} else {
cluster.setOptOutOfConformity(false);
}
//Cluster containing all solo instances
Set<String> instances = Sets.newHashSet();
for (com.amazonaws.services.ec2.model.Instance awsInstance : awsClient.describeInstances()) {
if (!asgInstances.contains(awsInstance.getInstanceId())) {
LOGGER.info(String.format("Adding instance %s to soloInstances cluster.",
awsInstance.getInstanceId()));
instances.add(awsInstance.getInstanceId());
}
}
//Only create cluster if we have solo instances.
if (!instances.isEmpty()) {
Cluster cluster = new Cluster("SoloInstances", region, instances);
updateCluster(cluster);
list.add(cluster);
}
}
return list;
}

private void updateCluster(Cluster cluster) {
updateExcludedConformityRules(cluster);
cluster.setOwnerEmail(getOwnerEmailForCluster(cluster));
String prop = String.format("simianarmy.conformity.cluster.%s.optedOut", cluster.getName());
if (cfg.getBoolOrElse(prop, false)) {
LOGGER.info(String.format("Cluster %s is opted out of Conformity Monkey.", cluster.getName()));
cluster.setOptOutOfConformity(true);
} else {
cluster.setOptOutOfConformity(false);
}
}

/**
* Gets the owner email from the monkey configuration.
* @param cluster
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.netflix.simianarmy.aws.conformity.rule;

import com.amazonaws.services.ec2.model.Instance;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.netflix.simianarmy.client.aws.AWSClient;
import com.netflix.simianarmy.conformity.AutoScalingGroup;
import com.netflix.simianarmy.conformity.Cluster;
import com.netflix.simianarmy.conformity.Conformity;
import com.netflix.simianarmy.conformity.ConformityRule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* The class implements a conformity rule to check an instance is in a virtual private cloud.
*/
public class InstanceInVPC implements ConformityRule {

private static final Logger LOGGER = LoggerFactory.getLogger(InstanceInVPC.class);

private final Map<String, AWSClient> regionToAwsClient = Maps.newHashMap();
private static final String RULE_NAME = "InstanceInVPC";
private static final String REASON = "VPC_ID not defined";

@Override
public Conformity check(Cluster cluster) {
Collection<String> failedComponents = Lists.newArrayList();
//check all instances
Set<String> failedInstances = checkInstancesInVPC(cluster.getRegion(), cluster.getSoloInstances());
failedComponents.addAll(failedInstances);
//check asg instances
for (AutoScalingGroup asg : cluster.getAutoScalingGroups()) {
if (asg.isSuspended()) {
continue;
}
Set<String> asgFailedInstances = checkInstancesInVPC(cluster.getRegion(), asg.getInstances());
failedComponents.addAll(asgFailedInstances);
}
return new Conformity(getName(), failedComponents);
}

@Override
public String getName() {
return RULE_NAME;
}

@Override
public String getNonconformingReason() {
return REASON;
}

private AWSClient getAwsClient(String region) {
AWSClient awsClient = regionToAwsClient.get(region);
if (awsClient == null) {
awsClient = new AWSClient(region);
regionToAwsClient.put(region, awsClient);
}
return awsClient;
}

private Set<String> checkInstancesInVPC(String region, Collection<String> instances) {
Set<String> failedInstances = Sets.newHashSet();
for (String instanceId : instances) {
for (Instance awsInstance : getAWSInstances(region, instanceId)) {
if (awsInstance.getVpcId() == null) {
LOGGER.info(String.format("Instance %s is not in a virtual private cloud", instanceId));
failedInstances.add(instanceId);
}
}
}
return failedInstances;
}

/**
* Gets the list of AWS instances. Can be overridden
* @param region the region
* @param instanceId the instance id.
* @return the list of the AWS instances with the given id.
*/
protected List<Instance> getAWSInstances(String region, String instanceId) {
AWSClient awsClient = getAwsClient(region);
return awsClient.describeInstances(instanceId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.netflix.simianarmy.aws.conformity.rule.InstanceHasHealthCheckUrl;
import com.netflix.simianarmy.aws.conformity.rule.InstanceHasStatusUrl;
import com.netflix.simianarmy.aws.conformity.rule.InstanceInSecurityGroup;
import com.netflix.simianarmy.aws.conformity.rule.InstanceInVPC;
import com.netflix.simianarmy.aws.conformity.rule.InstanceIsHealthyInEureka;
import com.netflix.simianarmy.aws.conformity.rule.InstanceTooOld;
import com.netflix.simianarmy.aws.conformity.rule.SameZonesInElbAndAsg;
Expand Down Expand Up @@ -143,6 +144,11 @@ public BasicConformityMonkeyContext() {
ruleEngine().addRule(new SameZonesInElbAndAsg());
}

if (configuration().getBoolOrElse(
"simianarmy.conformity.rule.InstanceInVPC.enabled", false)) {
ruleEngine.addRule(new InstanceInVPC());
}

regionToAwsClient.put(region(), new AWSClient(region()));
clusterCrawler = new AWSClusterCrawler(regionToAwsClient, configuration());
sesClient = new AmazonSimpleEmailServiceClient();
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/com/netflix/simianarmy/conformity/Cluster.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* The class implementing clusters. Cluster is the basic unit of conformity check. It can be a single ASG or
Expand All @@ -55,6 +56,7 @@ public class Cluster {
private final Collection<String> excludedConformityRules = Sets.newHashSet();
private boolean isConforming;
private boolean isOptOutOfConformity;
private final Set<String> soloInstances = Sets.newHashSet();

/**
* Constructor.
Expand All @@ -74,6 +76,24 @@ public Cluster(String name, String region, AutoScalingGroup... autoScalingGroups
}
}

/**
* Constructor.
* @param name
* the name of the cluster
* @param soloInstances
* the list of all instances
*/
public Cluster(String name, String region, Set<String> soloInstances) {
Validate.notNull(name);
Validate.notNull(region);
Validate.notNull(soloInstances);
this.name = name;
this.region = region;
for (String soleInstance : soloInstances) {
this.soloInstances.add(soleInstance);
}
}

/**
* Gets the name of the cluster.
* @return
Expand Down Expand Up @@ -294,4 +314,9 @@ private static void putToMapIfNotNull(Map<String, String> map, String key, Strin
map.put(key, value);
}
}

public Set<String> getSoloInstances() {
return Collections.unmodifiableSet(soloInstances);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// CHECKSTYLE IGNORE Javadoc
/*
*
* Copyright 2013 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.netflix.simianarmy.aws.conformity.rule;

import com.amazonaws.services.ec2.model.Instance;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.netflix.simianarmy.conformity.AutoScalingGroup;
import com.netflix.simianarmy.conformity.Cluster;
import com.netflix.simianarmy.conformity.Conformity;
import junit.framework.Assert;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.List;
import java.util.Set;

import static org.mockito.Mockito.doReturn;


public class TestInstanceInVPC {
private static final String VPC_INSTANCE_ID = "abc-123";
private static final String INSTANCE_ID = "zxy-098";
private static final String REGION = "eu-west-1";

@Spy
private InstanceInVPC instanceInVPC = new InstanceInVPC();

@BeforeMethod
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
List<Instance> instanceList = Lists.newArrayList();
Instance instance = new Instance().withInstanceId(VPC_INSTANCE_ID).withVpcId("12345");
instanceList.add(instance);
doReturn(instanceList).when(instanceInVPC).getAWSInstances(REGION, VPC_INSTANCE_ID);
List<Instance> instanceList2 = Lists.newArrayList();
Instance instance2 = new Instance().withInstanceId(INSTANCE_ID);
instanceList2.add(instance2);
doReturn(instanceList2).when(instanceInVPC).getAWSInstances(REGION, INSTANCE_ID);

}

@Test
public void testCheckSoloInstances() throws Exception {
Set<String> list = Sets.newHashSet();
list.add(VPC_INSTANCE_ID);
list.add(INSTANCE_ID);
Cluster cluster = new Cluster("SoloInstances", REGION, list);
Conformity result = instanceInVPC.check(cluster);
Assert.assertNotNull(result);
Assert.assertEquals(result.getRuleId(), instanceInVPC.getName());
Assert.assertEquals(result.getFailedComponents().size(), 1);
Assert.assertEquals(result.getFailedComponents().iterator().next(), INSTANCE_ID);
}

@Test
public void testAsgInstances() throws Exception {
AutoScalingGroup autoScalingGroup = new AutoScalingGroup("Conforming", VPC_INSTANCE_ID);
Cluster conformingCluster = new Cluster("Conforming", REGION, autoScalingGroup);
Conformity result = instanceInVPC.check(conformingCluster);
Assert.assertNotNull(result);
Assert.assertEquals(result.getRuleId(), instanceInVPC.getName());
Assert.assertEquals(result.getFailedComponents().size(), 0);

autoScalingGroup = new AutoScalingGroup("NonConforming", INSTANCE_ID);
Cluster nonConformingCluster = new Cluster("NonConforming", REGION, autoScalingGroup);
result = instanceInVPC.check(nonConformingCluster);
Assert.assertNotNull(result);
Assert.assertEquals(result.getRuleId(), instanceInVPC.getName());
Assert.assertEquals(result.getFailedComponents().size(), 1);
Assert.assertEquals(result.getFailedComponents().iterator().next(), INSTANCE_ID);
}
}