Package com.netflix.simianarmy.basic.janitor

Source Code of com.netflix.simianarmy.basic.janitor.BasicJanitorMonkeyContext

/*
*  Copyright 2012 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.
*
*/
// CHECKSTYLE IGNORE MagicNumberCheck
package com.netflix.simianarmy.basic.janitor;

import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClient;
import com.netflix.discovery.DiscoveryManager;
import com.netflix.simianarmy.MonkeyCalendar;
import com.netflix.simianarmy.MonkeyConfiguration;
import com.netflix.simianarmy.MonkeyRecorder;
import com.netflix.simianarmy.aws.janitor.ASGJanitor;
import com.netflix.simianarmy.aws.janitor.EBSSnapshotJanitor;
import com.netflix.simianarmy.aws.janitor.EBSVolumeJanitor;
import com.netflix.simianarmy.aws.janitor.ImageJanitor;
import com.netflix.simianarmy.aws.janitor.InstanceJanitor;
import com.netflix.simianarmy.aws.janitor.LaunchConfigJanitor;
import com.netflix.simianarmy.aws.janitor.SimpleDBJanitorResourceTracker;
import com.netflix.simianarmy.aws.janitor.crawler.ASGJanitorCrawler;
import com.netflix.simianarmy.aws.janitor.crawler.EBSSnapshotJanitorCrawler;
import com.netflix.simianarmy.aws.janitor.crawler.EBSVolumeJanitorCrawler;
import com.netflix.simianarmy.aws.janitor.crawler.InstanceJanitorCrawler;
import com.netflix.simianarmy.aws.janitor.crawler.LaunchConfigJanitorCrawler;
import com.netflix.simianarmy.aws.janitor.crawler.edda.EddaASGJanitorCrawler;
import com.netflix.simianarmy.aws.janitor.crawler.edda.EddaEBSSnapshotJanitorCrawler;
import com.netflix.simianarmy.aws.janitor.crawler.edda.EddaEBSVolumeJanitorCrawler;
import com.netflix.simianarmy.aws.janitor.crawler.edda.EddaImageJanitorCrawler;
import com.netflix.simianarmy.aws.janitor.crawler.edda.EddaInstanceJanitorCrawler;
import com.netflix.simianarmy.aws.janitor.crawler.edda.EddaLaunchConfigJanitorCrawler;
import com.netflix.simianarmy.aws.janitor.rule.ami.UnusedImageRule;
import com.netflix.simianarmy.aws.janitor.rule.asg.ASGInstanceValidator;
import com.netflix.simianarmy.aws.janitor.rule.asg.DiscoveryASGInstanceValidator;
import com.netflix.simianarmy.aws.janitor.rule.asg.DummyASGInstanceValidator;
import com.netflix.simianarmy.aws.janitor.rule.asg.OldEmptyASGRule;
import com.netflix.simianarmy.aws.janitor.rule.asg.SuspendedASGRule;
import com.netflix.simianarmy.aws.janitor.rule.instance.OrphanedInstanceRule;
import com.netflix.simianarmy.aws.janitor.rule.launchconfig.OldUnusedLaunchConfigRule;
import com.netflix.simianarmy.aws.janitor.rule.snapshot.NoGeneratedAMIRule;
import com.netflix.simianarmy.aws.janitor.rule.volume.DeleteOnTerminationRule;
import com.netflix.simianarmy.aws.janitor.rule.volume.OldDetachedVolumeRule;
import com.netflix.simianarmy.basic.BasicSimianArmyContext;
import com.netflix.simianarmy.client.edda.EddaClient;
import com.netflix.simianarmy.janitor.AbstractJanitor;
import com.netflix.simianarmy.janitor.JanitorCrawler;
import com.netflix.simianarmy.janitor.JanitorEmailBuilder;
import com.netflix.simianarmy.janitor.JanitorEmailNotifier;
import com.netflix.simianarmy.janitor.JanitorMonkey;
import com.netflix.simianarmy.janitor.JanitorResourceTracker;
import com.netflix.simianarmy.janitor.JanitorRuleEngine;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* The basic implementation of the context class for Janitor monkey.
*/
public class BasicJanitorMonkeyContext extends BasicSimianArmyContext implements JanitorMonkey.Context {

