Commit 7f6ed42b authored by lepdou's avatar lepdou

release history & 多处优化

parent d13244c8
...@@ -36,18 +36,15 @@ public class ItemController { ...@@ -36,18 +36,15 @@ public class ItemController {
@PreAcquireNamespaceLock @PreAcquireNamespaceLock
@RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.POST) @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.POST)
public ItemDTO createOrUpdate(@PathVariable("appId") String appId, public ItemDTO create(@PathVariable("appId") String appId,
@PathVariable("clusterName") String clusterName, @PathVariable("clusterName") String clusterName,
@PathVariable("namespaceName") String namespaceName, @RequestBody ItemDTO dto) { @PathVariable("namespaceName") String namespaceName, @RequestBody ItemDTO dto) {
Item entity = BeanUtils.transfrom(Item.class, dto); Item entity = BeanUtils.transfrom(Item.class, dto);
ConfigChangeContentBuilder builder = new ConfigChangeContentBuilder(); ConfigChangeContentBuilder builder = new ConfigChangeContentBuilder();
Item managedEntity = itemService.findOne(appId, clusterName, namespaceName, entity.getKey()); Item managedEntity = itemService.findOne(appId, clusterName, namespaceName, entity.getKey());
if (managedEntity != null) { if (managedEntity != null) {
Item beforeUpdateItem = BeanUtils.transfrom(Item.class, managedEntity); throw new BadRequestException("item already exist");
BeanUtils.copyEntityProperties(entity, managedEntity);
entity = itemService.update(managedEntity);
builder.updateItem(beforeUpdateItem, entity);
} else { } else {
Item lastItem = itemService.findLastOne(appId, clusterName, namespaceName); Item lastItem = itemService.findLastOne(appId, clusterName, namespaceName);
int lineNum = 1; int lineNum = 1;
......
...@@ -15,6 +15,7 @@ import com.ctrip.framework.apollo.core.dto.ReleaseDTO; ...@@ -15,6 +15,7 @@ import com.ctrip.framework.apollo.core.dto.ReleaseDTO;
import com.ctrip.framework.apollo.core.exception.NotFoundException; import com.ctrip.framework.apollo.core.exception.NotFoundException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
...@@ -52,8 +53,9 @@ public class ReleaseController { ...@@ -52,8 +53,9 @@ public class ReleaseController {
@RequestMapping("/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases") @RequestMapping("/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases")
public List<ReleaseDTO> find(@PathVariable("appId") String appId, public List<ReleaseDTO> find(@PathVariable("appId") String appId,
@PathVariable("clusterName") String clusterName, @PathVariable("clusterName") String clusterName,
@PathVariable("namespaceName") String namespaceName) { @PathVariable("namespaceName") String namespaceName,
List<Release> releases = releaseService.findReleases(appId, clusterName, namespaceName); Pageable page) {
List<Release> releases = releaseService.findReleases(appId, clusterName, namespaceName, page);
return BeanUtils.batchTransform(ReleaseDTO.class, releases); return BeanUtils.batchTransform(ReleaseDTO.class, releases);
} }
......
...@@ -6,6 +6,7 @@ import com.ctrip.framework.apollo.common.entity.AppNamespace; ...@@ -6,6 +6,7 @@ import com.ctrip.framework.apollo.common.entity.AppNamespace;
import java.util.List; import java.util.List;
public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNamespace, Long>{ public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNamespace, Long>{
AppNamespace findByAppIdAndName(String appId, String namespaceName); AppNamespace findByAppIdAndName(String appId, String namespaceName);
......
...@@ -2,6 +2,7 @@ package com.ctrip.framework.apollo.biz.repository; ...@@ -2,6 +2,7 @@ package com.ctrip.framework.apollo.biz.repository;
import java.util.List; import java.util.List;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
...@@ -15,6 +16,5 @@ public interface ReleaseRepository extends PagingAndSortingRepository<Release, L ...@@ -15,6 +16,5 @@ public interface ReleaseRepository extends PagingAndSortingRepository<Release, L
Release findFirstByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(@Param("appId") String appId, @Param("clusterName") String clusterName, Release findFirstByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(@Param("appId") String appId, @Param("clusterName") String clusterName,
@Param("namespaceName") String namespaceName); @Param("namespaceName") String namespaceName);
List<Release> findByAppIdAndClusterNameAndNamespaceName(String appId, String clusterName, List<Release> findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(String appId, String clusterName, String namespaceName, Pageable page);
String namespaceName);
} }
...@@ -83,8 +83,7 @@ public class AppNamespaceService { ...@@ -83,8 +83,7 @@ public class AppNamespaceService {
appNamespace.setDataChangeLastModifiedBy(createBy); appNamespace.setDataChangeLastModifiedBy(createBy);
appNamespace = appNamespaceRepository.save(appNamespace); appNamespace = appNamespaceRepository.save(appNamespace);
//// TODO: 16/7/11 上线完删除开关逻辑 if (!appNamespace.isPublic()) {
if ("true".equals(serverConfigService.getValue("appnamespace.private.enable", "false")) && !appNamespace.isPublic()) {
linkPrivateAppNamespaceInAllCluster(appNamespace.getAppId(), appNamespace.getName(), createBy); linkPrivateAppNamespaceInAllCluster(appNamespace.getAppId(), appNamespace.getName(), createBy);
} }
......
...@@ -6,6 +6,7 @@ import com.ctrip.framework.apollo.biz.entity.Namespace; ...@@ -6,6 +6,7 @@ import com.ctrip.framework.apollo.biz.entity.Namespace;
import com.ctrip.framework.apollo.biz.repository.ItemRepository; import com.ctrip.framework.apollo.biz.repository.ItemRepository;
import com.ctrip.framework.apollo.biz.repository.NamespaceRepository; import com.ctrip.framework.apollo.biz.repository.NamespaceRepository;
import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.core.exception.BadRequestException;
import com.ctrip.framework.apollo.core.exception.NotFoundException; import com.ctrip.framework.apollo.core.exception.NotFoundException;
import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.core.utils.StringUtils;
...@@ -93,6 +94,7 @@ public class ItemService { ...@@ -93,6 +94,7 @@ public class ItemService {
@Transactional @Transactional
public Item save(Item entity) { public Item save(Item entity) {
checkItemKeyLength(entity.getKey());
checkItemValueLength(entity.getValue()); checkItemValueLength(entity.getValue());
entity.setId(0);//protection entity.setId(0);//protection
...@@ -120,7 +122,15 @@ public class ItemService { ...@@ -120,7 +122,15 @@ public class ItemService {
private boolean checkItemValueLength(String value){ private boolean checkItemValueLength(String value){
int lengthLimit = Integer.valueOf(serverConfigService.getValue("item.value.length.limit", "20000")); int lengthLimit = Integer.valueOf(serverConfigService.getValue("item.value.length.limit", "20000"));
if (!StringUtils.isEmpty(value) && value.length() > lengthLimit){ if (!StringUtils.isEmpty(value) && value.length() > lengthLimit){
throw new IllegalArgumentException("value too long. length limit:" + lengthLimit); throw new BadRequestException("value too long. length limit:" + lengthLimit);
}
return true;
}
private boolean checkItemKeyLength(String key){
int lengthLimit = Integer.valueOf(serverConfigService.getValue("item.key.length.limit", "128"));
if (!StringUtils.isEmpty(key) && key.length() > lengthLimit){
throw new BadRequestException("key too long. length limit:" + lengthLimit);
} }
return true; return true;
} }
......
...@@ -12,6 +12,7 @@ import com.ctrip.framework.apollo.biz.utils.ReleaseKeyGenerator; ...@@ -12,6 +12,7 @@ import com.ctrip.framework.apollo.biz.utils.ReleaseKeyGenerator;
import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.core.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
...@@ -46,9 +47,9 @@ public class ReleaseService { ...@@ -46,9 +47,9 @@ public class ReleaseService {
return release; return release;
} }
public List<Release> findReleases(String appId, String clusterName, String namespaceName) { public List<Release> findReleases(String appId, String clusterName, String namespaceName, Pageable page) {
List<Release> releases = releaseRepository.findByAppIdAndClusterNameAndNamespaceName(appId, List<Release> releases = releaseRepository.findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(appId,
clusterName, namespaceName); clusterName, namespaceName, page);
if (releases == null) { if (releases == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
......
...@@ -36,6 +36,14 @@ public class RequestPrecondition { ...@@ -36,6 +36,14 @@ public class RequestPrecondition {
} }
} }
public static void checkNumberNotNegative(int... args){
for (int num: args){
if (num < 0){
throw new BadRequestException(ILLEGAL_NUMBER);
}
}
}
} }
...@@ -109,7 +109,7 @@ public class AdminServiceAPI { ...@@ -109,7 +109,7 @@ public class AdminServiceAPI {
public void updateItem(String appId, Env env, String clusterName, String namespace, long itemId, ItemDTO item) { public void updateItem(String appId, Env env, String clusterName, String namespace, long itemId, ItemDTO item) {
restTemplate.put("{host}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}", restTemplate.put("{host}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}",
item, getAdminServiceHost(env), appId, clusterName, namespace, itemId); item, getAdminServiceHost(env), appId, clusterName, namespace, itemId);
} }
...@@ -155,21 +155,27 @@ public class AdminServiceAPI { ...@@ -155,21 +155,27 @@ public class AdminServiceAPI {
@Service @Service
public static class ReleaseAPI extends API { public static class ReleaseAPI extends API {
public List<ReleaseDTO> findReleases(String appId, Env env, String clusterName, String namespaceName, int page, int size){
ReleaseDTO[] releaseDTOs = restTemplate.getForObject(
"{host}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases?page={page}&size={size}",
ReleaseDTO[].class,
getAdminServiceHost(env), appId, clusterName, namespaceName, page, size);
return Arrays.asList(releaseDTOs);
}
public ReleaseDTO loadLatestRelease(String appId, Env env, String clusterName, public ReleaseDTO loadLatestRelease(String appId, Env env, String clusterName,
String namespace) { String namespace) {
ReleaseDTO ReleaseDTO releaseDTO = restTemplate
releaseDTO = .getForObject("{host}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/latest",
restTemplate ReleaseDTO.class, getAdminServiceHost(env), appId, clusterName, namespace);
.getForObject("{host}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/latest",
ReleaseDTO.class, getAdminServiceHost(env), appId, clusterName, namespace);
return releaseDTO; return releaseDTO;
} }
public ReleaseDTO release(String appId, Env env, String clusterName, String namespace, public ReleaseDTO release(String appId, Env env, String clusterName, String namespace,
String releaseBy, String comment, String operator) { String releaseBy, String comment, String operator) {
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"));
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>(); MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("name", releaseBy); parameters.add("name", releaseBy);
parameters.add("comment", comment); parameters.add("comment", comment);
parameters.add("operator", operator); parameters.add("operator", operator);
...@@ -189,9 +195,7 @@ public class AdminServiceAPI { ...@@ -189,9 +195,7 @@ public class AdminServiceAPI {
public List<CommitDTO> find(String appId, Env env, String clusterName, String namespaceName, int page, int size) { public List<CommitDTO> find(String appId, Env env, String clusterName, String namespaceName, int page, int size) {
CommitDTO[] CommitDTO[] commitDTOs = restTemplate.getForObject(
commitDTOs =
restTemplate.getForObject(
"{host}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/commit?page={page}&size={size}", "{host}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/commit?page={page}&size={size}",
CommitDTO[].class, CommitDTO[].class,
getAdminServiceHost(env), appId, clusterName, namespaceName, page, size); getAdminServiceHost(env), appId, clusterName, namespaceName, page, size);
......
...@@ -58,11 +58,13 @@ public class RestTemplateFactory implements FactoryBean<RestTemplate>, Initializ ...@@ -58,11 +58,13 @@ public class RestTemplateFactory implements FactoryBean<RestTemplate>, Initializ
HttpClientBuilder.create().setDefaultCredentialsProvider(credentialsProvider) HttpClientBuilder.create().setDefaultCredentialsProvider(credentialsProvider)
.setDefaultHeaders(defaultHeaders).build(); .setDefaultHeaders(defaultHeaders).build();
restTemplate = new RestTemplate(httpMessageConverters.getConverters()); restTemplate = new RestTemplate(httpMessageConverters.getConverters());
HttpComponentsClientHttpRequestFactory requestFactory = HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient); new HttpComponentsClientHttpRequestFactory(httpClient);
requestFactory.setConnectTimeout(getConnectTimeout()); requestFactory.setConnectTimeout(getConnectTimeout());
requestFactory.setReadTimeout(getReadTimeout()); requestFactory.setReadTimeout(getReadTimeout());
restTemplate.setRequestFactory(requestFactory); restTemplate.setRequestFactory(requestFactory);
} }
......
package com.ctrip.framework.apollo.portal.controller; package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import com.ctrip.framework.apollo.core.dto.CommitDTO; import com.ctrip.framework.apollo.core.dto.CommitDTO;
import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.service.CommitService; import com.ctrip.framework.apollo.portal.service.CommitService;
...@@ -24,9 +25,8 @@ public class CommitController { ...@@ -24,9 +25,8 @@ public class CommitController {
@PathVariable String clusterName, @PathVariable String namespaceName, @PathVariable String clusterName, @PathVariable String namespaceName,
@RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size){ @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size){
if (page < 0){ RequestPrecondition.checkNumberPositive(size);
page = 0; RequestPrecondition.checkNumberNotNegative(page);
}
return commitService.find(appId, Env.valueOf(env), clusterName, namespaceName, page, size); return commitService.find(appId, Env.valueOf(env), clusterName, namespaceName, page, size);
......
package com.ctrip.framework.apollo.portal.controller; package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.core.dto.ItemDTO; import com.ctrip.framework.apollo.core.dto.ItemDTO;
import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.dto.ReleaseDTO;
import com.ctrip.framework.apollo.core.exception.BadRequestException; import com.ctrip.framework.apollo.core.exception.BadRequestException;
import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.entity.vo.ItemDiffs; import com.ctrip.framework.apollo.portal.entity.vo.ItemDiffs;
import com.ctrip.framework.apollo.portal.entity.form.NamespaceSyncModel; import com.ctrip.framework.apollo.portal.entity.form.NamespaceSyncModel;
import com.ctrip.framework.apollo.portal.entity.form.NamespaceTextModel; import com.ctrip.framework.apollo.portal.entity.form.NamespaceTextModel;
import com.ctrip.framework.apollo.portal.entity.form.NamespaceReleaseModel;
import com.ctrip.framework.apollo.portal.service.ConfigService; import com.ctrip.framework.apollo.portal.service.ConfigService;
import com.ctrip.framework.apollo.portal.service.ServerConfigService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
...@@ -34,8 +29,6 @@ public class ConfigController { ...@@ -34,8 +29,6 @@ public class ConfigController {
@Autowired @Autowired
private ConfigService configService; private ConfigService configService;
@Autowired
private ServerConfigService serverConfigService;
@PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)") @PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.PUT, consumes = { @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.PUT, consumes = {
...@@ -86,22 +79,7 @@ public class ConfigController { ...@@ -86,22 +79,7 @@ public class ConfigController {
configService.deleteItem(Env.valueOf(env), itemId); configService.deleteItem(Env.valueOf(env), itemId);
} }
@PreAuthorize(value = "@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/release", method = RequestMethod.POST, consumes = {
"application/json"})
public ReleaseDTO createRelease(@PathVariable String appId,
@PathVariable String env, @PathVariable String clusterName,
@PathVariable String namespaceName, @RequestBody NamespaceReleaseModel model) {
checkModel(model != null);
model.setAppId(appId);
model.setEnv(env);
model.setClusterName(clusterName);
model.setNamespaceName(namespaceName);
return configService.createRelease(model);
}
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items") @RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items")
public List<ItemDTO> findItems(@PathVariable String appId, @PathVariable String env, public List<ItemDTO> findItems(@PathVariable String appId, @PathVariable String env,
......
...@@ -16,6 +16,7 @@ import com.ctrip.framework.apollo.portal.service.AppNamespaceService; ...@@ -16,6 +16,7 @@ import com.ctrip.framework.apollo.portal.service.AppNamespaceService;
import com.ctrip.framework.apollo.portal.service.AppService; import com.ctrip.framework.apollo.portal.service.AppService;
import com.ctrip.framework.apollo.portal.service.NamespaceService; import com.ctrip.framework.apollo.portal.service.NamespaceService;
import com.ctrip.framework.apollo.portal.service.RoleInitializationService; import com.ctrip.framework.apollo.portal.service.RoleInitializationService;
import com.dianping.cat.Cat;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -76,7 +77,9 @@ public class NamespaceController { ...@@ -76,7 +77,9 @@ public class NamespaceController {
// TODO: 16/6/17 某些环境创建失败,统一处理这种场景 // TODO: 16/6/17 某些环境创建失败,统一处理这种场景
namespaceService.createNamespace(Env.valueOf(model.getEnv()), namespace); namespaceService.createNamespace(Env.valueOf(model.getEnv()), namespace);
} catch (Exception e) { } catch (Exception e) {
logger.error("create namespace error.", e); logger.error("create namespace fail.", e);
Cat.logError(
String.format("create namespace fail. (env=%s namespace=%s)", model.getEnv(), namespace.getNamespaceName()), e);
} }
} }
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
......
package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import com.ctrip.framework.apollo.core.dto.ReleaseDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.entity.form.NamespaceReleaseModel;
import com.ctrip.framework.apollo.portal.entity.vo.ReleaseVO;
import com.ctrip.framework.apollo.portal.service.ReleaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
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;
import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;
@RestController
public class ReleaseController {
@Autowired
private ReleaseService releaseService;
@PreAuthorize(value = "@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/release")
public ReleaseDTO createRelease(@PathVariable String appId,
@PathVariable String env, @PathVariable String clusterName,
@PathVariable String namespaceName, @RequestBody NamespaceReleaseModel model) {
checkModel(model != null);
model.setAppId(appId);
model.setEnv(env);
model.setClusterName(clusterName);
model.setNamespaceName(namespaceName);
return releaseService.createRelease(model);
}
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases")
public List<ReleaseVO> findReleases(@PathVariable String appId,
@PathVariable String env, @PathVariable String clusterName,
@PathVariable String namespaceName,
@RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "5") int size){
RequestPrecondition.checkNumberPositive(size);
RequestPrecondition.checkNumberNotNegative(page);
return releaseService.findReleases(appId, Env.valueOf(env), clusterName, namespaceName, page, size);
}
}
...@@ -10,6 +10,8 @@ public class NamespaceVO { ...@@ -10,6 +10,8 @@ public class NamespaceVO {
private int itemModifiedCnt; private int itemModifiedCnt;
private List<ItemVO> items; private List<ItemVO> items;
private String format; private String format;
private boolean isPublic;
private String parentAppId;
public NamespaceDTO getNamespace() { public NamespaceDTO getNamespace() {
...@@ -44,6 +46,22 @@ public class NamespaceVO { ...@@ -44,6 +46,22 @@ public class NamespaceVO {
this.format = format; this.format = format;
} }
public boolean isPublic() {
return isPublic;
}
public void setPublic(boolean aPublic) {
isPublic = aPublic;
}
public String getParentAppId() {
return parentAppId;
}
public void setParentAppId(String parentAppId) {
this.parentAppId = parentAppId;
}
public static class ItemVO{ public static class ItemVO{
private ItemDTO item; private ItemDTO item;
private boolean isModified; private boolean isModified;
...@@ -82,6 +100,7 @@ public class NamespaceVO { ...@@ -82,6 +100,7 @@ public class NamespaceVO {
this.newValue = newValue; this.newValue = newValue;
} }
} }
} }
package com.ctrip.framework.apollo.portal.entity.vo;
import com.ctrip.framework.apollo.core.dto.ReleaseDTO;
import java.util.Set;
public class ReleaseVO {
private ReleaseDTO baseInfo;
private Set<KVEntity> items;
public ReleaseDTO getBaseInfo() {
return baseInfo;
}
public void setBaseInfo(ReleaseDTO baseInfo) {
this.baseInfo = baseInfo;
}
public Set<KVEntity> getItems() {
return items;
}
public void setItems(Set<KVEntity> items) {
this.items = items;
}
public static class KVEntity{
String key;
String value;
public KVEntity(String key, String value){
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
...@@ -16,7 +16,6 @@ import com.ctrip.framework.apollo.core.enums.Env; ...@@ -16,7 +16,6 @@ import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.dto.ItemChangeSets; import com.ctrip.framework.apollo.core.dto.ItemChangeSets;
import com.ctrip.framework.apollo.core.dto.ItemDTO; import com.ctrip.framework.apollo.core.dto.ItemDTO;
import com.ctrip.framework.apollo.core.dto.NamespaceDTO; import com.ctrip.framework.apollo.core.dto.NamespaceDTO;
import com.ctrip.framework.apollo.core.dto.ReleaseDTO;
import com.ctrip.framework.apollo.core.exception.BadRequestException; import com.ctrip.framework.apollo.core.exception.BadRequestException;
import com.ctrip.framework.apollo.core.exception.ServiceException; import com.ctrip.framework.apollo.core.exception.ServiceException;
import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.core.utils.StringUtils;
...@@ -25,7 +24,6 @@ import com.ctrip.framework.apollo.portal.auth.UserInfoHolder; ...@@ -25,7 +24,6 @@ import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.entity.vo.ItemDiffs; import com.ctrip.framework.apollo.portal.entity.vo.ItemDiffs;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceIdentifer; import com.ctrip.framework.apollo.portal.entity.vo.NamespaceIdentifer;
import com.ctrip.framework.apollo.portal.entity.form.NamespaceTextModel; import com.ctrip.framework.apollo.portal.entity.form.NamespaceTextModel;
import com.ctrip.framework.apollo.portal.entity.form.NamespaceReleaseModel;
import com.ctrip.framework.apollo.portal.service.txtresolver.ConfigTextResolver; import com.ctrip.framework.apollo.portal.service.txtresolver.ConfigTextResolver;
import java.util.LinkedList; import java.util.LinkedList;
...@@ -107,15 +105,6 @@ public class ConfigService { ...@@ -107,15 +105,6 @@ public class ConfigService {
itemAPI.deleteItem(env, itemId, userInfoHolder.getUser().getUserId()); itemAPI.deleteItem(env, itemId, userInfoHolder.getUser().getUserId());
} }
/**
* createRelease config items
*/
public ReleaseDTO createRelease(NamespaceReleaseModel model) {
return releaseAPI.release(model.getAppId(), model.getEnv(), model.getClusterName(),
model.getNamespaceName(), model.getReleaseBy(), model.getReleaseComment()
, userInfoHolder.getUser().getUserId());
}
public List<ItemDTO> findItems(String appId, Env env, String clusterName, String namespaceName) { public List<ItemDTO> findItems(String appId, Env env, String clusterName, String namespaceName) {
return itemAPI.findItems(appId, env, clusterName, namespaceName); return itemAPI.findItems(appId, env, clusterName, namespaceName);
} }
......
...@@ -92,7 +92,7 @@ public class NamespaceService { ...@@ -92,7 +92,7 @@ public class NamespaceService {
NamespaceVO namespaceVO = new NamespaceVO(); NamespaceVO namespaceVO = new NamespaceVO();
namespaceVO.setNamespace(namespace); namespaceVO.setNamespace(namespace);
namespaceVO.setFormat(getNamespaceFormat(namespace)); fillFormatAndIsPublicAndParentAppField(namespaceVO);
List<NamespaceVO.ItemVO> itemVos = new LinkedList<>(); List<NamespaceVO.ItemVO> itemVos = new LinkedList<>();
namespaceVO.setItems(itemVos); namespaceVO.setItems(itemVos);
...@@ -137,19 +137,28 @@ public class NamespaceService { ...@@ -137,19 +137,28 @@ public class NamespaceService {
return namespaceVO; return namespaceVO;
} }
private String getNamespaceFormat(NamespaceDTO namespace){ private void fillFormatAndIsPublicAndParentAppField(NamespaceVO namespace) {
NamespaceDTO namespaceDTO = namespace.getNamespace();
//先从当前appId下面找,包含私有的和公共的 //先从当前appId下面找,包含私有的和公共的
AppNamespace appNamespace = appNamespaceService.findByAppIdAndName(namespace.getAppId(), namespace.getNamespaceName()); AppNamespace appNamespace =
appNamespaceService.findByAppIdAndName(namespaceDTO.getAppId(), namespaceDTO.getNamespaceName());
//再从公共的app namespace里面找 //再从公共的app namespace里面找
if (appNamespace == null) { if (appNamespace == null) {
appNamespace = appNamespaceService.findPublicAppNamespace(namespace.getNamespaceName()); appNamespace = appNamespaceService.findPublicAppNamespace(namespaceDTO.getNamespaceName());
} }
if (appNamespace == null){ String format;
return ConfigFileFormat.Properties.getValue(); boolean isPublic;
}else { if (appNamespace == null) {
return appNamespace.getFormat(); format = ConfigFileFormat.Properties.getValue();
isPublic = false;
} else {
format = appNamespace.getFormat();
isPublic = appNamespace.isPublic();
namespace.setParentAppId(appNamespace.getAppId());
} }
namespace.setFormat(format);
namespace.setPublic(isPublic);
} }
private List<NamespaceVO.ItemVO> countDeletedItemNum(List<ItemDTO> newItems, Map<String, String> releaseItems) { private List<NamespaceVO.ItemVO> countDeletedItemNum(List<ItemDTO> newItems, Map<String, String> releaseItems) {
......
package com.ctrip.framework.apollo.portal.service;
import com.google.gson.Gson;
import com.ctrip.framework.apollo.core.dto.ReleaseDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.entity.form.NamespaceReleaseModel;
import com.ctrip.framework.apollo.portal.entity.vo.ReleaseVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Collections;
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 createRelease(NamespaceReleaseModel model) {
return releaseAPI.release(model.getAppId(), model.getEnv(), model.getClusterName(),
model.getNamespaceName(), model.getReleaseBy(), model.getReleaseComment()
, userInfoHolder.getUser().getUserId());
}
public List<ReleaseVO> findReleases(String appId, Env env, String clusterName, String namespaceName, int page, int size){
List<ReleaseDTO> releaseDTOs = releaseAPI.findReleases(appId, env, clusterName, namespaceName, page, size);
if (CollectionUtils.isEmpty(releaseDTOs)){
return Collections.EMPTY_LIST;
}
List<ReleaseVO> releases = new LinkedList<>();
for (ReleaseDTO releaseDTO: releaseDTOs){
ReleaseVO release = new ReleaseVO();
release.setBaseInfo(releaseDTO);
Set<ReleaseVO.KVEntity> kvEntities = new LinkedHashSet<>();
Set<Map.Entry> entries = gson.fromJson(releaseDTO.getConfigurations(), Map.class).entrySet();
for(Map.Entry<String, String> entry: entries){
kvEntities.add(new ReleaseVO.KVEntity(entry.getKey(), entry.getValue()));
}
release.setItems(kvEntities);
//为了减少数据量
releaseDTO.setConfigurations("");
releases.add(release);
}
return releases;
}
}
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
<property name="LOG_FILE" <property name="LOG_FILE"
value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}apollo-portal.log}" /> value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}apollo-portal.log}" />
<include resource="org/springframework/boot/logging/logback/file-appender.xml" /> <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<root level="INFO"> <root level="INFO">
<appender-ref ref="FILE" /> <appender-ref ref="FILE" />
<appender-ref ref="CONSOLE" />
</root> </root>
</configuration> </configuration>
\ No newline at end of file
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
</header> </header>
<div class="panel-body"> <div class="panel-body">
<div class="alert alert-info" role="alert">apollo系统目前正在开发内测阶段,接入前请仔细阅读项目文档, 有问题请联系song_s@ctrip.com,zhanglea@ctrip.com</div>
<form class="form-horizontal" ng-controller="CreateAppController" ng-submit="create()"> <form class="form-horizontal" ng-controller="CreateAppController" ng-submit="create()">
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 部门</label> <label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 部门</label>
......
...@@ -65,14 +65,20 @@ ...@@ -65,14 +65,20 @@
</div> </div>
</section> </section>
<apolloentrance apollo-title="'补缺环境'" apollo-img-src="'img/plus-orange.png'" <a class="list-group-item" ng-show="missEnvs.length > 0" ng-click="createAppInMissEnv()">
ng-show="missEnvs.length > 0" ng-click="createAppInMissEnv()"></apolloentrance> <div class="row">
<div class="col-md-2"><img src="img/plus-orange.png" class="i-20"></div>
<div class="col-md-10 hidden-xs">
<p class="btn-title">补缺环境</p>
</div>
</div>
</a>
<apolloentrance apollo-title="'添加集群'" apollo-img-src="'img/plus-orange.png'" <apolloentrance apollo-title="'添加集群'" apollo-img-src="'img/plus-orange.png'"
apollo-href="'cluster.html?#/appid=' + pageContext.appId"></apolloentrance> apollo-href="'cluster.html?#/appid=' + pageContext.appId"></apolloentrance>
<apolloentrance apollo-title="'添加Namespace'" apollo-img-src="'img/plus-orange.png'" <apolloentrance apollo-title="'添加Namespace'" apollo-img-src="'img/plus-orange.png'"
apollo-href="'namespace.html?#/appid=' + pageContext.appId + '&type=link'" apollo-href="'namespace.html?#/appid=' + pageContext.appId"
ng-show="hasCreateNamespacePermission"></apolloentrance> ng-show="hasCreateNamespacePermission"></apolloentrance>
<apolloentrance apollo-title="'项目权限'" apollo-img-src="'img/user_manage.png'" <apolloentrance apollo-title="'项目权限'" apollo-img-src="'img/user_manage.png'"
...@@ -80,7 +86,6 @@ ...@@ -80,7 +86,6 @@
ng-show="hasAssignUserPermission"></apolloentrance> ng-show="hasAssignUserPermission"></apolloentrance>
</section> </section>
<!--create env modal-->
</div> </div>
...@@ -191,9 +196,12 @@ ...@@ -191,9 +196,12 @@
</div> </div>
</div> </div>
<span ng-show="!toReleaseNamespace.itemModifiedCnt"> <div class="col-sm-5">
<span ng-show="!toReleaseNamespace.itemModifiedCnt">
配置没有变化 配置没有变化
</span> </span>
</div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label"> <label class="col-sm-2 control-label">
...@@ -345,6 +353,7 @@ ...@@ -345,6 +353,7 @@
<script type="application/javascript" src="scripts/services/EnvService.js"></script> <script type="application/javascript" src="scripts/services/EnvService.js"></script>
<script type="application/javascript" src="scripts/services/UserService.js"></script> <script type="application/javascript" src="scripts/services/UserService.js"></script>
<script type="application/javascript" src="scripts/services/ConfigService.js"></script> <script type="application/javascript" src="scripts/services/ConfigService.js"></script>
<script type="application/javascript" src="scripts/services/ReleaseService.js"></script>
<script type="application/javascript" src="scripts/services/PermissionService.js"></script> <script type="application/javascript" src="scripts/services/PermissionService.js"></script>
<script type="application/javascript" src="scripts/services/CommitService.js"></script> <script type="application/javascript" src="scripts/services/CommitService.js"></script>
<script type="application/javascript" src="scripts/services/NamespaceLockService.js"></script> <script type="application/javascript" src="scripts/services/NamespaceLockService.js"></script>
......
<!doctype html >
<html ng-app="release_history">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- styles -->
<link rel="stylesheet" type="text/css" href="../vendor/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="../vendor/angular/angular-toastr-1.4.1.min.css">
<link rel="stylesheet" type="text/css" media='all' href="../vendor/angular/loading-bar.min.css">
<link rel="stylesheet" type="text/css" href="../styles/common-style.css">
<title>发布历史</title>
</head>
<body>
<apollonav></apollonav>
<div class="container-fluid apollo-container release-history" ng-controller="ReleaseHistoryController">
<section class="panel col-md-offset-1 col-md-10">
<div class="panel-heading row">
<div class="col-md-4">
<h4>发布历史</h4>
</div>
<div class="col-md-8 text-right">
<a type="button" class="btn btn-info" href="/config.html?#/appid={{pageContext.appId}}">返回到项目首页
</a>
</div>
</div>
<div class="panel-body">
<div class="media" ng-repeat="release in releases">
<div class="media-left media-middle badge-{{$index % 4}}">
</div>
<div class="media-body">
<div class="row">
<div class="col-md-2 user">
<img src="../img/user.png" class="i-20">
<span class="info" ng-bind="release.baseInfo.dataChangeCreatedBy"></span>
</div>
<div class="col-md-3 time">
<img src="../img/time.png" class="i-20">
<span class="info"
ng-bind="release.baseInfo.dataChangeCreatedTime | date: 'yyyy-MM-dd HH:mm:ss'"></span>
</div>
<div class="col-md-3 time">
<img src="../img/title.png" class="i-20">
<span class="info"
ng-bind="release.baseInfo.name"></span>
</div>
<div class="col-md-4 comment" ng-show="release.baseInfo.comment">
<img src="../img/comment.png" class="i-20">
<span class="info" ng-bind="release.baseInfo.comment"></span>
</div>
</div>
<table class="table table-hover table-bordered table-striped">
<tr ng-repeat="item in release.items">
<td width="30%" ng-bind="item.key">
</td>
<td width="70%" ng-bind="item.value">
</td>
</tr>
</table>
</div>
</div>
<div class="text-center">
<button type="button" class="btn btn-default" ng-show="!hasLoadAll"
ng-click="loadMore()">加载更多
<span class="glyphicon glyphicon-menu-down"></span>
</button>
</div>
</div>
</section>
</div>
<div ng-include="'../views/common/footer.html'"></div>
<!-- jquery.js -->
<script src="../vendor/jquery.min.js" type="text/javascript"></script>
<!--angular-->
<script src="../vendor/angular/angular.min.js"></script>
<script src="../vendor/angular/angular-route.min.js"></script>
<script src="../vendor/angular/angular-resource.min.js"></script>
<script src="../vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script>
<script src="../vendor/angular/loading-bar.min.js"></script>
<!-- bootstrap.js -->
<script src="../vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<!--nicescroll-->
<script src="../vendor/jquery.nicescroll.min.js"></script>
<!--biz-->
<script type="application/javascript" src="../scripts/app.js"></script>
<script type="application/javascript" src="../scripts/services/AppService.js"></script>
<script type="application/javascript" src="../scripts/services/EnvService.js"></script>
<script type="application/javascript" src="../scripts/services/ReleaseService.js"></script>
<script type="application/javascript" src="../scripts/services/UserService.js"></script>
<script type="application/javascript" src="../scripts/AppUtils.js"></script>
<script type="application/javascript" src="../scripts/controller/config/ReleaseHistoryController.js"></script>
<script type="application/javascript" src="../scripts/PageCommon.js"></script>
<script type="application/javascript" src="../scripts/directive/directive.js"></script>
</body>
</html>
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
<button type="button" class="btn btn-success" ng-show="syncItemStep == 2 && hasDiff" <button type="button" class="btn btn-success" ng-show="syncItemStep == 2 && hasDiff"
ng-click="syncItems()">同步 ng-click="syncItems()">同步
</button> </button>
<button type="button" class="btn btn-info" data-dismiss="modal" ng-show="syncItemStep == 3" <button type="button" class="btn btn-info" data-dismiss="modal"
ng-click="backToAppHomePage()">返回到项目首页 ng-click="backToAppHomePage()">返回到项目首页
</button> </button>
</div> </div>
......
appUtil.service('AppUtil', ['toastr', function (toastr) { appUtil.service('AppUtil', ['toastr', '$window', function (toastr, $window) {
return { return {
errorMsg: function (response) { errorMsg: function (response) {
...@@ -11,14 +11,19 @@ appUtil.service('AppUtil', ['toastr', function (toastr) { ...@@ -11,14 +11,19 @@ appUtil.service('AppUtil', ['toastr', function (toastr) {
} }
return msg; return msg;
}, },
parseParams: function (path) { parseParams: function (query, notJumpToHomePage) {
if (!path) { if (!query) {
return {}; //如果不传这个参数或者false则返回到首页(参数出错)
if (!notJumpToHomePage) {
$window.location.href = '/index.html';
} else {
return {};
}
} }
if (path.indexOf('/') == 0) { if (query.indexOf('/') == 0) {
path = path.substring(1, path.length); query = query.substring(1, query.length);
} }
var params = path.split("&"); var params = query.split("&");
var result = {}; var result = {};
params.forEach(function (param) { params.forEach(function (param) {
var kv = param.split("="); var kv = param.split("=");
......
...@@ -24,7 +24,8 @@ var server_config_module = angular.module('server_config', ['app.service', 'apol ...@@ -24,7 +24,8 @@ var server_config_module = angular.module('server_config', ['app.service', 'apol
var role_module = angular.module('role', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']); var role_module = angular.module('role', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
//cluster //cluster
var cluster_module = angular.module('cluster', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']); var cluster_module = angular.module('cluster', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
//release history
var release_history_module = angular.module('release_history', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
......
...@@ -6,7 +6,7 @@ namespace_module.controller("LinkNamespaceController", ...@@ -6,7 +6,7 @@ namespace_module.controller("LinkNamespaceController",
var params = AppUtil.parseParams($location.$$url); var params = AppUtil.parseParams($location.$$url);
$scope.appId = params.appid; $scope.appId = params.appid;
$scope.type = params.type; $scope.type = 'link';
$scope.step = 1; $scope.step = 1;
......
application_module.controller("ConfigNamespaceController", application_module.controller("ConfigNamespaceController",
['$rootScope', '$scope', '$window', '$location', 'toastr', 'AppUtil', 'ConfigService', ['$rootScope', '$scope', '$window', '$location', 'toastr', 'AppUtil', 'ConfigService',
'PermissionService', 'PermissionService',
'CommitService', 'NamespaceLockService', 'UserService', 'CommitService', 'NamespaceLockService', 'UserService', 'ReleaseService',
function ($rootScope, $scope, $window, $location, toastr, AppUtil, ConfigService, function ($rootScope, $scope, $window, $location, toastr, AppUtil, ConfigService,
PermissionService, PermissionService,
CommitService, NamespaceLockService, UserService) { CommitService, NamespaceLockService, UserService, ReleaseService) {
var namespace_view_type = { var namespace_view_type = {
TEXT: 'text', TEXT: 'text',
...@@ -117,13 +117,13 @@ application_module.controller("ConfigNamespaceController", ...@@ -117,13 +117,13 @@ application_module.controller("ConfigNamespaceController",
} else { } else {
$('#releaseModal').modal('show'); $('#releaseModal').modal('show');
} }
$scope.releaseTitle = new Date().Format("yyyy-MM-dd hh:mm:ss"); $scope.releaseTitle = new Date().Format("yyyyMMddhhmmss") + "-release";
$scope.toReleaseNamespace = namespace; $scope.toReleaseNamespace = namespace;
} }
$scope.releaseComment = ''; $scope.releaseComment = '';
function release() { function release() {
ConfigService.release($rootScope.pageContext.appId, $rootScope.pageContext.env, ReleaseService.release($rootScope.pageContext.appId, $rootScope.pageContext.env,
$rootScope.pageContext.clusterName, $rootScope.pageContext.clusterName,
$scope.toReleaseNamespace.namespace.namespaceName, $scope.toReleaseNamespace.namespace.namespaceName,
$scope.releaseTitle, $scope.releaseTitle,
......
release_history_module.controller("ReleaseHistoryController",
['$scope', '$location', '$window', 'toastr', 'AppService', 'AppUtil',
'ReleaseService',
function ($scope, $location, $window, toastr, AppService, AppUtil, ReleaseService) {
var params = AppUtil.parseParams($location.$$url);
$scope.pageContext = {
appId: params.appid,
env: params.env,
clusterName: params.clusterName,
namespaceName: params.namespaceName
};
$scope.page = 0;
$scope.releases = [];
$scope.hasLoadAll = false;
$scope.findReleases = findReleases;
$scope.loadMore = loadMore;
findReleases($scope.page);
function findReleases(page) {
ReleaseService.findRelease($scope.pageContext.appId,
$scope.pageContext.env,
$scope.pageContext.clusterName,
$scope.pageContext.namespaceName,
page)
.then(function (result) {
if (!result || result.length == 0){
$scope.hasLoadAll = true;
return;
}
result.forEach(function (release) {
$scope.releases.push(release);
})
}, function (result) {
toastr.error(AppUtil.errorMsg(result));
});
}
function loadMore() {
$scope.page += 1;
findReleases($scope.page);
}
}]);
...@@ -22,9 +22,11 @@ directive_module.directive('apollonav', function ($compile, $window, toastr, App ...@@ -22,9 +22,11 @@ directive_module.directive('apollonav', function ($compile, $window, toastr, App
scope.searchKey = ''; scope.searchKey = '';
scope.shouldShowAppList = false; scope.shouldShowAppList = false;
var selectedApp = {}; var selectedApp = {};
scope.selectApp = function (app) { scope.selectApp = function (app) {
select(app); select(app);
scope.jumpToConfigPage();
}; };
scope.changeSearchKey = function () { scope.changeSearchKey = function () {
......
...@@ -38,6 +38,8 @@ directive_module.directive('apollonspanel', ...@@ -38,6 +38,8 @@ directive_module.directive('apollonspanel',
scope.modifyByText = modifyByText; scope.modifyByText = modifyByText;
scope.goToParentAppConfigPage = goToParentAppConfigPage;
initNamespace(scope.namespace); initNamespace(scope.namespace);
//init method //init method
...@@ -115,7 +117,6 @@ directive_module.directive('apollonspanel', ...@@ -115,7 +117,6 @@ directive_module.directive('apollonspanel',
+ scope.env + "&clusterName=" + scope.env + "&clusterName="
+ scope.cluster + scope.cluster
+ "&namespaceName=" + namespace.namespace.namespaceName; + "&namespaceName=" + namespace.namespace.namespaceName;
} }
function modifyByText(namespace) { function modifyByText(namespace) {
...@@ -125,6 +126,11 @@ directive_module.directive('apollonspanel', ...@@ -125,6 +126,11 @@ directive_module.directive('apollonspanel',
} }
function goToParentAppConfigPage(namespace) {
$window.location.href = "/config.html?#/appid=" + namespace.parentAppId;
$window.location.reload();
}
//local method //local method
function initNamespace(namespace, viewType) { function initNamespace(namespace, viewType) {
...@@ -227,6 +233,8 @@ directive_module.directive('apollonspanel', ...@@ -227,6 +233,8 @@ directive_module.directive('apollonspanel',
return result; return result;
} }
function lockCheck(namespace) { function lockCheck(namespace) {
if (namespace.lockOwner && scope.currentUser != namespace.lockOwner) { if (namespace.lockOwner && scope.currentUser != namespace.lockOwner) {
scope.lockOwner = namespace.lockOwner; scope.lockOwner = namespace.lockOwner;
......
...@@ -14,10 +14,6 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q) ...@@ -14,10 +14,6 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
method: 'PUT', method: 'PUT',
url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/items' url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/items'
}, },
release: {
method: 'POST',
url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/release'
},
diff: { diff: {
method: 'POST', method: 'POST',
url: '/namespaces/:namespaceName/diff', url: '/namespaces/:namespaceName/diff',
...@@ -89,24 +85,6 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q) ...@@ -89,24 +85,6 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
return d.promise; return d.promise;
}, },
release: function (appId, env, clusterName, namespaceName, releaseBy, comment) {
var d = $q.defer();
config_source.release({
appId: appId,
env: env,
clusterName: clusterName,
namespaceName: namespaceName
}, {
releaseBy: releaseBy,
releaseComment: comment
}, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
diff: function (namespaceName, sourceData) { diff: function (namespaceName, sourceData) {
var d = $q.defer(); var d = $q.defer();
config_source.diff({ config_source.diff({
......
appService.service('ReleaseService', ['$resource', '$q', function ($resource, $q) {
var resource = $resource('', {}, {
find_releases: {
method: 'GET',
url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/releases',
isArray: true
},
release: {
method: 'POST',
url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/release'
}
});
function createRelease(appId, env, clusterName, namespaceName, releaseBy, comment) {
var d = $q.defer();
resource.release({
appId: appId,
env: env,
clusterName: clusterName,
namespaceName: namespaceName
}, {
releaseBy: releaseBy,
releaseComment: comment
}, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
function findReleases(appId, env, clusterName, namespaceName, page) {
var d = $q.defer();
resource.find_releases({
appId: appId,
env: env,
clusterName: clusterName,
namespaceName: namespaceName,
page: page
}, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
return {
release: createRelease,
findRelease: findReleases
}
}]);
...@@ -21,6 +21,14 @@ p, td, span { ...@@ -21,6 +21,14 @@ p, td, span {
word-break: break-all; word-break: break-all;
} }
.no-radius{
border-radius: 0px;
}
.hide-border-top{
border-top: 0px;
}
.logo { .logo {
width: 150px; width: 150px;
height: 50px; height: 50px;
...@@ -208,6 +216,7 @@ table th { ...@@ -208,6 +216,7 @@ table th {
.config-item-container .second-panel-heading .ns_btn { .config-item-container .second-panel-heading .ns_btn {
width: 25px; width: 25px;
height: 25px; height: 25px;
border-top: solid 1px #ffffff;
} }
.config-item-container .second-panel-heading .nav-tabs .node_active { .config-item-container .second-panel-heading .nav-tabs .node_active {
...@@ -244,9 +253,22 @@ table th { ...@@ -244,9 +253,22 @@ table th {
color: #555; color: #555;
font-size: 13px; font-size: 13px;
margin-bottom: 2px; margin-bottom: 2px;
}
.namespace-attribute-panel {
margin-left: 0px;
color: #fff;
border-top: 0px;
background: #f1f2f7;
}
.namespace-attribute-public{
background: #31708f;
width: 40px;
cursor: pointer;
} }
.second-panel-heading .nav-tabs { .second-panel-heading .nav-tabs {
border-bottom: 0px; border-bottom: 0px;
} }
...@@ -369,3 +391,48 @@ table th { ...@@ -369,3 +391,48 @@ table th {
height: 5px; height: 5px;
} }
.release-history .media-body{
padding-left: 20px;
}
.release-history .icon{
font-size: 13px;
}
.release-history .info{
font-size: 13px;
margin-left: 5px;
margin-top: 2px;
}
.release-history .user .info{
font-size: 22px;
}
.release-history .time{
padding-top: 8px;
}
.release-history .comment{
padding-top: 10px;
}
.release-history .table{
margin-top: 15px;
}
.release-history .badge-0{
background: #f0ad4e;
}
.release-history .badge-1{
background: #c3c3c3;
}
.release-history .badge-2{
background: #27AE60;
}
.release-history .badge-3{
background: #3478a8;
}
...@@ -10,12 +10,16 @@ ...@@ -10,12 +10,16 @@
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li><a href="http://conf.ctripcorp.com/display/FRAM/Apollo" target="_blank"> <li>
Help</span> <a href="http://conf.ctripcorp.com/display/FRAM/Apollo" target="_blank">
</a></li> <span class="glyphicon glyphicon-question-sign"></span> Help
</a>
</li>
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">{{userName}} <span class="caret"></span></a> aria-expanded="false"><span class="glyphicon glyphicon-user"></span>{{userName}} <span class="caret"></span></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a href="/user/logout">退出</a></li> <li><a href="/user/logout">退出</a></li>
</ul> </ul>
...@@ -25,8 +29,7 @@ ...@@ -25,8 +29,7 @@
<form class="navbar-form navbar-right form-inline" role="search"> <form class="navbar-form navbar-right form-inline" role="search">
<div class="form-group"> <div class="form-group">
<input type="text" class="form-control search-input" placeholder="应用ID/应用名" style="width: 350px" <input type="text" class="form-control search-input" placeholder="应用ID/应用名" style="width: 350px"
ng-model="searchKey" ng-change="changeSearchKey()" ng-focus="changeSearchKey()" ng-model="searchKey" ng-change="changeSearchKey()" ng-focus="changeSearchKey()">
ng-click="xx()">
<div class="row app-list" ng-show="shouldShowAppList"> <div class="row app-list" ng-show="shouldShowAppList">
<div ng-repeat="app in copyedApps" class="app-item" ng-class="{'app-selected':app.selected}" <div ng-repeat="app in copyedApps" class="app-item" ng-class="{'app-selected':app.selected}"
......
<div class="panel"> <div class="panel" style="border-top: 0px;">
<div class="row namespace-attribute-panel" ng-if="namespace.isPublic">
<div class="text-center namespace-attribute-public" data-tooltip="tooltip" data-placement="bottom"
title="点击跳转到公共Namespace" ng-click="goToParentAppConfigPage(namespace)">
公共
</div>
</div>
<header class="panel-heading"> <header class="panel-heading">
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<b ng-bind="namespace.viewName" style="font-size: 20px;"></b> <b ng-bind="namespace.viewName" style="font-size: 20px;"></b>
<span class="label label-info" ng-bind="namespace.format"></span> <span class="label label-info no-radius" ng-bind="namespace.format" ></span>
<span class="label label-primary" ng-show="namespace.itemModifiedCnt > 0">有修改 <span class="label label-primary no-radius" ng-show="namespace.itemModifiedCnt > 0" >有修改
<span class="badge label" ng-bind="namespace.itemModifiedCnt"></span></span> <span class="badge label" ng-bind="namespace.itemModifiedCnt"></span></span>
<span class="label label-warning" ng-show="namespace.lockOwner">当前修改者:{{namespace.lockOwner}}</span> <span class="label label-warning no-radius" ng-show="namespace.lockOwner">当前修改者:{{namespace.lockOwner}}</span>
</div> </div>
<div class="col-md-6 text-right"> <div class="col-md-6 text-right">
<button type="button" <button type="button"
...@@ -24,11 +31,11 @@ ...@@ -24,11 +31,11 @@
<img src="img/rollback.png"> <img src="img/rollback.png">
回滚 回滚
</button> </button>
<button type="button" class="btn btn-default btn-sm J_tableview_btn" disabled <a type="button" class="btn btn-default btn-sm J_tableview_btn"
href="/namespace/role.html?#/appid={{appId}}&namespaceName={{namespace.namespace.namespaceName}}"> href="/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{cluster}}&namespaceName={{namespace.namespace.namespaceName}}">
<img src="img/release-history.png"> <img src="img/release-history.png">
发布历史 发布历史
</button> </a>
<a type="button" class="btn btn-default btn-sm J_tableview_btn" <a type="button" class="btn btn-default btn-sm J_tableview_btn"
href="/namespace/role.html?#/appid={{appId}}&namespaceName={{namespace.namespace.namespaceName}}" href="/namespace/role.html?#/appid={{appId}}&namespaceName={{namespace.namespace.namespaceName}}"
ng-show="hasAssignUserPermission"> ng-show="hasAssignUserPermission">
...@@ -44,8 +51,10 @@ ...@@ -44,8 +51,10 @@
</div> </div>
</div> </div>
</header> </header>
<!--f1f2f7-->
<header class="panel-heading second-panel-heading" style="border-bottom: 0px"> <header class="panel-heading second-panel-heading">
<div class="row"> <div class="row">
<div class="col-md-5 pull-left"> <div class="col-md-5 pull-left">
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
......
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