Commit 37451643 by lepdou

add namespace publish info tips

parent 7e4f6bcc
...@@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.RequestParam; ...@@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
import java.util.Map;
@RestController @RestController
public class NamespaceController { public class NamespaceController {
...@@ -89,4 +90,14 @@ public class NamespaceController { ...@@ -89,4 +90,14 @@ public class NamespaceController {
return BeanUtils.transfrom(NamespaceDTO.class, namespace); return BeanUtils.transfrom(NamespaceDTO.class, namespace);
} }
/**
* cluster -> cluster has not published namespaces?
*/
@RequestMapping("/apps/{appId}/namespaces/publish_info")
public Map<String, Boolean> namespacePublishInfo(@PathVariable String appId){
return namespaceService.namespacePublishInfo(appId);
}
} }
...@@ -6,6 +6,7 @@ import org.springframework.data.jpa.repository.Modifying; ...@@ -6,6 +6,7 @@ import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.Date;
import java.util.List; import java.util.List;
public interface ItemRepository extends PagingAndSortingRepository<Item, Long> { public interface ItemRepository extends PagingAndSortingRepository<Item, Long> {
...@@ -14,6 +15,8 @@ public interface ItemRepository extends PagingAndSortingRepository<Item, Long> { ...@@ -14,6 +15,8 @@ public interface ItemRepository extends PagingAndSortingRepository<Item, Long> {
List<Item> findByNamespaceIdOrderByLineNumAsc(Long namespaceId); List<Item> findByNamespaceIdOrderByLineNumAsc(Long namespaceId);
List<Item> findByNamespaceIdAndDataChangeLastModifiedTimeGreaterThan(Long namespaceId, Date date);
Item findFirst1ByNamespaceIdOrderByLineNumDesc(Long namespaceId); Item findFirst1ByNamespaceIdOrderByLineNumDesc(Long namespaceId);
@Modifying @Modifying
......
...@@ -12,13 +12,10 @@ public class AdminService { ...@@ -12,13 +12,10 @@ public class AdminService {
@Autowired @Autowired
private AppService appService; private AppService appService;
@Autowired @Autowired
private AppNamespaceService appNamespaceService; private AppNamespaceService appNamespaceService;
@Autowired @Autowired
private ClusterService clusterService; private ClusterService clusterService;
@Autowired @Autowired
private NamespaceService namespaceService; private NamespaceService namespaceService;
...@@ -38,4 +35,5 @@ public class AdminService { ...@@ -38,4 +35,5 @@ public class AdminService {
return app; return app;
} }
} }
...@@ -23,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional; ...@@ -23,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
...@@ -168,6 +169,10 @@ public class ItemService implements InitializingBean { ...@@ -168,6 +169,10 @@ public class ItemService implements InitializingBean {
} }
} }
public List<Item> findItemsModifiedAfterDate(long namespaceId, Date date) {
return itemRepository.findByNamespaceIdAndDataChangeLastModifiedTimeGreaterThan(namespaceId, date);
}
@Transactional @Transactional
public Item save(Item entity) { public Item save(Item entity) {
checkItemKeyLength(entity.getKey()); checkItemKeyLength(entity.getKey());
......
package com.ctrip.framework.apollo.biz.service; package com.ctrip.framework.apollo.biz.service;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.ctrip.framework.apollo.biz.entity.Audit; import com.ctrip.framework.apollo.biz.entity.Audit;
import com.ctrip.framework.apollo.biz.entity.Cluster; import com.ctrip.framework.apollo.biz.entity.Cluster;
import com.ctrip.framework.apollo.biz.entity.Item;
import com.ctrip.framework.apollo.biz.entity.Namespace; import com.ctrip.framework.apollo.biz.entity.Namespace;
import com.ctrip.framework.apollo.biz.entity.Release;
import com.ctrip.framework.apollo.biz.repository.NamespaceRepository; import com.ctrip.framework.apollo.biz.repository.NamespaceRepository;
import com.ctrip.framework.apollo.common.constants.GsonType;
import com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus; import com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus;
import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.BadRequestException;
...@@ -17,7 +23,9 @@ import org.springframework.transaction.annotation.Transactional; ...@@ -17,7 +23,9 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -25,6 +33,8 @@ import java.util.stream.Collectors; ...@@ -25,6 +33,8 @@ import java.util.stream.Collectors;
@Service @Service
public class NamespaceService { public class NamespaceService {
private Gson gson = new Gson();
@Autowired @Autowired
private NamespaceRepository namespaceRepository; private NamespaceRepository namespaceRepository;
@Autowired @Autowired
...@@ -246,5 +256,59 @@ public class NamespaceService { ...@@ -246,5 +256,59 @@ public class NamespaceService {
} }
public Map<String, Boolean> namespacePublishInfo(String appId) {
List<Cluster> clusters = clusterService.findParentClusters(appId);
if (CollectionUtils.isEmpty(clusters)) {
throw new BadRequestException("app not exist");
}
Map<String, Boolean> clusterHasNotPublishedItems = Maps.newHashMap();
for (Cluster cluster : clusters) {
String clusterName = cluster.getName();
List<Namespace> namespaces = findNamespaces(appId, clusterName);
for (Namespace namespace: namespaces) {
boolean isNamespaceNotPublished = isNamespaceNotPublished(namespace);
if (isNamespaceNotPublished){
clusterHasNotPublishedItems.put(clusterName, true);
break;
}
}
clusterHasNotPublishedItems.putIfAbsent(clusterName, false);
}
return clusterHasNotPublishedItems;
}
private boolean isNamespaceNotPublished(Namespace namespace) {
Release latestRelease = releaseService.findLatestActiveRelease(namespace);
long namespaceId = namespace.getId();
if (latestRelease == null) {
Item lastItem = itemService.findLastOne(namespaceId);
return lastItem != null;
}
Date lastPublishTime = latestRelease.getDataChangeLastModifiedTime();
List<Item> itemsModifiedAfterLastPublish = itemService.findItemsModifiedAfterDate(namespaceId, lastPublishTime);
if (CollectionUtils.isEmpty(itemsModifiedAfterLastPublish)) {
return false;
}
Map<String, String> publishedConfiguration = gson.fromJson(latestRelease.getConfigurations(), GsonType.CONFIG);
for (Item item: itemsModifiedAfterLastPublish) {
if (!Objects.equals(item.getValue(), publishedConfiguration.get(item.getKey()))){
return true;
}
}
return false;
}
} }
package com.ctrip.framework.apollo.biz.service;
import com.ctrip.framework.apollo.biz.AbstractUnitTest;
import com.ctrip.framework.apollo.biz.entity.Cluster;
import com.ctrip.framework.apollo.biz.entity.Item;
import com.ctrip.framework.apollo.biz.entity.Namespace;
import com.ctrip.framework.apollo.biz.entity.Release;
import com.ctrip.framework.apollo.biz.repository.NamespaceRepository;
import com.ctrip.framework.apollo.core.ConfigConsts;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.Collections;
import java.util.Map;
import java.util.Random;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.when;
public class NamespacePublishInfoTest extends AbstractUnitTest {
@Mock
private ClusterService clusterService;
@Mock
private ReleaseService releaseService;
@Mock
private ItemService itemService;
@Mock
private NamespaceRepository namespaceRepository;
@InjectMocks
private NamespaceService namespaceService;
private String testApp = "testApp";
@Test
public void testNamespaceNotEverPublishedButHasItems() {
Cluster cluster = createCluster(ConfigConsts.CLUSTER_NAME_DEFAULT);
Namespace namespace = createNamespace(ConfigConsts.CLUSTER_NAME_DEFAULT, ConfigConsts.NAMESPACE_APPLICATION);
Item item = createItem(namespace.getId(), "a", "b");
when(clusterService.findParentClusters(testApp)).thenReturn(Collections.singletonList(cluster));
when(namespaceRepository.findByAppIdAndClusterNameOrderByIdAsc(testApp, ConfigConsts.CLUSTER_NAME_DEFAULT))
.thenReturn(Collections.singletonList(namespace));
when(itemService.findLastOne(anyLong())).thenReturn(item);
Map<String, Boolean> result = namespaceService.namespacePublishInfo(testApp);
Assert.assertEquals(1, result.size());
Assert.assertTrue(result.get(ConfigConsts.CLUSTER_NAME_DEFAULT));
}
@Test
public void testNamespaceEverPublishedAndNotModifiedAfter() {
Cluster cluster = createCluster(ConfigConsts.CLUSTER_NAME_DEFAULT);
Namespace namespace = createNamespace(ConfigConsts.CLUSTER_NAME_DEFAULT, ConfigConsts.NAMESPACE_APPLICATION);
Item item = createItem(namespace.getId(), "a", "b");
Release release = createRelease("{\"a\":\"b\"}");
when(clusterService.findParentClusters(testApp)).thenReturn(Collections.singletonList(cluster));
when(namespaceRepository.findByAppIdAndClusterNameOrderByIdAsc(testApp, ConfigConsts.CLUSTER_NAME_DEFAULT))
.thenReturn(Collections.singletonList(namespace));
when(releaseService.findLatestActiveRelease(namespace)).thenReturn(release);
when(itemService.findItemsModifiedAfterDate(anyLong(), anyObject())).thenReturn(Collections.singletonList(item));
Map<String, Boolean> result = namespaceService.namespacePublishInfo(testApp);
Assert.assertEquals(1, result.size());
Assert.assertFalse(result.get(ConfigConsts.CLUSTER_NAME_DEFAULT));
}
@Test
public void testNamespaceEverPublishedAndModifiedAfter() {
Cluster cluster = createCluster(ConfigConsts.CLUSTER_NAME_DEFAULT);
Namespace namespace = createNamespace(ConfigConsts.CLUSTER_NAME_DEFAULT, ConfigConsts.NAMESPACE_APPLICATION);
Item item = createItem(namespace.getId(), "a", "b");
Release release = createRelease("{\"a\":\"c\"}");
when(clusterService.findParentClusters(testApp)).thenReturn(Collections.singletonList(cluster));
when(namespaceRepository.findByAppIdAndClusterNameOrderByIdAsc(testApp, ConfigConsts.CLUSTER_NAME_DEFAULT))
.thenReturn(Collections.singletonList(namespace));
when(releaseService.findLatestActiveRelease(namespace)).thenReturn(release);
when(itemService.findItemsModifiedAfterDate(anyLong(), anyObject())).thenReturn(Collections.singletonList(item));
Map<String, Boolean> result = namespaceService.namespacePublishInfo(testApp);
Assert.assertEquals(1, result.size());
Assert.assertTrue(result.get(ConfigConsts.CLUSTER_NAME_DEFAULT));
}
private Cluster createCluster(String clusterName) {
Cluster cluster = new Cluster();
cluster.setAppId(testApp);
cluster.setName(clusterName);
cluster.setParentClusterId(0);
return cluster;
}
private Namespace createNamespace(String clusterName, String namespaceName) {
Namespace namespace = new Namespace();
namespace.setAppId(testApp);
namespace.setClusterName(clusterName);
namespace.setNamespaceName(namespaceName);
namespace.setId(new Random().nextLong());
return namespace;
}
private Item createItem(long namespaceId, String key, String value) {
Item item = new Item();
item.setNamespaceId(namespaceId);
item.setKey(key);
item.setValue(value);
return item;
}
private Release createRelease(String configuration) {
Release release = new Release();
release.setConfigurations(configuration);
return release;
}
}
...@@ -32,6 +32,7 @@ import org.springframework.util.MultiValueMap; ...@@ -32,6 +32,7 @@ import org.springframework.util.MultiValueMap;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -62,6 +63,10 @@ public class AdminServiceAPI { ...@@ -62,6 +63,10 @@ public class AdminServiceAPI {
@Service @Service
public static class NamespaceAPI extends API { public static class NamespaceAPI extends API {
private ParameterizedTypeReference<Map<String, Boolean>>
typeReference = new ParameterizedTypeReference<Map<String, Boolean>>() {
};
public List<NamespaceDTO> findNamespaceByCluster(String appId, Env env, String clusterName) { public List<NamespaceDTO> findNamespaceByCluster(String appId, Env env, String clusterName) {
NamespaceDTO[] namespaceDTOs = restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces", NamespaceDTO[] namespaceDTOs = restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces",
NamespaceDTO[].class, appId, NamespaceDTO[].class, appId,
...@@ -100,6 +105,10 @@ public class AdminServiceAPI { ...@@ -100,6 +105,10 @@ public class AdminServiceAPI {
namespaceName, operator); namespaceName, operator);
} }
public Map<String, Boolean> getNamespacePublishInfo(Env env, String appId) {
return restTemplate.get(env, "apps/{appId}/namespaces/publish_info", typeReference, appId).getBody();
}
} }
@Service @Service
......
...@@ -35,10 +35,10 @@ import org.springframework.web.bind.annotation.PathVariable; ...@@ -35,10 +35,10 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
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;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
import java.util.Map;
import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel; import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;
...@@ -169,4 +169,18 @@ public class NamespaceController { ...@@ -169,4 +169,18 @@ public class NamespaceController {
return createdAppNamespace; return createdAppNamespace;
} }
/**
* env -> cluster -> cluster has not published namespace?
* Example:
* dev ->
* default -> true (default cluster has not published namespace)
* customCluster -> false (customCluster cluster's all namespaces had published)
*
*/
@RequestMapping("/apps/{appId}/namespaces/publish_info")
public Map<String, Map<String, Boolean>> getNamespacesPublishInfo(@PathVariable String appId) {
return namespaceService.getNamespacesPublishInfo(appId);
}
} }
package com.ctrip.framework.apollo.portal.service; package com.ctrip.framework.apollo.portal.service;
import com.google.common.collect.Maps;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.ctrip.framework.apollo.common.constants.GsonType; import com.ctrip.framework.apollo.common.constants.GsonType;
...@@ -14,6 +15,7 @@ import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; ...@@ -14,6 +15,7 @@ import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.utils.StringUtils; import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.components.PortalSettings;
import com.ctrip.framework.apollo.portal.constant.CatEventType; import com.ctrip.framework.apollo.portal.constant.CatEventType;
import com.ctrip.framework.apollo.portal.entity.bo.ItemBO; import com.ctrip.framework.apollo.portal.entity.bo.ItemBO;
import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO; import com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO;
...@@ -40,6 +42,8 @@ public class NamespaceService { ...@@ -40,6 +42,8 @@ public class NamespaceService {
private Gson gson = new Gson(); private Gson gson = new Gson();
@Autowired @Autowired
private PortalSettings portalSettings;
@Autowired
private UserInfoHolder userInfoHolder; private UserInfoHolder userInfoHolder;
@Autowired @Autowired
private ItemService itemService; private ItemService itemService;
...@@ -100,10 +104,10 @@ public class NamespaceService { ...@@ -100,10 +104,10 @@ public class NamespaceService {
List<NamespaceBO> namespaceBOs = new LinkedList<>(); List<NamespaceBO> namespaceBOs = new LinkedList<>();
for (NamespaceDTO namespace : namespaces) { for (NamespaceDTO namespace : namespaces) {
NamespaceBO namesapceBO = null; NamespaceBO namespaceBO = null;
try { try {
namesapceBO = transformNamespace2BO(appId, env, clusterName, namespace); namespaceBO = transformNamespace2BO(appId, env, clusterName, namespace);
namespaceBOs.add(namesapceBO); namespaceBOs.add(namespaceBO);
} catch (Exception e) { } catch (Exception e) {
logger.error("parse namespace error. app id:{}, env:{}, clusterName:{}, namespace:{}", logger.error("parse namespace error. app id:{}, env:{}, clusterName:{}, namespace:{}",
appId, env, clusterName, namespace.getNamespaceName(), e); appId, env, clusterName, namespace.getNamespaceName(), e);
...@@ -131,6 +135,17 @@ public class NamespaceService { ...@@ -131,6 +135,17 @@ public class NamespaceService {
return transformNamespace2BO(appId, env, actualClusterName, namespace); return transformNamespace2BO(appId, env, actualClusterName, namespace);
} }
public Map<String, Map<String, Boolean>> getNamespacesPublishInfo(String appId) {
Map<String, Map<String, Boolean>> result = Maps.newHashMap();
List<Env> envs = portalSettings.getActiveEnvs();
for (Env env: envs) {
result.put(env.toString(), namespaceAPI.getNamespacePublishInfo(env, appId));
}
return result;
}
private NamespaceBO transformNamespace2BO(String appId, Env env, String clusterName, NamespaceDTO namespace) { private NamespaceBO transformNamespace2BO(String appId, Env env, String clusterName, NamespaceDTO namespace) {
NamespaceBO namespaceBO = new NamespaceBO(); NamespaceBO namespaceBO = new NamespaceBO();
namespaceBO.setBaseInfo(namespace); namespaceBO.setBaseInfo(namespace);
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
<strong>Tips:</strong> <strong>Tips:</strong>
<ul> <ul>
<li>通过添加集群,可以使同一份程序在不同的集群(如不同的数据中心)使用不同的配置</li> <li>通过添加集群,可以使同一份程序在不同的集群(如不同的数据中心)使用不同的配置</li>
<li>如果不同集群使用一样的配置,则没有必要创建集群</li>
<li> <li>
Apollo默认会读取机器上/opt/settings/server.properties(linux)或C:\opt\settings\server.properties(windows)文件中的idc属性作为集群名字, Apollo默认会读取机器上/opt/settings/server.properties(linux)或C:\opt\settings\server.properties(windows)文件中的idc属性作为集群名字,
如SHAJQ(金桥数据中心)、SHAOY(欧阳数据中心) 如SHAJQ(金桥数据中心)、SHAOY(欧阳数据中心)
......
...@@ -137,7 +137,7 @@ ...@@ -137,7 +137,7 @@
<!--namespaces--> <!--namespaces-->
<div class="col-md-10 col-xs-10 col-sm-10 config-item-container hide" <div class="col-md-10 col-xs-10 col-sm-10 config-item-container hide"
ng-controller="ConfigNamespaceController"> ng-controller="ConfigNamespaceController">
<div class="alert alert-warning alert-dismissible" role="alert" <div class="alert alert-info alert-dismissible" role="alert"
ng-show="(!hideTip || !hideTip[pageContext.appId][pageContext.clusterName]) && envMapClusters[pageContext.env]"> ng-show="(!hideTip || !hideTip[pageContext.appId][pageContext.clusterName]) && envMapClusters[pageContext.env]">
<button class="btn btn-sm btn-default pull-right" style="margin-top: -7px;margin-right:-15px;" <button class="btn btn-sm btn-default pull-right" style="margin-top: -7px;margin-right:-15px;"
...@@ -146,7 +146,7 @@ ...@@ -146,7 +146,7 @@
<!--default cluster tip --> <!--default cluster tip -->
<div ng-show="pageContext.clusterName == 'default'"> <div ng-show="pageContext.clusterName == 'default'">
<strong>注意:</strong>所有不属于 <strong>注意: </strong>所有不属于
<span ng-bind="envMapClusters[pageContext.env]"></span> <span ng-bind="envMapClusters[pageContext.env]"></span>
集群的实例会使用default集群(当前页面)的配置,属于 集群的实例会使用default集群(当前页面)的配置,属于
<span ng-bind="envMapClusters[pageContext.env]"></span> <span ng-bind="envMapClusters[pageContext.env]"></span>
...@@ -164,6 +164,11 @@ ...@@ -164,6 +164,11 @@
</div> </div>
<div class="alert alert-info"
ng-if="hasNotPublishNamespace">
<p><b>注意:</b>以下环境/集群有未发布的配置,客户端获取不到未发布的配置,请及时发布。</p>
<p><mark ng-bind="namespacePublishInfo.join(',')"></mark></p>
</div>
<apollonspanel ng-repeat="namespace in namespaces" <apollonspanel ng-repeat="namespace in namespaces"
namespace="namespace" namespace="namespace"
...@@ -336,6 +341,7 @@ ...@@ -336,6 +341,7 @@
<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/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/NamespaceService.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>
<script type="application/javascript" src="scripts/services/InstanceService.js"></script> <script type="application/javascript" src="scripts/services/InstanceService.js"></script>
......
...@@ -20,9 +20,11 @@ $(document).ready(function () { ...@@ -20,9 +20,11 @@ $(document).ready(function () {
}, 2500); }, 2500);
setTimeout(function () { setTimeout(function () {
$("textarea").niceScroll({cursoropacitymax: 0}); $("textarea").niceScroll({cursoropacitymax: 0});
$("pre").niceScroll({cursoropacitymax: 0}); $("pre").niceScroll({cursoropacitymax: 0});
$(".release-history-list").niceScroll({cursoropacitymax: 0}); $(".release-history-list").niceScroll({cursoropacitymax: 0});
}, 2500); }, 2500);
}); });
......
...@@ -119,6 +119,7 @@ function ConfigBaseInfoController($rootScope, $scope, $location, toastr, EventMa ...@@ -119,6 +119,7 @@ function ConfigBaseInfoController($rootScope, $scope, $location, toastr, EventMa
} }
function loadNavTree() { function loadNavTree() {
AppService.load_nav_tree($rootScope.pageContext.appId).then(function (result) { AppService.load_nav_tree($rootScope.pageContext.appId).then(function (result) {
var navTree = []; var navTree = [];
var nodes = AppUtil.collectData(result); var nodes = AppUtil.collectData(result);
...@@ -140,6 +141,7 @@ function ConfigBaseInfoController($rootScope, $scope, $location, toastr, EventMa ...@@ -140,6 +141,7 @@ function ConfigBaseInfoController($rootScope, $scope, $location, toastr, EventMa
} }
var node = {}; var node = {};
node.text = env.env; node.text = env.env;
var clusterNodes = []; var clusterNodes = [];
//如果env下面只有一个default集群则不显示集群列表 //如果env下面只有一个default集群则不显示集群列表
...@@ -150,6 +152,7 @@ function ConfigBaseInfoController($rootScope, $scope, $location, toastr, EventMa ...@@ -150,6 +152,7 @@ function ConfigBaseInfoController($rootScope, $scope, $location, toastr, EventMa
node.state.selected = true; node.state.selected = true;
} }
node.selectable = true; node.selectable = true;
} else { } else {
node.selectable = false; node.selectable = false;
//cluster list //cluster list
...@@ -169,6 +172,7 @@ function ConfigBaseInfoController($rootScope, $scope, $location, toastr, EventMa ...@@ -169,6 +172,7 @@ function ConfigBaseInfoController($rootScope, $scope, $location, toastr, EventMa
clusterNode.tags = ['集群']; clusterNode.tags = ['集群'];
clusterNode.parentNode = parentNode; clusterNode.parentNode = parentNode;
clusterNodes.push(clusterNode); clusterNodes.push(clusterNode);
}); });
} }
node.nodes = clusterNodes; node.nodes = clusterNodes;
...@@ -229,6 +233,7 @@ function ConfigBaseInfoController($rootScope, $scope, $location, toastr, EventMa ...@@ -229,6 +233,7 @@ function ConfigBaseInfoController($rootScope, $scope, $location, toastr, EventMa
}, function (result) { }, function (result) {
toastr.error(AppUtil.errorMsg(result), "系统出错,请重试或联系系统负责人"); toastr.error(AppUtil.errorMsg(result), "系统出错,请重试或联系系统负责人");
}); });
} }
function handleFavorite() { function handleFavorite() {
......
application_module.controller("ConfigNamespaceController", application_module.controller("ConfigNamespaceController",
['$rootScope', '$scope', 'toastr', 'AppUtil', 'EventManager', 'ConfigService', ['$rootScope', '$scope', 'toastr', 'AppUtil', 'EventManager', 'ConfigService',
'PermissionService', 'UserService', 'NamespaceBranchService', 'PermissionService', 'UserService', 'NamespaceBranchService', 'NamespaceService',
controller]); controller]);
function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigService, function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigService,
PermissionService, UserService, NamespaceBranchService) { PermissionService, UserService, NamespaceBranchService, NamespaceService) {
$scope.rollback = rollback; $scope.rollback = rollback;
$scope.preDeleteItem = preDeleteItem; $scope.preDeleteItem = preDeleteItem;
...@@ -21,9 +21,15 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer ...@@ -21,9 +21,15 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer
$scope.lockCheck = lockCheck; $scope.lockCheck = lockCheck;
init(); init();
function init() { function init() {
initRole();
initUser();
initPublishInfo();
}
function initRole() {
PermissionService.get_app_role_users($rootScope.pageContext.appId) PermissionService.get_app_role_users($rootScope.pageContext.appId)
.then(function (result) { .then(function (result) {
var masterUsers = ''; var masterUsers = '';
...@@ -34,18 +40,56 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer ...@@ -34,18 +40,56 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer
}, function (result) { }, function (result) {
}); });
}
function initUser() {
UserService.load_user().then(function (result) { UserService.load_user().then(function (result) {
$scope.currentUser = result.userId; $scope.currentUser = result.userId;
}); });
} }
function initPublishInfo() {
NamespaceService.getNamespacePublishInfo($rootScope.pageContext.appId)
.then(function (result) {
if (!result) {
return;
}
$scope.hasNotPublishNamespace = false;
var namespacePublishInfo = [];
Object.keys(result).forEach(function (env) {
if (env.indexOf("$") >= 0) {
return;
}
var envPublishInfo = result[env];
Object.keys(envPublishInfo).forEach(function (cluster) {
var clusterPublishInfo = envPublishInfo[cluster];
if (clusterPublishInfo) {
$scope.hasNotPublishNamespace = true;
if (Object.keys(envPublishInfo).length > 1) {
namespacePublishInfo.push("[" + env + ", " + cluster + "]");
} else {
namespacePublishInfo.push("[" + env + "]");
}
}
})
});
$scope.namespacePublishInfo = namespacePublishInfo;
});
}
EventManager.subscribe(EventManager.EventType.REFRESH_NAMESPACE, EventManager.subscribe(EventManager.EventType.REFRESH_NAMESPACE,
function (context) { function (context) {
if (context.namespace){ if (context.namespace) {
refreshSingleNamespace(context.namespace); refreshSingleNamespace(context.namespace);
}else { } else {
refreshAllNamespaces(); refreshAllNamespaces();
} }
...@@ -57,20 +101,19 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer ...@@ -57,20 +101,19 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer
} }
ConfigService.load_all_namespaces($rootScope.pageContext.appId, ConfigService.load_all_namespaces($rootScope.pageContext.appId,
$rootScope.pageContext.env, $rootScope.pageContext.env,
$rootScope.pageContext.clusterName).then( $rootScope.pageContext.clusterName).then(
function (result) { function (result) {
$scope.namespaces = result; $scope.namespaces = result;
$('.config-item-container').removeClass('hide'); $('.config-item-container').removeClass('hide');
initPublishInfo();
}, function (result) { }, function (result) {
toastr.error(AppUtil.errorMsg(result), "加载配置信息出错"); toastr.error(AppUtil.errorMsg(result), "加载配置信息出错");
}); });
} }
function refreshSingleNamespace(namespace) { function refreshSingleNamespace(namespace) {
if ($rootScope.pageContext.env == '') { if ($rootScope.pageContext.env == '') {
return; return;
...@@ -83,17 +126,18 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer ...@@ -83,17 +126,18 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer
function (result) { function (result) {
$scope.namespaces.forEach(function (namespace, index) { $scope.namespaces.forEach(function (namespace, index) {
if (namespace.baseInfo.namespaceName == result.baseInfo.namespaceName){ if (namespace.baseInfo.namespaceName == result.baseInfo.namespaceName) {
$scope.namespaces[index] = result; $scope.namespaces[index] = result;
} }
}) });
initPublishInfo();
}, function (result) { }, function (result) {
toastr.error(AppUtil.errorMsg(result), "加载配置信息出错"); toastr.error(AppUtil.errorMsg(result), "加载配置信息出错");
}); });
} }
function rollback() { function rollback() {
EventManager.emit(EventManager.EventType.ROLLBACK_NAMESPACE); EventManager.emit(EventManager.EventType.ROLLBACK_NAMESPACE);
} }
...@@ -268,10 +312,6 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer ...@@ -268,10 +312,6 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer
} }
new Clipboard('.clipboard'); new Clipboard('.clipboard');
} }
......
...@@ -101,6 +101,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na ...@@ -101,6 +101,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
initNamespaceInstancesCount(namespace); initNamespaceInstancesCount(namespace);
initPermission(namespace); initPermission(namespace);
initLinkedNamespace(namespace); initLinkedNamespace(namespace);
loadInstanceInfo(namespace);
function initNamespaceBranch(namespace) { function initNamespaceBranch(namespace) {
NamespaceBranchService.findNamespaceBranch(scope.appId, scope.env, NamespaceBranchService.findNamespaceBranch(scope.appId, scope.env,
...@@ -237,12 +238,11 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na ...@@ -237,12 +238,11 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
linkNamespaceItemKeys.push(key); linkNamespaceItemKeys.push(key);
}); });
publicNamespace.viewItems = []; publicNamespace.viewItems = [];
publicNamespace.items.forEach(function (item) { publicNamespace.items.forEach(function (item) {
var key = item.item.key; var key = item.item.key;
if (key){ if (key) {
publicNamespace.viewItems.push(item); publicNamespace.viewItems.push(item);
} }
...@@ -250,7 +250,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na ...@@ -250,7 +250,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
if (item.isModified || item.isDeleted) { if (item.isModified || item.isDeleted) {
publicNamespace.isModified = true; publicNamespace.isModified = true;
} else if (key){ } else if (key) {
publicNamespace.hasPublishedItem = true; publicNamespace.hasPublishedItem = true;
} }
}); });
...@@ -410,28 +410,26 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na ...@@ -410,28 +410,26 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
if (namespace_instance_view_type.LATEST_RELEASE == type) { if (namespace_instance_view_type.LATEST_RELEASE == type) {
if (!namespace.latestRelease) { if (!namespace.latestRelease) {
ReleaseService.findActiveReleases(scope.appId, ReleaseService.findLatestActiveRelease(scope.appId,
scope.env, scope.env,
namespace.baseInfo.clusterName, namespace.baseInfo.clusterName,
namespace.baseInfo.namespaceName, namespace.baseInfo.namespaceName)
0, 1).then(function (result) { .then(function (result) {
if (!result) {
var latestRelease = result[0]; namespace.latestReleaseInstances = {};
if (!latestRelease) { namespace.latestReleaseInstances.total = 0;
namespace.latestReleaseInstances = {}; return;
namespace.latestReleaseInstances.total = 0; }
return; namespace.latestRelease = result;
} InstanceService.findInstancesByRelease(scope.env,
namespace.latestRelease = latestRelease; namespace.latestRelease.id,
InstanceService.findInstancesByRelease(scope.env, namespace.latestReleaseInstancesPage,
latestRelease.id, size)
namespace.latestReleaseInstancesPage, .then(function (result) {
size) namespace.latestReleaseInstances = result;
.then(function (result) { namespace.latestReleaseInstancesPage++;
namespace.latestReleaseInstances = result; })
namespace.latestReleaseInstancesPage++; });
})
});
} else { } else {
InstanceService.findInstancesByRelease(scope.env, InstanceService.findInstancesByRelease(scope.env,
namespace.latestRelease.id, namespace.latestRelease.id,
...@@ -781,8 +779,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na ...@@ -781,8 +779,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
setTimeout(function () { setTimeout(function () {
scope.namespace.show = true; scope.namespace.show = true;
}, 200); }, 70);
} }
} }
} }
......
...@@ -14,41 +14,65 @@ appService.service("NamespaceService", ['$resource', '$q', function ($resource, ...@@ -14,41 +14,65 @@ appService.service("NamespaceService", ['$resource', '$q', function ($resource,
method: 'POST', method: 'POST',
url: '/apps/:appId/appnamespaces', url: '/apps/:appId/appnamespaces',
isArray: false isArray: false
},
getNamespacePublishInfo: {
method: 'GET',
url: '/apps/:appId/namespaces/publish_info'
} }
}); });
function find_public_namespaces() {
var d = $q.defer();
namespace_source.find_public_namespaces({}, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
function createNamespace(appId, namespaceCreationModel) {
var d = $q.defer();
namespace_source.createNamespace({
appId: appId
}, namespaceCreationModel, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
function createAppNamespace(appId, appnamespace) {
var d = $q.defer();
namespace_source.createAppNamespace({
appId: appId
}, appnamespace, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
function getNamespacePublishInfo(appId) {
var d = $q.defer();
namespace_source.getNamespacePublishInfo({
appId: appId
}, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
})
return d.promise;
}
return { return {
find_public_namespaces: function () { find_public_namespaces: find_public_namespaces,
var d = $q.defer(); createNamespace: createNamespace,
namespace_source.find_public_namespaces({}, function (result) { createAppNamespace: createAppNamespace,
d.resolve(result); getNamespacePublishInfo: getNamespacePublishInfo
}, function (result) {
d.reject(result);
});
return d.promise;
},
createNamespace: function (appId, namespaceCreationModel) {
var d = $q.defer();
namespace_source.createNamespace({
appId: appId
}, namespaceCreationModel, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
createAppNamespace: function (appId, appnamespace) {
var d = $q.defer();
namespace_source.createAppNamespace({
appId: appId
}, appnamespace, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
} }
}]); }]);
...@@ -10,7 +10,9 @@ ...@@ -10,7 +10,9 @@
<b class="namespace-name" ng-bind="namespace.viewName" <b class="namespace-name" ng-bind="namespace.viewName"
data-tooltip="tooltip" data-placement="bottom" title="{{namespace.comment}}"></b> data-tooltip="tooltip" data-placement="bottom" title="{{namespace.comment}}"></b>
<span class="label label-info no-radius namespace-label" ng-bind="namespace.format"></span> <span class="label label-info no-radius namespace-label" ng-bind="namespace.format"></span>
<span class="label label-warning no-radius namespace-label" ng-show="namespace.itemModifiedCnt > 0">有修改 <span class="label label-warning no-radius namespace-label modify-tip"
ng-show="namespace.itemModifiedCnt > 0">
有修改
<span class="badge label badge-white namespace-label" ng-bind="namespace.itemModifiedCnt"></span> <span class="badge label badge-white namespace-label" ng-bind="namespace.itemModifiedCnt"></span>
</span> </span>
<span class="label label-primary no-radius namespace-label" <span class="label label-primary no-radius namespace-label"
...@@ -67,7 +69,7 @@ ...@@ -67,7 +69,7 @@
<!--second header--> <!--second header-->
<header class="panel-heading second-panel-heading"> <header class="panel-heading second-panel-heading">
<div class="row"> <div class="row">
<div class="col-md-8 pull-left"> <div class="col-md-6 pull-left">
<!--master branch nav tabs--> <!--master branch nav tabs-->
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li role="presentation" ng-click="switchView(namespace, 'table')" <li role="presentation" ng-click="switchView(namespace, 'table')"
...@@ -99,7 +101,7 @@ ...@@ -99,7 +101,7 @@
</li> </li>
</ul> </ul>
</div> </div>
<div class="col-md-4 text-right"> <div class="col-md-6 text-right">
<a class="clipboard" <a class="clipboard"
data-clipboard-text="{{namespace.text}}" data-clipboard-text="{{namespace.text}}"
data-tooltip="tooltip" data-placement="bottom" title="复制文本" data-tooltip="tooltip" data-placement="bottom" title="复制文本"
...@@ -161,6 +163,9 @@ ...@@ -161,6 +163,9 @@
<!--table view--> <!--table view-->
<div class="namespace-view-table" ng-show="namespace.viewType == 'table'"> <div class="namespace-view-table" ng-show="namespace.viewType == 'table'">
<div class="well well-sm no-radius text-center" ng-show="!namespace.latestRelease">
<span style="color: red"> Tips: 此namespace从来没有发布过,Apollo客户端将获取不到配置并记录404日志信息,请及时发布。</span>
</div>
<!--not link namespace--> <!--not link namespace-->
<div ng-if="!namespace.isLinkedNamespace"> <div ng-if="!namespace.isLinkedNamespace">
<div class="col-md-8 col-lg-offset-2 search-input" ng-show="namespace.showSearchInput"> <div class="col-md-8 col-lg-offset-2 search-input" ng-show="namespace.showSearchInput">
......
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