    /** The Constant LOGGER. */
    private static final Logger LOGGER = LoggerFactory.getLogger(BasicJanitorMonkeyContext.class);

    /** The email notifier. */
    private final JanitorEmailNotifier emailNotifier;

    private final JanitorResourceTracker janitorResourceTracker;

    /** The janitors. */
    private final List<AbstractJanitor> janitors;

    private final String monkeyRegion;

    private final MonkeyCalendar monkeyCalendar;

    private final AmazonSimpleEmailServiceClient sesClient;

    private final JanitorEmailBuilder janitorEmailBuilder;

    private final String defaultEmail;

    private final String[] ccEmails;

    private final String sourceEmail;

    private final String ownerEmailDomain;

    private final int daysBeforeTermination;

    /**
     * The constructor.
     */
    public BasicJanitorMonkeyContext() {
        super("simianarmy.properties", "client.properties", "janitor.properties");

        monkeyRegion = region();
        monkeyCalendar = calendar();

        String resourceDomain = configuration().getStrOrElse("simianarmy.janitor.resources.sdb.domain", "SIMIAN_ARMY");

        Set<String> enabledResourceSet = getEnabledResourceSet();

        janitorResourceTracker = new SimpleDBJanitorResourceTracker(awsClient(), resourceDomain);

        janitorEmailBuilder = new BasicJanitorEmailBuilder();
        sesClient = new AmazonSimpleEmailServiceClient();
        defaultEmail = configuration().getStrOrElse("simianarmy.janitor.notification.defaultEmail", "");
        ccEmails = StringUtils.split(
                configuration().getStrOrElse("simianarmy.janitor.notification.ccEmails", ""), ",");
        sourceEmail = configuration().getStrOrElse("simianarmy.janitor.notification.sourceEmail", "");
        ownerEmailDomain = configuration().getStrOrElse("simianarmy.janitor.notification.ownerEmailDomain", "");
        daysBeforeTermination =
                (int) configuration().getNumOrElse("simianarmy.janitor.notification.daysBeforeTermination", 3);

        emailNotifier = new JanitorEmailNotifier(getJanitorEmailNotifierContext());

        janitors = new ArrayList<AbstractJanitor>();
        if (enabledResourceSet.contains("ASG")) {
            janitors.add(getASGJanitor());
        }

        if (enabledResourceSet.contains("INSTANCE")) {
            janitors.add(getInstanceJanitor());
        }

        if (enabledResourceSet.contains("EBS_VOLUME")) {
            janitors.add(getEBSVolumeJanitor());
        }

        if (enabledResourceSet.contains("EBS_SNAPSHOT")) {
            janitors.add(getEBSSnapshotJanitor());
        }

        if (enabledResourceSet.contains("LAUNCH_CONFIG")) {
            janitors.add(getLaunchConfigJanitor());
        }

        if (enabledResourceSet.contains("IMAGE")) {
            janitors.add(getImageJanitor());
        }
    }

    private ASGJanitor getASGJanitor() {
        JanitorRuleEngine ruleEngine = new BasicJanitorRuleEngine();
        boolean discoveryEnabled = configuration().getBoolOrElse("simianarmy.janitor.Eureka.enabled", false);
        ASGInstanceValidator instanceValidator;
        if (discoveryEnabled) {
            LOGGER.info("Initializing Discovery client.");
            instanceValidator = new DiscoveryASGInstanceValidator(DiscoveryManager.getInstance().getDiscoveryClient());
        } else {
            LOGGER.info("Discovery/Eureka is not enabled, use the dummy instance validator.");
            instanceValidator = new DummyASGInstanceValidator();
        }
        if (configuration().getBoolOrElse("simianarmy.janitor.rule.oldEmptyASGRule.enabled", false)) {
            ruleEngine.addRule(new OldEmptyASGRule(monkeyCalendar,
                    (int) configuration().getNumOrElse(
                            "simianarmy.janitor.rule.oldEmptyASGRule.launchConfigAgeThreshold", 50),
                            (int) configuration().getNumOrElse(
                                    "simianarmy.janitor.rule.oldEmptyASGRule.retentionDays", 10),
                                    instanceValidator
                    ));
        }

        if (configuration().getBoolOrElse("simianarmy.janitor.rule.suspendedASGRule.enabled", false)) {
            ruleEngine.addRule(new SuspendedASGRule(monkeyCalendar,
                    (int) configuration().getNumOrElse(
                            "simianarmy.janitor.rule.suspendedASGRule.suspensionAgeThreshold", 2),
                            (int) configuration().getNumOrElse(
                                    "simianarmy.janitor.rule.suspendedASGRule.retentionDays", 5),
                                    instanceValidator
                    ));
        }
        JanitorCrawler crawler;
        if (configuration().getBoolOrElse("simianarmy.janitor.edda.enabled", false)) {
            crawler = new EddaASGJanitorCrawler(createEddaClient(), awsClient().region());
        } else {
            crawler = new ASGJanitorCrawler(awsClient());
        }
        BasicJanitorContext asgJanitorCtx = new BasicJanitorContext(
                monkeyRegion, ruleEngine, crawler, janitorResourceTracker,
                monkeyCalendar, configuration(), recorder());
        return new ASGJanitor(awsClient(), asgJanitorCtx);
    }

