com.capitalone.dashboard.service.PipelineServiceImpl Maven / Gradle / Ivy
package com.capitalone.dashboard.service;
import com.capitalone.dashboard.misc.HygieiaException;
import com.capitalone.dashboard.settings.ApiSettings;
import com.capitalone.dashboard.model.CollectorItem;
import com.capitalone.dashboard.model.Dashboard;
import com.capitalone.dashboard.model.Pipeline;
import com.capitalone.dashboard.model.PipelineCommit;
import com.capitalone.dashboard.model.PipelineResponse;
import com.capitalone.dashboard.model.PipelineResponseCommit;
import com.capitalone.dashboard.model.PipelineStage;
import com.capitalone.dashboard.model.PipelineStageType;
import com.capitalone.dashboard.repository.CollectorItemRepository;
import com.capitalone.dashboard.repository.DashboardRepository;
import com.capitalone.dashboard.repository.PipelineRepository;
import com.capitalone.dashboard.request.PipelineSearchRequest;
import com.capitalone.dashboard.util.PipelineUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@Service("pipeline")
public class PipelineServiceImpl implements PipelineService {
private static final int PROD_COMMIT_DATE_RANGE_DEFAULT = -90;
private final PipelineRepository pipelineRepository;
private final DashboardRepository dashboardRepository;
private final CollectorItemRepository collectorItemRepository;
private final ApiSettings settings;
@Autowired
public PipelineServiceImpl(PipelineRepository pipelineRepository, DashboardRepository dashboardRepository, CollectorItemRepository collectorItemRepository,
ApiSettings settings) {
this.pipelineRepository = pipelineRepository;
this.dashboardRepository = dashboardRepository;
this.collectorItemRepository = collectorItemRepository;
this.settings = settings;
}
@Override
public Iterable search(PipelineSearchRequest searchRequest) throws HygieiaException {
List pipelineResponses = new ArrayList<>();
for(ObjectId collectorItemId : searchRequest.getCollectorItemId()){
Pipeline pipeline = getOrCreatePipeline(collectorItemId);
pipelineResponses.add(buildPipelineResponse(pipeline, searchRequest.getBeginDate(), searchRequest.getEndDate()));
}
return pipelineResponses;
}
protected Pipeline getOrCreatePipeline(ObjectId collectorItemId) {
Pipeline pipeline = pipelineRepository.findByCollectorItemId(collectorItemId);
if(pipeline == null){
pipeline = new Pipeline();
pipeline.setCollectorItemId(collectorItemId);
pipelineRepository.save(pipeline);
}
return pipeline;
}
private PipelineResponse buildPipelineResponse(Pipeline pipeline, Long beginDate, Long endDate) throws HygieiaException {
Long lowerBound = beginDate;
if(beginDate == null){
Calendar cal = new GregorianCalendar();
cal.setTime(new Date());
cal.add(Calendar.DAY_OF_MONTH, PROD_COMMIT_DATE_RANGE_DEFAULT);
lowerBound = cal.getTime().getTime();
}
Long upperBound = endDate != null ? endDate : new Date().getTime();
/**
* get the collector item and dashboard
*/
CollectorItem dashboardCollectorItem = collectorItemRepository.findOne(pipeline.getCollectorItemId());
if(dashboardCollectorItem.getOptions().get("dashboardId") == null) {
throw new HygieiaException(" Collector Item: " + dashboardCollectorItem.getId() + " is not associated to a dashboard. ", HygieiaException.BAD_DATA);
}
String dashboardId = (String) dashboardCollectorItem.getOptions().get("dashboardId");
Dashboard dashboard = dashboardRepository.findOne(new ObjectId(dashboardId));
if(dashboard == null) {
throw new HygieiaException(" Dashboard " + dashboardId + " is not found for collectorItem: " + dashboardCollectorItem.getId() + " ", HygieiaException.BAD_DATA);
}
PipelineResponse pipelineResponse = new PipelineResponse();
pipelineResponse.setCollectorItemId(dashboardCollectorItem.getId());
pipelineResponse.setProdStage(PipelineUtils.getProdStage(dashboard));
pipelineResponse.setOrderMap(PipelineUtils.getOrderForStages(dashboard));
/**
* iterate over the pipeline stages
* **/
Map stageToEnvironmentNameMap = PipelineUtils.getStageToEnvironmentNameMap(dashboard);
List pipelineStageList = new ArrayList<>();
for (PipelineStage pl : stageToEnvironmentNameMap.keySet()) {
pipelineStageList.add(pl);
}
Map orderMap = pipelineResponse.getOrderMap();
for (Map.Entry entry : orderMap.entrySet())
{
String stageName = entry.getValue();
for(PipelineStage stage : pipelineStageList){
if(stageName.equalsIgnoreCase(stage.getName())) {
List commitsForStage = findNotPropagatedCommits(dashboard, pipeline, stage, pipelineStageList,orderMap);
pipelineResponse.setStageCommits(stage, commitsForStage);
/**
* remove prod commits outside of filter date range
*/
Iterator commitIterator = commitsForStage.iterator();
while (commitIterator.hasNext()) {
PipelineResponseCommit commit = commitIterator.next();
if (!isBetween(commit.getProcessedTimestamps().get(stage.getName()), lowerBound, upperBound)) {
commitIterator.remove();
}
}
}
}
}
pipelineResponse.setUnmappedStages(findUnmappedStages(dashboard,pipelineStageList)
.stream().map(it -> it.getName()).collect(Collectors.toList()));
return pipelineResponse;
}
/**
* finds any stages for a dashboard that aren't mapped.
* @param dashboard
* @return a list of deploy PipelineStages that are not mapped
*/
private List findUnmappedStages(Dashboard dashboard,List pipelineStageList) throws HygieiaException {
List unmappedStages = new ArrayList<>();
Map stageToEnvironmentNameMap = PipelineUtils.getStageToEnvironmentNameMap(dashboard);
for (PipelineStage systemStage : pipelineStageList) {
if (PipelineStageType.DEPLOY.equals(systemStage.getType())) {
String mappedName = stageToEnvironmentNameMap.get(systemStage);
if (mappedName == null || mappedName.isEmpty()) {
unmappedStages.add(systemStage);
}
}
}
return unmappedStages;
}
/**
* Finds a map of commits for all stages after the current stage
* @param stage
* @param pipeline
* @param dashboard
* @return
*/
private Map getCommitsAfterStage(PipelineStage stage, Pipeline pipeline, Dashboard dashboard,List pipelineStageList,Map orderMap) throws HygieiaException {
Map unionOfAllSets = new HashMap<>();
// get key(ordinal) for stage name
List list = getKeysByValue(orderMap,stage.getName());
int ordinal = Integer.parseInt(list.get(0));
for (int systemStageOrdinal = ordinal+1; systemStageOrdinal < pipelineStageList.size(); ++systemStageOrdinal) {
PipelineStage systemStage = null;
for (Map.Entry entry : orderMap.entrySet()) {
String stageOrder = entry.getKey();
String stageName = entry.getValue();
if(Integer.parseInt(stageOrder) == systemStageOrdinal){
for(PipelineStage currentStage : pipelineStageList){
if(stageName.equalsIgnoreCase(currentStage.getName())){
systemStage = currentStage;
}
}
}
}
Map commits = findCommitsForStage(dashboard, pipeline, systemStage);
unionOfAllSets.putAll(commits);
}
return unionOfAllSets;
}
private List getKeysByValue(Map map, E value) {
return map.entrySet()
.stream()
.filter(entry -> Objects.equals(entry.getValue(), value))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
private boolean isBetween(Long commitTimestamp, Long lowerBound, Long upperBound){
return (lowerBound <= commitTimestamp && commitTimestamp <= upperBound);
}
/**
* For a given commit, will traverse the pipeline and find the time it entered in each stage of the pipeline
* @param commit
* @param dashboard
* @param pipeline
* @return
*/
private PipelineResponseCommit applyStageTimestamps(PipelineResponseCommit commit, Dashboard dashboard, Pipeline pipeline,List pipelineStageList) throws HygieiaException {
PipelineResponseCommit returnCommit = new PipelineResponseCommit(commit);
for(PipelineStage systemStage : pipelineStageList) {
//get commits for a given stage
Map commitMap = findCommitsForStage(dashboard, pipeline, systemStage);
//if this commit doesnt have a processed timestamp for this stage, add one
PipelineCommit pipelineCommit = commitMap.get(commit.getScmRevisionNumber());
if(pipelineCommit != null && !returnCommit.getProcessedTimestamps().containsKey(systemStage.getName())){
Long timestamp = pipelineCommit.getTimestamp();
returnCommit.addNewPipelineProcessedTimestamp(systemStage, timestamp);
}
}
return returnCommit;
}
/**
* Gets all commits for a given pipeline stage, taking into account the mappings for environment stages
* @param dashboard
* @param pipeline
* @param stage
* @return
*/
private Map findCommitsForStage(Dashboard dashboard, Pipeline pipeline, PipelineStage stage) throws HygieiaException {
Map commitMap = new HashMap<>();
String pseudoEnvironmentName =
PipelineStage.COMMIT.equals(stage) || PipelineStage.BUILD.equals(stage)? stage.getName() :
PipelineUtils.getStageToEnvironmentNameMap(dashboard).get(stage);
if(pseudoEnvironmentName != null){
commitMap = pipeline.getCommitsByEnvironmentName(pseudoEnvironmentName);
}
return commitMap;
}
/**
* get the commits for a given stage by finding which commits havent passed to a later stage
* @param dashboard dashboard
* @param pipeline pipeline for that dashboard
* @param stage current stage
* @return a list of all commits as pipeline response commits that havent moved past the current stage
*/
public List findNotPropagatedCommits(Dashboard dashboard, Pipeline pipeline, PipelineStage stage,List pipelineStageList,Map orderMap) throws HygieiaException {
Map startingStage = findCommitsForStage(dashboard, pipeline, stage);
Map commitsInLaterStages = getCommitsAfterStage(stage, pipeline, dashboard,pipelineStageList,orderMap);
List notPropagatedCommits = new ArrayList<>();
for(Map.Entry entry : startingStage.entrySet()){
if(!commitsInLaterStages.containsKey(entry.getKey())) {
PipelineResponseCommit commit = applyStageTimestamps(new PipelineResponseCommit((PipelineCommit) entry.getValue()), dashboard, pipeline, pipelineStageList);
notPropagatedCommits.add(commit);
}
}
return notPropagatedCommits;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy