Package com.sequenceiq.cloudbreak.service.stack.connector.aws

Source Code of com.sequenceiq.cloudbreak.service.stack.connector.aws.SnsTopicManager

package com.sequenceiq.cloudbreak.service.stack.connector.aws;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.amazonaws.regions.Regions;
import com.amazonaws.services.sns.AmazonSNSClient;
import com.amazonaws.services.sns.model.ConfirmSubscriptionResult;
import com.amazonaws.services.sns.model.CreateTopicResult;
import com.google.common.annotations.VisibleForTesting;
import com.sequenceiq.cloudbreak.conf.ReactorConfig;
import com.sequenceiq.cloudbreak.domain.AwsCredential;
import com.sequenceiq.cloudbreak.domain.CloudPlatform;
import com.sequenceiq.cloudbreak.domain.SnsRequest;
import com.sequenceiq.cloudbreak.domain.SnsTopic;
import com.sequenceiq.cloudbreak.domain.Stack;
import com.sequenceiq.cloudbreak.logger.MDCBuilder;
import com.sequenceiq.cloudbreak.repository.SnsTopicRepository;
import com.sequenceiq.cloudbreak.repository.StackRepository;
import com.sequenceiq.cloudbreak.service.credential.aws.CrossAccountCredentialsProvider;
import com.sequenceiq.cloudbreak.service.stack.event.ProvisionSetupComplete;

import reactor.core.Reactor;
import reactor.event.Event;

@Service
public class SnsTopicManager {

    public static final String NOTIFICATION_TOPIC_ARN_KEY = "notificationTopicArn";

    private static final String CB_TOPIC_NAME = "cloudbreak-notifications";

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

    @Value("${cb.host.addr}")
    private String hostAddress;

    @Value("${cb.sns.ssl}")
    private boolean useSslForSns;

    @Autowired
    private CrossAccountCredentialsProvider credentialsProvider;

    @Autowired
    private SnsTopicRepository snsTopicRepository;

    @Autowired
    private StackRepository stackRepository;

    @Autowired
    private AwsStackUtil awsStackUtil;

    @Autowired
    private Reactor reactor;

    public void createTopicAndSubscribe(AwsCredential awsCredential, Regions region) {
        MDCBuilder.buildMdcContext(awsCredential);
        AmazonSNSClient amazonSNSClient = awsStackUtil.createSnsClient(region, awsCredential);
        LOGGER.info("Amazon SNS client successfully created.");

        CreateTopicResult createTopicResult = amazonSNSClient.createTopic(CB_TOPIC_NAME);
        LOGGER.info("Amazon SNS topic successfully created. [topic ARN: '{}']", createTopicResult.getTopicArn());

        SnsTopic snsTopic = new SnsTopic();
        snsTopic.setName(CB_TOPIC_NAME);
        snsTopic.setRegion(region);
        snsTopic.setCredential(awsCredential);
        snsTopic.setTopicArn(createTopicResult.getTopicArn());
        snsTopic.setConfirmed(false);
        snsTopicRepository.save(snsTopic);

        subscribeToTopic(amazonSNSClient, createTopicResult.getTopicArn());
    }

    /**
     * Handling subscription confirmation should be done only once, so this
     * method is synchronized.
     */
    public synchronized void confirmSubscription(SnsRequest snsRequest) {
        List<SnsTopic> snsTopics = snsTopicRepository.findByTopicArn(snsRequest.getTopicArn());
        for (SnsTopic snsTopic : snsTopics) {
            MDCBuilder.buildMdcContext(snsTopic.getCredential());
            if (!snsTopic.isConfirmed()) {
                AmazonSNSClient amazonSNSClient = awsStackUtil.createSnsClient(snsTopic.getRegion(), snsTopic.getCredential());
                ConfirmSubscriptionResult result = amazonSNSClient.confirmSubscription(snsTopic.getTopicArn(), snsRequest.getToken());
                LOGGER.info("Subscription to Amazon SNS topic confirmed. [topic ARN: '{}', subscription ARN: '{}', credential: '{}']",
                        snsRequest.getTopicArn(), result.getSubscriptionArn(), snsTopic.getCredential().getId());
                snsTopic.setConfirmed(true);
                snsTopicRepository.save(snsTopic);
                notifyRequestedStacks(snsTopic);
            }
        }
    }

    private void notifyRequestedStacks(SnsTopic snsTopic) {
        AwsCredential awsCredential = snsTopic.getCredential();
        MDCBuilder.buildMdcContext(awsCredential);
        List<Stack> requestedStacks = stackRepository.findRequestedStacksWithCredential(awsCredential.getId());
        for (Stack stack : requestedStacks) {
            LOGGER.info("Publishing {} event [StackId: '{}']", ReactorConfig.PROVISION_SETUP_COMPLETE_EVENT, stack.getId());
            reactor.notify(ReactorConfig.PROVISION_SETUP_COMPLETE_EVENT,
                    Event.wrap(new ProvisionSetupComplete(CloudPlatform.AWS, stack.getId()).withSetupProperty(NOTIFICATION_TOPIC_ARN_KEY,
                            snsTopic.getTopicArn())));
        }
    }

    public void subscribeToTopic(AwsCredential awsCredential, Regions region, String topicArn) {
        AmazonSNSClient amazonSNSClient = awsStackUtil.createSnsClient(region, awsCredential);
        subscribeToTopic(amazonSNSClient, topicArn);
    }

    private void subscribeToTopic(AmazonSNSClient amazonSNSClient, String topicArn) {
        String subscriptionEndpoint = hostAddress + "/sns";
        if (subscriptionEndpoint.startsWith("https")) {
            if (useSslForSns) {
                amazonSNSClient.subscribe(topicArn, "https", subscriptionEndpoint);
            } else {
                subscriptionEndpoint = subscriptionEndpoint.replaceFirst("https", "http");
                amazonSNSClient.subscribe(topicArn, "http", subscriptionEndpoint);
            }
        } else {
            amazonSNSClient.subscribe(topicArn, "http", subscriptionEndpoint);
        }
        LOGGER.info("Amazon SNS subscription request sent. [topic ARN: '{}', endpoint: '{}']", topicArn, subscriptionEndpoint);
    }

    @VisibleForTesting
    protected void setHostAddress(String hostAddress) {
        this.hostAddress = hostAddress;
    }

    @VisibleForTesting
    protected void setUseSslForSns(boolean useSslForSns) {
        this.useSslForSns = useSslForSns;
    }
}
TOP

Related Classes of com.sequenceiq.cloudbreak.service.stack.connector.aws.SnsTopicManager

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.