    private InstanceJanitor getInstanceJanitor() {
        JanitorRuleEngine ruleEngine = new BasicJanitorRuleEngine();
        if (configuration().getBoolOrElse("simianarmy.janitor.rule.orphanedInstanceRule.enabled", false)) {
            ruleEngine.addRule(new OrphanedInstanceRule(monkeyCalendar,
                    (int) configuration().getNumOrElse(
                            "simianarmy.janitor.rule.orphanedInstanceRule.instanceAgeThreshold", 2),
                            (int) configuration().getNumOrElse(
                                    "simianarmy.janitor.rule.orphanedInstanceRule.retentionDaysWithOwner", 3),
                                    (int) configuration().getNumOrElse(
                                            "simianarmy.janitor.rule.orphanedInstanceRule.retentionDaysWithoutOwner",
                                            8)));
        }
        JanitorCrawler instanceCrawler;
        if (configuration().getBoolOrElse("simianarmy.janitor.edda.enabled", false)) {
            instanceCrawler = new EddaInstanceJanitorCrawler(createEddaClient(), awsClient().region());
        } else {
            instanceCrawler = new InstanceJanitorCrawler(awsClient());
        }
        BasicJanitorContext instanceJanitorCtx = new BasicJanitorContext(
                monkeyRegion, ruleEngine, instanceCrawler, janitorResourceTracker,
                monkeyCalendar, configuration(), recorder());
        return new InstanceJanitor(awsClient(), instanceJanitorCtx);
    }

    private EBSVolumeJanitor getEBSVolumeJanitor() {
        JanitorRuleEngine ruleEngine = new BasicJanitorRuleEngine();
        if (configuration().getBoolOrElse("simianarmy.janitor.rule.oldDetachedVolumeRule.enabled", false)) {
            ruleEngine.addRule(new OldDetachedVolumeRule(monkeyCalendar,
                    (int) configuration().getNumOrElse(
                            "simianarmy.janitor.rule.oldDetachedVolumeRule.detachDaysThreshold", 30),
                            (int) configuration().getNumOrElse(
                                    "simianarmy.janitor.rule.oldDetachedVolumeRule.retentionDays", 7)));

            if (configuration().getBoolOrElse("simianarmy.janitor.edda.enabled", false)
                && configuration().getBoolOrElse("simianarmy.janitor.rule.deleteOnTerminationRule.enabled", false)) {
                ruleEngine.addRule(new DeleteOnTerminationRule(monkeyCalendar, (int) configuration().getNumOrElse(
                        "simianarmy.janitor.rule.deleteOnTerminationRule.retentionDays", 3)));
            }
        }
        JanitorCrawler volumeCrawler;
        if (configuration().getBoolOrElse("simianarmy.janitor.edda.enabled", false)) {
            volumeCrawler = new EddaEBSVolumeJanitorCrawler(createEddaClient(), awsClient().region());
        } else {
            volumeCrawler = new EBSVolumeJanitorCrawler(awsClient());
        }

        BasicJanitorContext volumeJanitorCtx = new BasicJanitorContext(
                monkeyRegion, ruleEngine, volumeCrawler, janitorResourceTracker,
                monkeyCalendar, configuration(), recorder());
        return new EBSVolumeJanitor(awsClient(), volumeJanitorCtx);
    }

