All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zalando.stups.fullstop.plugin.ApplicationMasterdataPlugin Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2015 Zalando SE (http://tech.zalando.com)
 *
 * 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 org.zalando.stups.fullstop.plugin;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.cloudtrail.processinglibrary.model.CloudTrailEvent;
import com.amazonaws.services.cloudtrail.processinglibrary.model.CloudTrailEventData;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.zalando.stups.clients.kio.Application;
import org.zalando.stups.clients.kio.KioOperations;
import org.zalando.stups.clients.kio.NotFoundException;
import org.zalando.stups.fullstop.events.UserDataProvider;
import org.zalando.stups.fullstop.plugin.config.ApplicationMasterdataPluginProperties;
import org.zalando.stups.fullstop.violation.ViolationSink;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;

import static com.google.common.collect.Lists.newArrayList;
import static org.zalando.stups.fullstop.events.CloudTrailEventSupport.getInstanceIds;
import static org.zalando.stups.fullstop.events.CloudTrailEventSupport.violationFor;
import static org.zalando.stups.fullstop.violation.ViolationType.*;

//J-
@Component
public class ApplicationMasterdataPlugin extends AbstractFullstopPlugin {

    private static final Logger LOG = LoggerFactory.getLogger(ApplicationMasterdataPlugin.class);

    private static final String EC2_SOURCE_EVENTS = "ec2.amazonaws.com";

    private static final String EVENT_NAME = "RunInstances";

    private static final String APPLICATION_ID = "application_id";

    private final ApplicationMasterdataPluginProperties applicationMasterdataPluginProperties;

    private final List namedValidators;

    private final ViolationSink violationSink;

    private KioOperations kioOperations;

    private Validator chainingValidator;

    private UserDataProvider userDataProvider;

    @Autowired
    public ApplicationMasterdataPlugin(
            final KioOperations kioOperations,
            final UserDataProvider userDataProvider,
            final ApplicationMasterdataPluginProperties applicationMasterdataPluginProperties,
            final List namedValidators, final ViolationSink violationSink) {
        this.applicationMasterdataPluginProperties = applicationMasterdataPluginProperties;
        this.namedValidators = namedValidators;
        this.violationSink = violationSink;
        this.kioOperations = kioOperations;
        this.userDataProvider = userDataProvider;
    }

    @Override
    public boolean supports(final CloudTrailEvent event) {
        CloudTrailEventData cloudTrailEventData = event.getEventData();
        String eventSource = cloudTrailEventData.getEventSource();
        String eventName = cloudTrailEventData.getEventName();

        return EC2_SOURCE_EVENTS.equals(eventSource) && EVENT_NAME.equals(eventName);
    }

    @Override
    public void processEvent(final CloudTrailEvent event) {
        List instanceIds = getInstanceIds(event);
        for (String instanceId : instanceIds) {
            // 1) get user data
            Map userData;

            final String accountId = event.getEventData().getUserIdentity().getAccountId();
            final String region = event.getEventData().getAwsRegion();
            try {
                userData = userDataProvider.getUserData(
                        accountId, region,
                        instanceId);
            }
            catch (AmazonServiceException ex) {
                violationSink.put(
                        violationFor(event).withInstanceId(instanceId).withType(MISSING_USER_DATA).withPluginFullyQualifiedClassName(
                                ApplicationMasterdataPlugin.class).build());
                return;
            }

            if (userData == null) {
                violationSink.put(
                        violationFor(event).withInstanceId(instanceId).withType(MISSING_USER_DATA).withPluginFullyQualifiedClassName(
                                ApplicationMasterdataPlugin.class).build());
                return;
            }
            // 2) read application id from user data
            if (userData.get(APPLICATION_ID) == null) {
                violationSink.put(
                        violationFor(event).withInstanceId(instanceId).withType(WRONG_USER_DATA).withPluginFullyQualifiedClassName(
                                ApplicationMasterdataPlugin.class).withMetaInfo(
                                APPLICATION_ID).build());
                return;
            }
            String applicationId = userData.get(APPLICATION_ID)
                                           .toString();
            Application application;
            try {
                application = kioOperations.getApplicationById(applicationId);
            }
            catch (NotFoundException ex) {
                violationSink.put(
                        violationFor(event).withInstanceId(instanceId).withType(APPLICATION_NOT_PRESENT_IN_KIO).withPluginFullyQualifiedClassName(
                                ApplicationMasterdataPlugin.class).withMetaInfo(
                                applicationId).build());
                return;
            }
            // ACTUAL VALIDATION
            Errors errors = buildErrorsObject(application);
            this.chainingValidator.validate(
                    application,
                    errors);

            if (errors.hasErrors()) {
                String message = errors.getAllErrors()
                                       .stream()
                                       .map(e -> e.getDefaultMessage())
                                       .reduce(
                                               "",
                                               (s, m) -> s.concat(m + "\n"));
                violationSink.put(
                        violationFor(event).withInstanceId(instanceId).withType(WRONG_APPLICATION_MASTERDATA).withPluginFullyQualifiedClassName(
                                ApplicationMasterdataPlugin.class).withMetaInfo(
                                newArrayList(
                                        applicationId,
                                        message)).build());
            }
        }
    }

    protected Errors buildErrorsObject(final Application application) {
        return new BeanPropertyBindingResult(
                application,
                "application");
    }

    @PostConstruct
    public void init() {
        List validators = Lists.newArrayList();
        for (NamedValidator v : this.namedValidators) {
            if (this.applicationMasterdataPluginProperties.getDefaultValidatorsIfValidatorsEnabledIsEmpty()
                                                          .contains(v.getName())) {
                validators.add(v);
                LOG.info(
                        "VALIDATOR : '{}' IS ENABLED",
                        v.getName());
            }
        }

        this.chainingValidator = new ChainingValidator(validators.toArray(new NamedValidator[validators.size()]));
    }

    /**
     * {@link Validator} implementation that wraps {@link Validator} instances and chains their execution.
     */
    private static class ChainingValidator implements Validator {

        private Validator[] validators;

        public ChainingValidator(final Validator... validators) {
            Assert.notNull(
                    validators,
                    "Validators must not be null");
            this.validators = validators;
        }

        @Override
        public boolean supports(final Class clazz) {
            for (Validator validator : this.validators) {
                if (validator.supports(clazz)) {
                    return true;
                }
            }

            return false;
        }

        @Override
        public void validate(final Object target, final Errors errors) {
            for (Validator validator : this.validators) {
                if (validator.supports(target.getClass())) {
                    validator.validate(
                            target,
                            errors);
                }
            }
        }

    }
}
//J+




© 2015 - 2025 Weber Informatics LLC | Privacy Policy