com.netflix.spinnaker.clouddriver.aws.provider.agent.AmazonCloudFormationCachingAgent.java Source code

Java tutorial

Introduction

Here is the source code for com.netflix.spinnaker.clouddriver.aws.provider.agent.AmazonCloudFormationCachingAgent.java

Source

/*
 * Copyright (c) 2019 Schibsted Media Group.
 *
 * 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.spinnaker.clouddriver.aws.provider.agent;

import com.amazonaws.services.cloudformation.AmazonCloudFormation;
import com.amazonaws.services.cloudformation.model.*;
import com.amazonaws.services.cloudformation.model.Stack;
import com.netflix.spinnaker.cats.agent.AccountAware;
import com.netflix.spinnaker.cats.agent.AgentDataType;
import com.netflix.spinnaker.cats.agent.CacheResult;
import com.netflix.spinnaker.cats.agent.CachingAgent;
import com.netflix.spinnaker.cats.agent.DefaultCacheResult;
import com.netflix.spinnaker.cats.cache.CacheData;
import com.netflix.spinnaker.cats.cache.DefaultCacheData;
import com.netflix.spinnaker.cats.provider.ProviderCache;
import com.netflix.spinnaker.clouddriver.aws.cache.Keys;
import com.netflix.spinnaker.clouddriver.aws.provider.AwsInfrastructureProvider;
import com.netflix.spinnaker.clouddriver.aws.security.AmazonClientProvider;
import com.netflix.spinnaker.clouddriver.aws.security.NetflixAmazonCredentials;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.stream.Collectors;

import static com.netflix.spinnaker.clouddriver.aws.cache.Keys.Namespace.STACKS;
import static com.netflix.spinnaker.cats.agent.AgentDataType.Authority.AUTHORITATIVE;

@Slf4j
public class AmazonCloudFormationCachingAgent implements CachingAgent, AccountAware {
    private final AmazonClientProvider amazonClientProvider;
    private final NetflixAmazonCredentials account;
    private final String region;

    static final Set<AgentDataType> types = new HashSet<>(
            Collections.singletonList(AUTHORITATIVE.forType(STACKS.getNs())));

    public AmazonCloudFormationCachingAgent(AmazonClientProvider amazonClientProvider,
            NetflixAmazonCredentials account, String region) {
        this.amazonClientProvider = amazonClientProvider;
        this.account = account;
        this.region = region;
    }

    @Override
    public String getProviderName() {
        return AwsInfrastructureProvider.PROVIDER_NAME;
    }

    @Override
    public String getAgentType() {
        return String.format("%s/%s/%s", account.getName(), region,
                AmazonCloudFormationCachingAgent.class.getSimpleName());
    }

    @Override
    public String getAccountName() {
        return account.getName();
    }

    @Override
    public Collection<AgentDataType> getProvidedDataTypes() {
        return types;
    }

    @Override
    public CacheResult loadData(ProviderCache providerCache) {
        log.info("Describing items in {}", getAgentType());
        AmazonCloudFormation cloudformation = amazonClientProvider.getAmazonCloudFormation(account, region);

        Collection<CacheData> stackCacheData = new ArrayList<>();

        try {
            List<Stack> stacks = cloudformation.describeStacks().getStacks();

            for (Stack stack : stacks) {
                Map<String, Object> stackAttributes = new HashMap<>();
                stackAttributes.put("stackId", stack.getStackId());
                stackAttributes.put("tags",
                        stack.getTags().stream().collect(Collectors.toMap(Tag::getKey, Tag::getValue)));
                stackAttributes.put("outputs", stack.getOutputs().stream()
                        .collect(Collectors.toMap(Output::getOutputKey, Output::getOutputValue)));
                stackAttributes.put("stackName", stack.getStackName());
                stackAttributes.put("region", region);
                stackAttributes.put("accountName", account.getName());
                stackAttributes.put("accountId", account.getAccountId());
                stackAttributes.put("stackStatus", stack.getStackStatus());
                stackAttributes.put("creationTime", stack.getCreationTime());

                if (stack.getStackStatus().equals("ROLLBACK_COMPLETE")) {
                    DescribeStackEventsRequest request = new DescribeStackEventsRequest()
                            .withStackName(stack.getStackName());
                    cloudformation.describeStackEvents(request).getStackEvents().stream()
                            .filter(e -> e.getResourceStatus().equals("CREATE_FAILED")).findFirst()
                            .map(StackEvent::getResourceStatusReason)
                            .map(statusReason -> stackAttributes.put("stackStatusReason", statusReason));
                }
                String stackCacheKey = Keys.getCloudFormationKey(stack.getStackId(), region, account.getName());
                Map<String, Collection<String>> relationships = new HashMap<>();
                relationships.put(STACKS.getNs(), Collections.singletonList(stackCacheKey));
                stackCacheData.add(new DefaultCacheData(stackCacheKey, stackAttributes, relationships));
            }
        } catch (AmazonCloudFormationException e) {
            log.error("Error retrieving stacks", e);
        }

        log.info("Caching {} items in {}", stackCacheData.size(), getAgentType());
        HashMap<String, Collection<CacheData>> result = new HashMap<>();
        result.put(STACKS.getNs(), stackCacheData);
        return new DefaultCacheResult(result);
    }
}