    private EBSSnapshotJanitor getEBSSnapshotJanitor() {
        JanitorRuleEngine ruleEngine = new BasicJanitorRuleEngine();
        if (configuration().getBoolOrElse("simianarmy.janitor.rule.noGeneratedAMIRule.enabled", false)) {
            ruleEngine.addRule(new NoGeneratedAMIRule(monkeyCalendar,
                    (int) configuration().getNumOrElse("simianarmy.janitor.rule.noGeneratedAMIRule.ageThreshold", 30),
                    (int) configuration().getNumOrElse(
                            "simianarmy.janitor.rule.noGeneratedAMIRule.retentionDays", 7)));
        }
        JanitorCrawler snapshotCrawler;
        if (configuration().getBoolOrElse("simianarmy.janitor.edda.enabled", false)) {
            snapshotCrawler = new EddaEBSSnapshotJanitorCrawler(
                    configuration().getStr("simianarmy.janitor.snapshots.ownerId"),
                    createEddaClient(), awsClient().region());
        } else {
            snapshotCrawler = new EBSSnapshotJanitorCrawler(awsClient());
        }
        BasicJanitorContext snapshotJanitorCtx = new BasicJanitorContext(
                monkeyRegion, ruleEngine, snapshotCrawler, janitorResourceTracker,
                monkeyCalendar, configuration(), recorder());
        return new EBSSnapshotJanitor(awsClient(), snapshotJanitorCtx);
    }

    private LaunchConfigJanitor getLaunchConfigJanitor() {
        JanitorRuleEngine ruleEngine = new BasicJanitorRuleEngine();
        if (configuration().getBoolOrElse("simianarmy.janitor.rule.oldUnusedLaunchConfigRule.enabled", false)) {
            ruleEngine.addRule(new OldUnusedLaunchConfigRule(monkeyCalendar,
                    (int) configuration().getNumOrElse(
                            "simianarmy.janitor.rule.oldUnusedLaunchConfigRule.ageThreshold", 4),
                    (int) configuration().getNumOrElse(
                            "simianarmy.janitor.rule.oldUnusedLaunchConfigRule.retentionDays", 3)));
        }
        JanitorCrawler crawler;
        if (configuration().getBoolOrElse("simianarmy.janitor.edda.enabled", false)) {
            crawler = new EddaLaunchConfigJanitorCrawler(
                    createEddaClient(), awsClient().region());
        } else {
            crawler = new LaunchConfigJanitorCrawler(awsClient());
        }
        BasicJanitorContext janitorCtx = new BasicJanitorContext(
                monkeyRegion, ruleEngine, crawler, janitorResourceTracker,
                monkeyCalendar, configuration(), recorder());
        return new LaunchConfigJanitor(awsClient(), janitorCtx);
    }

    private ImageJanitor getImageJanitor() {
        JanitorCrawler crawler;
        if (configuration().getBoolOrElse("simianarmy.janitor.edda.enabled", false)) {
            crawler = new EddaImageJanitorCrawler(createEddaClient(),
                    configuration().getStr("simianarmy.janitor.image.ownerId"),
                    (int) configuration().getNumOrElse("simianarmy.janitor.image.crawler.lookBackDays", 60),
                    awsClient().region());
        } else {
            throw new RuntimeException("Image Janitor only works when Edda is enabled.");
        }

        JanitorRuleEngine ruleEngine = new BasicJanitorRuleEngine();
        if (configuration().getBoolOrElse("simianarmy.janitor.rule.unusedImageRule.enabled", false)) {
            ruleEngine.addRule(new UnusedImageRule(monkeyCalendar,
                    (int) configuration().getNumOrElse(
                            "simianarmy.janitor.rule.unusedImageRule.retentionDays", 3),
                    (int) configuration().getNumOrElse(
                            "simianarmy.janitor.rule.unusedImageRule.lastReferenceDaysThreshold", 45)));
        }

        BasicJanitorContext janitorCtx = new BasicJanitorContext(
                monkeyRegion, ruleEngine, crawler, janitorResourceTracker,
                monkeyCalendar, configuration(), recorder());
        return new ImageJanitor(awsClient(), janitorCtx);
    }

