Commit f5218b17 by lepdou

link namespace show public namespace's item & refactor bean & improve log

parent b6996c0a
......@@ -78,4 +78,15 @@ public class NamespaceController {
return BeanUtils.transfrom(NamespaceDTO.class, namespace);
}
@RequestMapping("/clusters/{clusterName}/namespaces/{namespaceName}/public")
public NamespaceDTO findPublicNamespace(@PathVariable String clusterName,
@PathVariable String namespaceName) {
Namespace namespace = namespaceService.findPublicNamespace(clusterName, namespaceName);
if (namespace == null) {
throw new NotFoundException(String.format("public namespace not found. namespace:%s", namespaceName));
}
return BeanUtils.transfrom(NamespaceDTO.class, namespace);
}
}
......@@ -6,8 +6,10 @@ import com.ctrip.framework.apollo.biz.entity.Namespace;
import com.ctrip.framework.apollo.biz.repository.NamespaceRepository;
import com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.exception.ServiceException;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.core.ConfigConsts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -57,6 +59,23 @@ public class NamespaceService {
namespaceName);
}
public Namespace findPublicNamespace(String clusterName, String namespaceName) {
AppNamespace appNamespace = appNamespaceService.findPublicNamespaceByName(namespaceName);
if (appNamespace == null) {
throw new BadRequestException("namespace not exist");
}
String appId = appNamespace.getAppId();
Namespace namespace = findOne(appId, clusterName, namespaceName);
if (namespace == null) {
namespace = findOne(appId, ConfigConsts.CLUSTER_NAME_DEFAULT, namespaceName);
}
return namespace;
}
public List<Namespace> findNamespaces(String appId, String clusterName) {
List<Namespace> namespaces = namespaceRepository.findByAppIdAndClusterNameOrderByIdAsc(appId, clusterName);
if (namespaces == null) {
......
......@@ -12,7 +12,8 @@ import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenReleaseDTO;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO;
import com.ctrip.framework.apollo.portal.entity.bo.ItemBO;
import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;
import org.springframework.util.CollectionUtils;
......@@ -51,22 +52,22 @@ public class OpenApiBeanUtils {
return openReleaseDTO;
}
public static OpenNamespaceDTO transformFromNamespaceVO(NamespaceVO namespaceVO) {
Preconditions.checkArgument(namespaceVO != null);
public static OpenNamespaceDTO transformFromNamespaceBO(NamespaceBO namespaceBO) {
Preconditions.checkArgument(namespaceBO != null);
OpenNamespaceDTO openNamespaceDTO = BeanUtils.transfrom(OpenNamespaceDTO.class, namespaceVO
OpenNamespaceDTO openNamespaceDTO = BeanUtils.transfrom(OpenNamespaceDTO.class, namespaceBO
.getBaseInfo());
//app namespace info
openNamespaceDTO.setFormat(namespaceVO.getFormat());
openNamespaceDTO.setComment(namespaceVO.getComment());
openNamespaceDTO.setPublic(namespaceVO.isPublic());
openNamespaceDTO.setFormat(namespaceBO.getFormat());
openNamespaceDTO.setComment(namespaceBO.getComment());
openNamespaceDTO.setPublic(namespaceBO.isPublic());
//items
List<OpenItemDTO> items = new LinkedList<>();
List<NamespaceVO.ItemVO> itemVOs = namespaceVO.getItems();
if (!CollectionUtils.isEmpty(itemVOs)) {
items.addAll(itemVOs.stream().map(itemVO -> transformFromItemDTO(itemVO.getItem())).collect
List<ItemBO> itemBOs = namespaceBO.getItems();
if (!CollectionUtils.isEmpty(itemBOs)) {
items.addAll(itemBOs.stream().map(itemBO -> transformFromItemDTO(itemBO.getItem())).collect
(Collectors.toList()));
}
openNamespaceDTO.setItems(items);
......@@ -74,14 +75,14 @@ public class OpenApiBeanUtils {
}
public static List<OpenNamespaceDTO> batchTransformFromNamespaceVOs(List<NamespaceVO>
namespaceVOs) {
if (CollectionUtils.isEmpty(namespaceVOs)) {
public static List<OpenNamespaceDTO> batchTransformFromNamespaceBOs(List<NamespaceBO>
namespaceBOs) {
if (CollectionUtils.isEmpty(namespaceBOs)) {
return Collections.emptyList();
}
List<OpenNamespaceDTO> openNamespaceDTOs =
namespaceVOs.stream().map(OpenApiBeanUtils::transformFromNamespaceVO)
namespaceBOs.stream().map(OpenApiBeanUtils::transformFromNamespaceBO)
.collect(Collectors.toCollection(LinkedList::new));
return openNamespaceDTOs;
......
......@@ -7,7 +7,7 @@ import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO;
import com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO;
import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;
import com.ctrip.framework.apollo.portal.service.NamespaceLockService;
import com.ctrip.framework.apollo.portal.service.NamespaceService;
......@@ -33,7 +33,7 @@ public class NamespaceController {
@PathVariable String clusterName) {
return OpenApiBeanUtils
.batchTransformFromNamespaceVOs(namespaceService.findNamespaces(appId, Env
.batchTransformFromNamespaceBOs(namespaceService.findNamespaceBOs(appId, Env
.fromString(env), clusterName));
}
......@@ -41,12 +41,12 @@ public class NamespaceController {
public OpenNamespaceDTO loadNamespace(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String
namespaceName) {
NamespaceVO namespaceVO = namespaceService.loadNamespace(appId, Env.fromString
NamespaceBO namespaceBO = namespaceService.loadNamespaceBO(appId, Env.fromString
(env), clusterName, namespaceName);
if (namespaceVO == null) {
if (namespaceBO == null) {
return null;
}
return OpenApiBeanUtils.transformFromNamespaceVO(namespaceVO);
return OpenApiBeanUtils.transformFromNamespaceBO(namespaceBO);
}
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock", method = RequestMethod.GET)
......
......@@ -71,12 +71,16 @@ public class AdminServiceAPI {
public NamespaceDTO loadNamespace(String appId, Env env, String clusterName,
String namespaceName) {
NamespaceDTO dto =
return
restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}",
NamespaceDTO.class, appId, clusterName, namespaceName);
return dto;
}
public NamespaceDTO loadPublicNamespace(Env env, String clusterName, String namespaceName) {
return
restTemplate.get(env, "/clusters/{clusterName}/namespaces/{namespaceName}/public",
NamespaceDTO.class, clusterName, namespaceName);
}
public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace) {
return restTemplate
......@@ -378,23 +382,26 @@ public class AdminServiceAPI {
public static class ReleaseHistoryAPI extends API {
private ParameterizedTypeReference<PageDTO<ReleaseHistoryDTO>> type =
new ParameterizedTypeReference<PageDTO<ReleaseHistoryDTO>>() {};
new ParameterizedTypeReference<PageDTO<ReleaseHistoryDTO>>() {
};
public PageDTO<ReleaseHistoryDTO> findReleaseHistoriesByNamespace(String appId, Env env, String clusterName,
String namespaceName, int page, int size) {
String namespaceName, int page, int size) {
return restTemplate.get(env,
"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/histories?page={page}&size={size}",
type, appId, clusterName, namespaceName, page, size).getBody();
}
public PageDTO<ReleaseHistoryDTO> findByReleaseIdAndOperation(Env env, long releaseId, int operation, int page, int size) {
public PageDTO<ReleaseHistoryDTO> findByReleaseIdAndOperation(Env env, long releaseId, int operation, int page,
int size) {
return restTemplate.get(env,
"/releases/histories/by_release_id_and_operation?releaseId={releaseId}&operation={operation}&page={page}&size={size}",
type, releaseId, operation, page, size).getBody();
}
public PageDTO<ReleaseHistoryDTO> findByPreviousReleaseIdAndOperation(Env env, long previousReleaseId, int operation, int page, int size) {
public PageDTO<ReleaseHistoryDTO> findByPreviousReleaseIdAndOperation(Env env, long previousReleaseId,
int operation, int page, int size) {
return restTemplate.get(env,
"/releases/histories/by_previous_release_id_and_operation?previousReleaseId={releaseId}&operation={operation}&page={page}&size={size}",
type, previousReleaseId, operation, page, size).getBody();
......
package com.ctrip.framework.apollo.portal.components;
import com.ctrip.framework.apollo.core.MetaDomainConsts;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
......@@ -110,13 +111,15 @@ public class PortalSettings {
logger.info("Env revived because env health check success. env: {}", env);
}
} else {
logger.warn("Env health check failed, maybe because of admin server down. env: {}", env);
logger.error("Env health check failed, maybe because of admin server down. env: {}, meta server address: {}", env,
MetaDomainConsts.getDomain(env));
handleEnvDown(env);
}
} catch (Exception e) {
logger.warn("Env health check failed, maybe because of meta server down "
+ "or config error meta server address. env: {}", env);
logger.error("Env health check failed, maybe because of meta server down "
+ "or configure wrong meta server address. env: {}, meta server address: {}", env,
MetaDomainConsts.getDomain(env), e);
handleEnvDown(env);
}
}
......@@ -133,15 +136,18 @@ public class PortalSettings {
healthCheckFailedCounter.put(env, ++failedTimes);
if (!envStatusMark.get(env)) {
logger.error("Env is down. env: {}, failed times: {}", env, failedTimes);
logger.error("Env is down. env: {}, failed times: {}, meta server address: {}", env, failedTimes,
MetaDomainConsts.getDomain(env));
} else {
if (failedTimes >= ENV_DOWN_THRESHOLD) {
envStatusMark.put(env, false);
logger.error("Env is down because health check failed for {} times, "
+ "which equals to down threshold. env: {}", ENV_DOWN_THRESHOLD, env);
+ "which equals to down threshold. env: {}, meta server address: {}", ENV_DOWN_THRESHOLD, env,
MetaDomainConsts.getDomain(env));
} else {
logger.warn("Env health check failed for {} times which less than down threshold. down threshold:{}, env: {}",
failedTimes, ENV_DOWN_THRESHOLD, env);
logger.error(
"Env health check failed for {} times which less than down threshold. down threshold:{}, env: {}, meta server address: {}",
failedTimes, ENV_DOWN_THRESHOLD, env, MetaDomainConsts.getDomain(env));
}
}
......
package com.ctrip.framework.apollo.portal.components;
import com.ctrip.framework.apollo.common.exception.ServiceException;
import com.ctrip.framework.apollo.core.MetaDomainConsts;
import com.ctrip.framework.apollo.core.dto.ServiceDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.constant.CatEventType;
......@@ -109,7 +110,9 @@ public class RetryableRestTemplate {
}
//all admin server down
ServiceException e = new ServiceException("No available admin service");
ServiceException e =
new ServiceException(String.format("Admin servers are unresponsive. meta server address: %s, admin servers: %s",
MetaDomainConsts.getDomain(env), services));
ct.setStatus(e);
ct.complete();
throw e;
......@@ -138,9 +141,9 @@ public class RetryableRestTemplate {
} catch (Throwable t) {
logger.error("Http request failed, uri: {}, method: {}", uri, HttpMethod.GET, t);
Tracer.logError(t);
if (canRetry(t, HttpMethod.GET)){
if (canRetry(t, HttpMethod.GET)) {
Tracer.logEvent(CatEventType.API_RETRY, uri);
}else {// biz exception rethrow
} else {// biz exception rethrow
ct.setStatus(t);
ct.complete();
throw t;
......@@ -150,7 +153,9 @@ public class RetryableRestTemplate {
}
//all admin server down
ServiceException e = new ServiceException("No available admin service");
ServiceException e =
new ServiceException(String.format("Admin servers are unresponsive. meta server address: %s, admin servers: %s",
MetaDomainConsts.getDomain(env), services));
ct.setStatus(e);
ct.complete();
throw e;
......@@ -162,7 +167,10 @@ public class RetryableRestTemplate {
List<ServiceDTO> services = adminServiceAddressLocator.getServiceList(env);
if (CollectionUtils.isEmpty(services)) {
ServiceException e = new ServiceException("No available admin service");
ServiceException e = new ServiceException(String.format("No available admin server."
+ " Maybe because of meta server down or all admin server down. "
+ "Meta server address: %s",
MetaDomainConsts.getDomain(env)));
ct.setStatus(e);
ct.complete();
throw e;
......
......@@ -6,7 +6,7 @@ import com.ctrip.framework.apollo.common.dto.ReleaseDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.components.PermissionValidator;
import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO;
import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;
import com.ctrip.framework.apollo.portal.listener.ConfigPublishEvent;
import com.ctrip.framework.apollo.portal.service.NamespaceBranchService;
import com.ctrip.framework.apollo.portal.service.ReleaseService;
......@@ -35,7 +35,7 @@ public class NamespaceBranchController {
private ApplicationEventPublisher publisher;
@RequestMapping("/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches")
public NamespaceVO findBranch(@PathVariable String appId,
public NamespaceBO findBranch(@PathVariable String appId,
@PathVariable String env,
@PathVariable String clusterName,
@PathVariable String namespaceName) {
......
......@@ -13,7 +13,7 @@ import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.constant.RoleType;
import com.ctrip.framework.apollo.portal.entity.model.NamespaceCreationModel;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO;
import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;
import com.ctrip.framework.apollo.portal.listener.AppNamespaceCreationEvent;
import com.ctrip.framework.apollo.portal.service.AppNamespaceService;
import com.ctrip.framework.apollo.portal.service.AppService;
......@@ -35,6 +35,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
......@@ -67,17 +68,25 @@ public class NamespaceController {
}
@RequestMapping("/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces")
public List<NamespaceVO> findNamespaces(@PathVariable String appId, @PathVariable String env,
public List<NamespaceBO> findNamespaces(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName) {
return namespaceService.findNamespaces(appId, Env.valueOf(env), clusterName);
return namespaceService.findNamespaceBOs(appId, Env.valueOf(env), clusterName);
}
@RequestMapping("/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName:.+}")
public NamespaceVO findNamespaces(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName) {
public NamespaceBO findNamespace(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName) {
return namespaceService.loadNamespace(appId, Env.valueOf(env), clusterName, namespaceName);
return namespaceService.loadNamespaceBO(appId, Env.valueOf(env), clusterName, namespaceName);
}
@RequestMapping("/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/public")
public NamespaceBO findPublicNamespace(@PathVariable String env,
@PathVariable String namespaceName,
@PathVariable String clusterName) {
return namespaceService.loadPublicNamespaceBO(Env.valueOf(env), clusterName, namespaceName);
}
@PreAuthorize(value = "@permissionValidator.hasCreateNamespacePermission(#appId)")
......
......@@ -5,7 +5,7 @@ import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel;
import com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult;
import com.ctrip.framework.apollo.portal.entity.vo.ReleaseVO;
import com.ctrip.framework.apollo.portal.entity.bo.ReleaseBO;
import com.ctrip.framework.apollo.portal.listener.ConfigPublishEvent;
import com.ctrip.framework.apollo.portal.service.ReleaseService;
......@@ -89,7 +89,7 @@ public class ReleaseController {
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases/all")
public List<ReleaseVO> findAllReleases(@PathVariable String appId,
public List<ReleaseBO> findAllReleases(@PathVariable String appId,
@PathVariable String env,
@PathVariable String clusterName,
@PathVariable String namespaceName,
......
package com.ctrip.framework.apollo.portal.entity.bo;
import com.ctrip.framework.apollo.common.dto.ItemDTO;
public class ItemBO {
private ItemDTO item;
private boolean isModified;
private boolean isDeleted;
private String oldValue;
private String newValue;
public ItemDTO getItem() {
return item;
}
public void setItem(ItemDTO item) {
this.item = item;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
public boolean isModified() {
return isModified;
}
public void setModified(boolean isModified) {
this.isModified = isModified;
}
public String getOldValue() {
return oldValue;
}
public void setOldValue(String oldValue) {
this.oldValue = oldValue;
}
public String getNewValue() {
return newValue;
}
public void setNewValue(String newValue) {
this.newValue = newValue;
}
}
package com.ctrip.framework.apollo.portal.entity.vo;
package com.ctrip.framework.apollo.portal.entity.bo;
public class KVEntity {
......
package com.ctrip.framework.apollo.portal.entity.vo;
package com.ctrip.framework.apollo.portal.entity.bo;
import com.ctrip.framework.apollo.common.dto.ItemDTO;
import com.ctrip.framework.apollo.common.dto.NamespaceDTO;
import java.util.List;
public class NamespaceVO {
public class NamespaceBO {
private NamespaceDTO baseInfo;
private int itemModifiedCnt;
private List<ItemVO> items;
private List<ItemBO> items;
private String format;
private boolean isPublic;
private String parentAppId;
......@@ -31,11 +30,11 @@ public class NamespaceVO {
this.itemModifiedCnt = itemModifiedCnt;
}
public List<ItemVO> getItems() {
public List<ItemBO> getItems() {
return items;
}
public void setItems(List<ItemVO> items) {
public void setItems(List<ItemBO> items) {
this.items = items;
}
......@@ -71,54 +70,4 @@ public class NamespaceVO {
this.comment = comment;
}
public static class ItemVO {
private ItemDTO item;
private boolean isModified;
private boolean isDeleted;
private String oldValue;
private String newValue;
public ItemDTO getItem() {
return item;
}
public void setItem(ItemDTO item) {
this.item = item;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
public boolean isModified() {
return isModified;
}
public void setModified(boolean isModified) {
this.isModified = isModified;
}
public String getOldValue() {
return oldValue;
}
public void setOldValue(String oldValue) {
this.oldValue = oldValue;
}
public String getNewValue() {
return newValue;
}
public void setNewValue(String newValue) {
this.newValue = newValue;
}
}
}
package com.ctrip.framework.apollo.portal.entity.vo;
package com.ctrip.framework.apollo.portal.entity.bo;
import com.ctrip.framework.apollo.common.dto.ReleaseDTO;
import com.ctrip.framework.apollo.portal.entity.bo.KVEntity;
import java.util.Set;
public class ReleaseVO {
public class ReleaseBO {
private ReleaseDTO baseInfo;
......
package com.ctrip.framework.apollo.portal.entity.vo;
import com.ctrip.framework.apollo.common.entity.EntityPair;
import com.ctrip.framework.apollo.portal.entity.bo.KVEntity;
import com.ctrip.framework.apollo.portal.enums.ChangeType;
public class Change {
......
package com.ctrip.framework.apollo.portal.entity.vo;
import com.ctrip.framework.apollo.common.entity.EntityPair;
import com.ctrip.framework.apollo.portal.entity.bo.KVEntity;
import com.ctrip.framework.apollo.portal.enums.ChangeType;
import java.util.LinkedList;
......
......@@ -11,7 +11,7 @@ import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.components.ItemsComparator;
import com.ctrip.framework.apollo.portal.components.PermissionValidator;
import com.ctrip.framework.apollo.portal.constant.CatEventType;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO;
import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;
import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
import com.ctrip.framework.apollo.tracer.Tracer;
......@@ -100,7 +100,7 @@ public class NamespaceBranchService {
private ItemChangeSets calculateBranchChangeSet(String appId, Env env, String clusterName, String namespaceName,
String branchName) {
NamespaceVO parentNamespace = namespaceService.loadNamespace(appId, env, clusterName, namespaceName);
NamespaceBO parentNamespace = namespaceService.loadNamespaceBO(appId, env, clusterName, namespaceName);
if (parentNamespace == null) {
throw new BadRequestException("base namespace not existed");
......@@ -125,12 +125,12 @@ public class NamespaceBranchService {
return namespaceBranchAPI.findBranch(appId, env, clusterName, namespaceName);
}
public NamespaceVO findBranch(String appId, Env env, String clusterName, String namespaceName) {
public NamespaceBO findBranch(String appId, Env env, String clusterName, String namespaceName) {
NamespaceDTO namespaceDTO = findBranchBaseInfo(appId, env, clusterName, namespaceName);
if (namespaceDTO == null) {
return null;
}
return namespaceService.loadNamespace(appId, env, namespaceDTO.getClusterName(), namespaceName);
return namespaceService.loadNamespaceBO(appId, env, namespaceDTO.getClusterName(), namespaceName);
}
}
package com.ctrip.framework.apollo.portal.service;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ctrip.framework.apollo.common.constants.GsonType;
import com.ctrip.framework.apollo.common.dto.ItemDTO;
import com.ctrip.framework.apollo.common.dto.NamespaceDTO;
import com.ctrip.framework.apollo.common.dto.ReleaseDTO;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
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.vo.NamespaceVO;
import com.ctrip.framework.apollo.portal.entity.bo.ItemBO;
import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;
import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
import com.ctrip.framework.apollo.tracer.Tracer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.HttpClientErrorException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
......@@ -35,8 +38,6 @@ public class NamespaceService {
private Logger logger = LoggerFactory.getLogger(NamespaceService.class);
private Gson gson = new Gson();
private static Type mapType = new TypeToken<Map<String, String>>() {
}.getType();
@Autowired
private UserInfoHolder userInfoHolder;
......@@ -58,8 +59,8 @@ public class NamespaceService {
NamespaceDTO createdNamespace = namespaceAPI.createNamespace(env, namespace);
Tracer.logEvent(CatEventType.CREATE_NAMESPACE,
String.format("%s+%s+%s+%s", namespace.getAppId(), env, namespace.getClusterName(),
namespace.getNamespaceName()));
String.format("%s+%s+%s+%s", namespace.getAppId(), env, namespace.getClusterName(),
namespace.getNamespaceName()));
return createdNamespace;
}
......@@ -68,7 +69,7 @@ public class NamespaceService {
public void deleteNamespace(String appId, Env env, String clusterName, String namespaceName) {
AppNamespace appNamespace = appNamespaceService.findByAppIdAndName(appId, namespaceName);
if (appNamespace != null && !appNamespace.isPublic()){
if (appNamespace != null && !appNamespace.isPublic()) {
throw new BadRequestException("private namespace can not be deleted");
}
......@@ -89,20 +90,20 @@ public class NamespaceService {
/**
* load cluster all namespace info with items
*/
public List<NamespaceVO> findNamespaces(String appId, Env env, String clusterName) {
public List<NamespaceBO> findNamespaceBOs(String appId, Env env, String clusterName) {
List<NamespaceDTO> namespaces = namespaceAPI.findNamespaceByCluster(appId, env, clusterName);
if (namespaces == null || namespaces.size() == 0) {
throw new BadRequestException("namespaces not exist");
}
List<NamespaceVO> namespaceVOs = new LinkedList<>();
List<NamespaceBO> namespaceBOs = new LinkedList<>();
for (NamespaceDTO namespace : namespaces) {
NamespaceVO namespaceVO = null;
NamespaceBO namesapceBO = null;
try {
namespaceVO = parseNamespace(appId, env, clusterName, namespace);
namespaceVOs.add(namespaceVO);
namesapceBO = transformNamespace2BO(appId, env, clusterName, namespace);
namespaceBOs.add(namesapceBO);
} catch (Exception e) {
logger.error("parse namespace error. app id:{}, env:{}, clusterName:{}, namespace:{}",
appId, env, clusterName, namespace.getNamespaceName(), e);
......@@ -110,25 +111,34 @@ public class NamespaceService {
}
}
return namespaceVOs;
return namespaceBOs;
}
public NamespaceVO loadNamespace(String appId, Env env, String clusterName, String namespaceName) {
public NamespaceBO loadNamespaceBO(String appId, Env env, String clusterName, String namespaceName) {
NamespaceDTO namespace = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName);
if (namespace == null) {
throw new BadRequestException("namespaces not exist");
}
return parseNamespace(appId, env, clusterName, namespace);
return transformNamespace2BO(appId, env, clusterName, namespace);
}
private NamespaceVO parseNamespace(String appId, Env env, String clusterName, NamespaceDTO namespace) {
NamespaceVO namespaceVO = new NamespaceVO();
namespaceVO.setBaseInfo(namespace);
public NamespaceBO loadPublicNamespaceBO(Env env, String clusterName, String namespaceName) {
NamespaceDTO namespace = namespaceAPI.loadPublicNamespace(env, clusterName, namespaceName);
fillAppNamespaceProperties(namespaceVO);
String appId = namespace.getAppId();
String actualClusterName = namespace.getClusterName();
List<NamespaceVO.ItemVO> itemVos = new LinkedList<>();
namespaceVO.setItems(itemVos);
return transformNamespace2BO(appId, env, actualClusterName, namespace);
}
private NamespaceBO transformNamespace2BO(String appId, Env env, String clusterName, NamespaceDTO namespace) {
NamespaceBO namespaceBO = new NamespaceBO();
namespaceBO.setBaseInfo(namespace);
fillAppNamespaceProperties(namespaceBO);
List<ItemBO> itemBOs = new LinkedList<>();
namespaceBO.setItems(itemBOs);
String namespaceName = namespace.getNamespaceName();
......@@ -137,7 +147,7 @@ public class NamespaceService {
Map<String, String> releaseItems = new HashMap<>();
latestRelease = releaseService.loadLatestRelease(appId, env, clusterName, namespaceName);
if (latestRelease != null) {
releaseItems = gson.fromJson(latestRelease.getConfigurations(), mapType);
releaseItems = gson.fromJson(latestRelease.getConfigurations(), GsonType.CONFIG);
}
//not Release config items
......@@ -145,26 +155,26 @@ public class NamespaceService {
int modifiedItemCnt = 0;
for (ItemDTO itemDTO : items) {
NamespaceVO.ItemVO itemVO = parseItemVO(itemDTO, releaseItems);
ItemBO itemBO = transformItem2BO(itemDTO, releaseItems);
if (itemVO.isModified()) {
if (itemBO.isModified()) {
modifiedItemCnt++;
}
itemVos.add(itemVO);
itemBOs.add(itemBO);
}
//deleted items
List<NamespaceVO.ItemVO> deletedItems = parseDeletedItems(items, releaseItems);
itemVos.addAll(deletedItems);
List<ItemBO> deletedItems = parseDeletedItems(items, releaseItems);
itemBOs.addAll(deletedItems);
modifiedItemCnt += deletedItems.size();
namespaceVO.setItemModifiedCnt(modifiedItemCnt);
namespaceBO.setItemModifiedCnt(modifiedItemCnt);
return namespaceVO;
return namespaceBO;
}
private void fillAppNamespaceProperties(NamespaceVO namespace) {
private void fillAppNamespaceProperties(NamespaceBO namespace) {
NamespaceDTO namespaceDTO = namespace.getBaseInfo();
//先从当前appId下面找,包含私有的和公共的
......@@ -190,14 +200,14 @@ public class NamespaceService {
namespace.setPublic(isPublic);
}
private List<NamespaceVO.ItemVO> parseDeletedItems(List<ItemDTO> newItems, Map<String, String> releaseItems) {
private List<ItemBO> parseDeletedItems(List<ItemDTO> newItems, Map<String, String> releaseItems) {
Map<String, ItemDTO> newItemMap = BeanUtils.mapByKey("key", newItems);
List<NamespaceVO.ItemVO> deletedItems = new LinkedList<>();
List<ItemBO> deletedItems = new LinkedList<>();
for (Map.Entry<String, String> entry : releaseItems.entrySet()) {
String key = entry.getKey();
if (newItemMap.get(key) == null) {
NamespaceVO.ItemVO deletedItem = new NamespaceVO.ItemVO();
ItemBO deletedItem = new ItemBO();
deletedItem.setDeleted(true);
ItemDTO deletedItemDto = new ItemDTO();
......@@ -215,19 +225,19 @@ public class NamespaceService {
return deletedItems;
}
private NamespaceVO.ItemVO parseItemVO(ItemDTO itemDTO, Map<String, String> releaseItems) {
private ItemBO transformItem2BO(ItemDTO itemDTO, Map<String, String> releaseItems) {
String key = itemDTO.getKey();
NamespaceVO.ItemVO itemVO = new NamespaceVO.ItemVO();
itemVO.setItem(itemDTO);
ItemBO itemBO = new ItemBO();
itemBO.setItem(itemDTO);
String newValue = itemDTO.getValue();
String oldValue = releaseItems.get(key);
//new item or modified
if (!StringUtils.isEmpty(key) && (oldValue == null || !newValue.equals(oldValue))) {
itemVO.setModified(true);
itemVO.setOldValue(oldValue == null ? "" : oldValue);
itemVO.setNewValue(newValue);
itemBO.setModified(true);
itemBO.setOldValue(oldValue == null ? "" : oldValue);
itemBO.setNewValue(newValue);
}
return itemVO;
return itemBO;
}
}
......@@ -11,9 +11,9 @@ 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.vo.KVEntity;
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.vo.ReleaseVO;
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;
......@@ -65,7 +65,7 @@ public class ReleaseService {
deleteBranch, changeSets);
}
public List<ReleaseVO> findAllReleases(String appId, Env env, String clusterName, String namespaceName, int page,
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);
......@@ -73,9 +73,9 @@ public class ReleaseService {
return Collections.emptyList();
}
List<ReleaseVO> releases = new LinkedList<>();
List<ReleaseBO> releases = new LinkedList<>();
for (ReleaseDTO releaseDTO : releaseDTOs) {
ReleaseVO release = new ReleaseVO();
ReleaseBO release = new ReleaseBO();
release.setBaseInfo(releaseDTO);
Set<KVEntity> kvEntities = new LinkedHashSet<>();
......
......@@ -62,6 +62,7 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer
function (result) {
$scope.namespaces = result;
$('.config-item-container').removeClass('hide');
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "加载配置信息出错");
......@@ -138,10 +139,9 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer
$scope.item = _.clone(toEditItem);
if (namespace.isBranch) {
if (namespace.isBranch || namespace.isLinkedNamespace) {
var existedItem = false;
namespace.items.forEach(function (item) {
//branch items contain the item
if (!item.isDeleted && item.item.key == toEditItem.key) {
existedItem = true;
}
......@@ -270,7 +270,7 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer
$('.config-item-container').removeClass('hide');
new Clipboard('.clipboard');
}
......
......@@ -40,7 +40,6 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
ALL: 'all'
};
var operate_branch_storage_key = 'OperateBranch';
scope.switchView = switchView;
......@@ -101,6 +100,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
initNamespaceLock(namespace);
initNamespaceInstancesCount(namespace);
initPermission(namespace);
initLinkedNamespace(namespace);
function initNamespaceBranch(namespace) {
NamespaceBranchService.findNamespaceBranch(scope.appId, scope.env,
......@@ -221,6 +221,44 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
});
}
function initLinkedNamespace(namespace) {
if (!namespace.isPublic || !namespace.isLinkedNamespace) {
return;
}
//load public namespace
ConfigService.load_public_namespace(scope.env, scope.cluster, namespace.baseInfo.namespaceName)
.then(function (result) {
var publicNamespace = result;
namespace.publicNamespace = publicNamespace;
var linkNamespaceItemKeys = [];
namespace.items.forEach(function (item) {
var key = item.item.key;
linkNamespaceItemKeys.push(key);
});
publicNamespace.viewItems = [];
publicNamespace.items.forEach(function (item) {
var key = item.item.key;
if (key){
publicNamespace.viewItems.push(item);
}
item.covered = linkNamespaceItemKeys.indexOf(key) >= 0;
if (item.isModified || item.isDeleted) {
publicNamespace.isModified = true;
} else if (key){
publicNamespace.hasPublishedItem = true;
}
});
});
}
function initNamespaceViewName(namespace) {
//namespace view name hide suffix
namespace.viewName =
......@@ -270,7 +308,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
switchBranch(operateBranchStorage[namespaceId]);
}
}
function initNamespaceInstancesCount(namespace) {
......@@ -497,11 +535,11 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
scope.namespace.baseInfo.namespaceName,
branch.baseInfo.clusterName)
.then(function (result) {
if (result.appId) {
branch.rules = result;
}
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "加载灰度规则出错");
});
......@@ -684,7 +722,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
namespace.itemCnt = itemCnt;
return result;
}
function toggleItemSearchInput(namespace) {
namespace.showSearchInput = !namespace.showSearchInput;
}
......@@ -727,7 +765,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
var parentNamespace = branch.parentNamespace;
if (!parentNamespace.hasReleasePermission) {
AppUtil.showModal('#releaseNoPermissionDialog');
}else if (branch.lockOwner && scope.user == branch.lockOwner) {
} else if (branch.lockOwner && scope.user == branch.lockOwner) {
AppUtil.showModal('#releaseDenyDialog');
} else if (parentNamespace.itemModifiedCnt > 0) {
AppUtil.showModal('#mergeAndReleaseDenyDialog');
......@@ -741,6 +779,10 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
EventManager.emit(EventManager.EventType.PRE_ROLLBACK_NAMESPACE, {namespace: namespace});
}
setTimeout(function () {
scope.namespace.show = true;
}, 200);
}
}
}
......
......@@ -5,6 +5,11 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
isArray: false,
url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName'
},
load_public_namespace: {
method: 'GET',
isArray: false,
url: '/envs/:env/clusters/:clusterName/namespaces/:namespaceName/public'
},
load_all_namespaces: {
method: 'GET',
isArray: true,
......@@ -58,6 +63,19 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
});
return d.promise;
},
load_public_namespace: function (env, clusterName, namespaceName) {
var d = $q.defer();
config_source.load_public_namespace({
env: env,
clusterName: clusterName,
namespaceName: namespaceName
}, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
load_all_namespaces: function (appId, env, clusterName) {
var d = $q.defer();
config_source.load_all_namespaces({
......
......@@ -98,6 +98,29 @@ appService.service('ReleaseService', ['$resource', '$q', function ($resource, $q
});
return d.promise;
}
function findLatestActiveRelease(appId, env, clusterName, namespaceName) {
var d = $q.defer();
resource.find_active_releases({
appId: appId,
env: env,
clusterName: clusterName,
namespaceName: namespaceName,
page: 0,
size: 1
}, function (result) {
if (result && result.length){
d.resolve(result[0]);
}
d.resolve(undefined);
}, function (result) {
d.reject(result);
});
return d.promise;
}
function compare(env, baseReleaseId, toCompareReleaseId) {
var d = $q.defer();
......@@ -133,6 +156,7 @@ appService.service('ReleaseService', ['$resource', '$q', function ($resource, $q
grayPublish: createGrayRelease,
findAllRelease: findAllReleases,
findActiveReleases: findActiveReleases,
findLatestActiveRelease: findLatestActiveRelease,
compare: compare,
rollback: rollback
}
......
......@@ -50,6 +50,14 @@ p, td, span {
border: solid 1px #c3c3c3;
}
.padding-top-5 {
padding-top: 5px;
}
.border-top {
border-top: 1px solid #ddd;
}
.active {
background: #f5f5f5;
}
......@@ -336,6 +344,7 @@ table th {
.namespace-panel {
border-top: 0;
border-bottom: 0;
}
.namespace-panel .namespace-name {
......@@ -388,6 +397,10 @@ table th {
}
.namespace-panel .no-config-panel {
padding: 15px 0;
}
.namespace-panel .history-view {
padding: 10px 20px;
......@@ -724,4 +737,10 @@ table th {
width: auto !important;
}
.search-onblur {
background: #f5f5f5;
}
.search-focus {
background: #fff;
}
<header class="row namespace-attribute-panel">
<div class="text-center namespace-attribute-public">
<span data-tooltip="tooltip" data-placement="bottom"
title="私有namespace({{namespace.baseInfo.namespaceName}})的配置只能被AppId为{{appId}}的客户端读取到"
ng-show="!namespace.isPublic">私有</span>
<span data-tooltip="tooltip" data-placement="top"
title="namespace({{namespace.baseInfo.namespaceName}})的配置能被任何客户端读取到"
ng-show="namespace.isPublic && namespace.parentAppId == namespace.baseInfo.appId">公共</span>
<span data-tooltip="tooltip" data-placement="top"
title="namespace({{namespace.baseInfo.namespaceName}})的配置将会覆盖公共namespace的配置, 且合并之后的配置只能被AppId为{{appId}}的客户端读取到"
ng-show="namespace.isPublic && namespace.isLinkedNamespace"
ng-click="goToParentAppConfigPage(namespace)">关联</span>
</div>
</header>
<!--branch nav-->
<header class="panel-heading second-panel-heading" ng-show="namespace.hasBranch">
<div class="row">
<div class="col-md-8 pull-left">
<ul class="nav nav-tabs">
<li role="presentation">
<a ng-class="{'node_active': namespace.currentOperateBranch == 'master'}"
ng-click="switchBranch('master')">
<img src="img/branch.png">
主版本
</a>
</li>
<li role="presentation">
<a ng-class="{'node_active': namespace.currentOperateBranch != 'master'}"
ng-click="switchBranch(namespace.branchName)">
<img src="img/branch.png">
灰度版本
</a>
</li>
</ul>
</div>
</div>
</header>
......@@ -8,7 +8,7 @@ import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.components.txtresolver.PropertyResolver;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO;
import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;
import org.junit.Before;
import org.junit.Test;
......@@ -87,9 +87,9 @@ public class NamespaceServiceTest {
when(releaseService.loadLatestRelease(appId, Env.DEV, clusterName, "hermes")).thenReturn(someRelease);
when(itemService.findItems(appId, Env.DEV, clusterName, namespaceName)).thenReturn(someItems);
List<NamespaceVO> namespaceVOs = namespaceService.findNamespaces(appId, Env.DEV, clusterName);
List<NamespaceBO> namespaceVOs = namespaceService.findNamespaceBOs(appId, Env.DEV, clusterName);
assertEquals(2, namespaceVOs.size());
NamespaceVO namespaceVO = namespaceVOs.get(0);
NamespaceBO namespaceVO = namespaceVOs.get(0);
assertEquals(4, namespaceVO.getItems().size());
assertEquals("a", namespaceVO.getItems().get(0).getItem().getKey());
assertEquals(2, namespaceVO.getItemModifiedCnt());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment