package com.ctrip.framework.apollo.portal.service;
import com.google.common.base.Objects;
import com.google.gson.Gson;
import com.ctrip.framework.apollo.common.constants.GsonType;
import com.ctrip.framework.apollo.common.dto.ItemChangeSets;
import com.ctrip.framework.apollo.common.dto.ReleaseDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.constant.CatEventType;
import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel;
import com.ctrip.framework.apollo.portal.entity.bo.KVEntity;
import com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult;
import com.ctrip.framework.apollo.portal.entity.bo.ReleaseBO;
import com.ctrip.framework.apollo.portal.enums.ChangeType;
import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
import com.ctrip.framework.apollo.tracer.Tracer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Service
public class ReleaseService {
private static final Gson gson = new Gson();
@Autowired
private UserInfoHolder userInfoHolder;
@Autowired
private AdminServiceAPI.ReleaseAPI releaseAPI;
public ReleaseDTO publish(NamespaceReleaseModel model) {
Env env = model.getEnv();
boolean isEmergencyPublish = model.isEmergencyPublish();
String appId = model.getAppId();
String clusterName = model.getClusterName();
String namespaceName = model.getNamespaceName();
String releaseBy = StringUtils.isEmpty(model.getReleasedBy()) ?
userInfoHolder.getUser().getUserId() : model.getReleasedBy();
ReleaseDTO releaseDTO = releaseAPI.createRelease(appId, env, clusterName, namespaceName,
model.getReleaseTitle(), model.getReleaseComment(),
releaseBy, isEmergencyPublish);
Tracer.logEvent(CatEventType.RELEASE_NAMESPACE,
String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName));
return releaseDTO;
}
public ReleaseDTO updateAndPublish(String appId, Env env, String clusterName, String namespaceName,
String releaseTitle, String releaseComment, String branchName,
boolean isEmergencyPublish, boolean deleteBranch, ItemChangeSets changeSets) {
return releaseAPI.updateAndPublish(appId, env, clusterName, namespaceName, releaseTitle, releaseComment, branchName,
isEmergencyPublish, deleteBranch, changeSets);
}
public List<ReleaseBO> findAllReleases(String appId, Env env, String clusterName, String namespaceName, int page,
int size) {
List<ReleaseDTO> releaseDTOs = releaseAPI.findAllReleases(appId, env, clusterName, namespaceName, page, size);
if (CollectionUtils.isEmpty(releaseDTOs)) {
return Collections.emptyList();
}
List<ReleaseBO> releases = new LinkedList<>();
for (ReleaseDTO releaseDTO : releaseDTOs) {
ReleaseBO release = new ReleaseBO();
release.setBaseInfo(releaseDTO);
Set<KVEntity> kvEntities = new LinkedHashSet<>();
Map<String, String> configurations = gson.fromJson(releaseDTO.getConfigurations(), GsonType.CONFIG);
Set<Map.Entry<String, String>> entries = configurations.entrySet();
for (Map.Entry<String, String> entry : entries) {
kvEntities.add(new KVEntity(entry.getKey(), entry.getValue()));
}
release.setItems(kvEntities);
//为了减少数据量
releaseDTO.setConfigurations("");
releases.add(release);
}
return releases;
}
public List<ReleaseDTO> findActiveReleases(String appId, Env env, String clusterName, String namespaceName, int page,
int size) {
return releaseAPI.findActiveReleases(appId, env, clusterName, namespaceName, page, size);
}
public ReleaseDTO findReleaseById(Env env, long releaseId) {
Set<Long> releaseIds = new HashSet<>(1);
releaseIds.add(releaseId);
List<ReleaseDTO> releases = findReleaseByIds(env, releaseIds);
if (CollectionUtils.isEmpty(releases)) {
return null;
} else {
return releases.get(0);
}
}
public List<ReleaseDTO> findReleaseByIds(Env env, Set<Long> releaseIds) {
return releaseAPI.findReleaseByIds(env, releaseIds);
}
public ReleaseDTO loadLatestRelease(String appId, Env env, String clusterName, String namespaceName) {
return releaseAPI.loadLatestRelease(appId, env, clusterName, namespaceName);
}
public void rollback(Env env, long releaseId) {
releaseAPI.rollback(env, releaseId, userInfoHolder.getUser().getUserId());
}
public ReleaseCompareResult compare(Env env, long baseReleaseId, long toCompareReleaseId) {
ReleaseDTO baseRelease = null;
ReleaseDTO toCompareRelease = null;
if (baseReleaseId != 0) {
baseRelease = releaseAPI.loadRelease(env, baseReleaseId);
}
if (toCompareReleaseId != 0) {
toCompareRelease = releaseAPI.loadRelease(env, toCompareReleaseId);
}
return compare(baseRelease, toCompareRelease);
}
public ReleaseCompareResult compare(ReleaseDTO baseRelease, ReleaseDTO toCompareRelease) {
Map<String, String> baseReleaseConfiguration = baseRelease == null ? new HashMap<>() :
gson.fromJson(baseRelease.getConfigurations(), GsonType.CONFIG);
Map<String, String> toCompareReleaseConfiguration = toCompareRelease == null ? new HashMap<>() :
gson.fromJson(toCompareRelease.getConfigurations(),
GsonType.CONFIG);
ReleaseCompareResult compareResult = new ReleaseCompareResult();
//added and modified in firstRelease
for (Map.Entry<String, String> entry : baseReleaseConfiguration.entrySet()) {
String key = entry.getKey();
String firstValue = entry.getValue();
String secondValue = toCompareReleaseConfiguration.get(key);
//added
if (secondValue == null) {
compareResult.addEntityPair(ChangeType.DELETED, new KVEntity(key, firstValue),
new KVEntity(key, null));
} else if (!Objects.equal(firstValue, secondValue)) {
compareResult.addEntityPair(ChangeType.MODIFIED, new KVEntity(key, firstValue),
new KVEntity(key, secondValue));
}
}
//deleted in firstRelease
for (Map.Entry<String, String> entry : toCompareReleaseConfiguration.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (baseReleaseConfiguration.get(key) == null) {
compareResult
.addEntityPair(ChangeType.ADDED, new KVEntity(key, ""), new KVEntity(key, value));
}
}
return compareResult;
}
}