    private EddaClient createEddaClient() {
        return new EddaClient((int) configuration().getNumOrElse("simianarmy.janitor.edda.client.timeout", 30000),
                (int) configuration().getNumOrElse("simianarmy.janitor.edda.client.retries", 3),
                (int) configuration().getNumOrElse("simianarmy.janitor.edda.client.retryInterval", 1000),
                configuration());
    }

    private Set<String> getEnabledResourceSet() {
        Set<String> enabledResourceSet = new HashSet<String>();
        String enabledResources = configuration().getStr("simianarmy.janitor.enabledResources");
        if (StringUtils.isNotBlank(enabledResources)) {
            for (String resourceType : enabledResources.split(",")) {
                enabledResourceSet.add(resourceType.trim().toUpperCase());
            }
        }
        return enabledResourceSet;
    }

    public JanitorEmailNotifier.Context getJanitorEmailNotifierContext() {
        return new JanitorEmailNotifier.Context() {
            @Override
            public AmazonSimpleEmailServiceClient sesClient() {
                return sesClient;
            }

            @Override
            public String defaultEmail() {
                return defaultEmail;
            }

            @Override
            public int daysBeforeTermination() {
                return daysBeforeTermination;
            }

            @Override
            public String region() {
                return monkeyRegion;
            }

            @Override
            public JanitorResourceTracker resourceTracker() {
                return janitorResourceTracker;
            }

            @Override
            public JanitorEmailBuilder emailBuilder() {
                return janitorEmailBuilder;
            }

            @Override
            public MonkeyCalendar calendar() {
                return monkeyCalendar;
            }

            @Override
            public String[] ccEmails() {
                return ccEmails;
            }

            @Override
            public String sourceEmail() {
                return sourceEmail;
            }

            @Override
            public String ownerEmailDomain() {
                return ownerEmailDomain;
            }
        };
    }

    /** {@inheritDoc} */
    @Override
    public List<AbstractJanitor> janitors() {
        return janitors;
    }

    /** {@inheritDoc} */
    @Override
    public JanitorEmailNotifier emailNotifier() {
        return emailNotifier;
    }

    @Override
    public JanitorResourceTracker resourceTracker() {
        return janitorResourceTracker;
    }

    /** The Context class for Janitor.
     */
    public static class BasicJanitorContext implements AbstractJanitor.Context {
        private final String region;
        private final JanitorRuleEngine ruleEngine;
        private final JanitorCrawler crawler;
        private final JanitorResourceTracker resourceTracker;
        private final MonkeyCalendar calendar;
        private final MonkeyConfiguration config;
        private final MonkeyRecorder recorder;

        /**
         * Constructor.
         * @param region the region of the janitor
         * @param ruleEngine the rule engine used by the janitor
         * @param crawler the crawler used by the janitor
         * @param resourceTracker the resource tracker used by the janitor
         * @param calendar the calendar used by the janitor
         * @param config the monkey configuration used by the janitor
         */
        public BasicJanitorContext(String region, JanitorRuleEngine ruleEngine, JanitorCrawler crawler,
                JanitorResourceTracker resourceTracker, MonkeyCalendar calendar, MonkeyConfiguration config,
                MonkeyRecorder recorder) {
            this.region = region;
            this.resourceTracker = resourceTracker;
            this.ruleEngine = ruleEngine;
            this.crawler = crawler;
            this.calendar = calendar;
            this.config = config;
            this.recorder = recorder;
        }

        @Override
        public String region() {
            return region;
        }

        @Override
        public MonkeyConfiguration configuration() {
            return config;
        }

        @Override
        public MonkeyCalendar calendar() {
            return calendar;
        }

        @Override
        public JanitorRuleEngine janitorRuleEngine() {
            return ruleEngine;
        }

        @Override
        public JanitorCrawler janitorCrawler() {
            return crawler;
        }

        @Override
        public JanitorResourceTracker janitorResourceTracker() {
            return resourceTracker;
        }

        @Override
        public MonkeyRecorder recorder() {
            return recorder;
        }
    }
}
TOP

Related Classes of com.netflix.simianarmy.basic.janitor.BasicJanitorMonkeyContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.