Java tutorial
/* * * 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.auth.AWSCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.services.ec2.model.Instance; import com.google.common.collect.Lists; import com.google.common.collect.Maps; 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.apache.commons.lang.Validate; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; import java.util.List; import java.util.Map; /** * The class implementing a conformity rule that checks if there are instances that are older than certain days. * Instances are not considered to be permanent in the cloud, so sometimes having too old instances could indicate * potential issues. */ public class InstanceTooOld implements ConformityRule { private static final Logger LOGGER = LoggerFactory.getLogger(InstanceHasStatusUrl.class); private static final String RULE_NAME = "InstanceTooOld"; private final String reason; private final int instanceAgeThreshold; private AWSCredentialsProvider awsCredentialsProvider; /** * Constructor. * @param instanceAgeThreshold * The age in days that makes an instance be considered too old. */ public InstanceTooOld(int instanceAgeThreshold) { this(new DefaultAWSCredentialsProviderChain(), instanceAgeThreshold); } /** * Constructor. * @param awsCredentialsProvider * The AWS credentials provider * @param instanceAgeThreshold * The age in days that makes an instance be considered too old. */ public InstanceTooOld(AWSCredentialsProvider awsCredentialsProvider, int instanceAgeThreshold) { this.awsCredentialsProvider = awsCredentialsProvider; Validate.isTrue(instanceAgeThreshold > 0); this.instanceAgeThreshold = instanceAgeThreshold; this.reason = String.format("Instances are older than %d days", instanceAgeThreshold); } @Override public Conformity check(Cluster cluster) { List<String> instanceIds = Lists.newArrayList(); for (AutoScalingGroup asg : cluster.getAutoScalingGroups()) { instanceIds.addAll(asg.getInstances()); } Map<String, Long> instanceIdToLaunchTime = getInstanceLaunchTimes(cluster.getRegion(), instanceIds.toArray(new String[instanceIds.size()])); Collection<String> failedComponents = Lists.newArrayList(); long creationTimeThreshold = DateTime.now().minusDays(instanceAgeThreshold).getMillis(); for (Map.Entry<String, Long> entry : instanceIdToLaunchTime.entrySet()) { String instanceId = entry.getKey(); if (creationTimeThreshold > entry.getValue()) { LOGGER.info(String.format("Instance %s was created more than %d days ago", instanceId, instanceAgeThreshold)); failedComponents.add(instanceId); } } return new Conformity(getName(), failedComponents); } @Override public String getName() { return RULE_NAME; } @Override public String getNonconformingReason() { return reason; } /** * Gets the launch time (in milliseconds) for a list of instance ids of the same region. The default * implementation is using an AWS client. The method can be overridden in subclasses to get the instance * launch times differently. * @param region * the region of the instances * @param instanceIds * the instance ids, all instances should be in the same region. * @return * the map from instance id to the launch time in milliseconds */ protected Map<String, Long> getInstanceLaunchTimes(String region, String... instanceIds) { Map<String, Long> result = Maps.newHashMap(); if (instanceIds == null || instanceIds.length == 0) { return result; } AWSClient awsClient = new AWSClient(region, awsCredentialsProvider); for (Instance instance : awsClient.describeInstances(instanceIds)) { if (instance.getLaunchTime() != null) { result.put(instance.getInstanceId(), instance.getLaunchTime().getTime()); } else { LOGGER.warn(String.format("No launch time found for instance %s", instance.getInstanceId())); } } return result; } }