Commit 26cb8582 authored by lepdou's avatar lepdou

portal v2

parent 11e8b799
......@@ -8,10 +8,12 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ctrip.apollo.biz.entity.Release;
import com.ctrip.apollo.biz.service.ConfigService;
import com.ctrip.apollo.biz.service.ReleaseService;
import com.ctrip.apollo.biz.service.ViewService;
import com.ctrip.apollo.biz.utils.BeanUtils;
import com.ctrip.apollo.core.dto.ReleaseDTO;
import com.ctrip.apollo.core.utils.StringUtils;
@RestController
public class ReleaseController {
......@@ -22,6 +24,9 @@ public class ReleaseController {
@Autowired
private ReleaseService releaseService;
@Autowired
private ConfigService configService;
@RequestMapping("/release/{releaseId}")
public ReleaseDTO findOne(@PathVariable("releaseId") long releaseId) {
Release release = releaseService.findOne(releaseId);
......@@ -35,4 +40,16 @@ public class ReleaseController {
List<Release> releases = viewSerivce.findReleases(appId, clusterName, namespaceName);
return BeanUtils.batchTransform(ReleaseDTO.class, releases);
}
@RequestMapping("/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/latest")
public ReleaseDTO findLatestRelease(@PathVariable("appId") String appId,
@PathVariable("clusterName") String clusterName,
@PathVariable("namespaceName") String namespaceName){
if (StringUtils.isContainEmpty(appId, clusterName, namespaceName)){
return null;
}
Release release = configService.findRelease(appId, clusterName, namespaceName);
return BeanUtils.transfrom(ReleaseDTO.class, release);
}
}
......@@ -43,7 +43,10 @@ public class BeanUtils {
* return BeanUtil.transform(UserDTO.class, userBean);
* </pre>
*/
public static <T> T transfrom(Class<T> clazz, Object src) {
public static <T> T transfrom(Class<T> clazz, Object src) {
if (src == null){
return null;
}
T instance = null;
try {
instance = clazz.newInstance();
......
......@@ -2,3 +2,4 @@ spring.datasource.url = jdbc:h2:mem:~/fxapolloconfigdb;mode=mysql
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy
spring.h2.console.enabled = true
spring.h2.console.settings.web-allow-others=true
......@@ -31,6 +31,20 @@ public class StringUtils {
return str == null || str.length() == 0;
}
public static boolean isContainEmpty(String... args){
if (args == null){
return false;
}
for (String arg: args){
if (arg == null || "".equals(arg)){
return true;
}
}
return false;
}
/**
* <p>
* Checks if a String is whitespace, empty ("") or null.
......
package com.ctrip.apollo.portal.api;
import com.google.common.base.Strings;
import com.ctrip.apollo.Apollo;
import com.ctrip.apollo.core.dto.AppDTO;
import com.ctrip.apollo.core.dto.ClusterDTO;
import com.ctrip.apollo.core.dto.ItemDTO;
import com.ctrip.apollo.core.dto.NamespaceDTO;
import com.ctrip.apollo.core.dto.ReleaseDTO;
import com.ctrip.apollo.core.utils.StringUtils;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class AdminServiceAPI {
......@@ -24,45 +24,61 @@ public class AdminServiceAPI {
}
}
@Service
public static class ConfigAPI extends API {
public static String CONFIG_RELEASE_API = "/configs/release/";
public static class NamespaceAPI extends API {
public ReleaseDTO[] getConfigByReleaseId(Apollo.Env env, long releaseId) {
if (releaseId <= 0) {
public NamespaceDTO[] findGroupsByAppAndCluster(String appId, Apollo.Env env,
String clusterName) {
if (StringUtils.isContainEmpty(appId, clusterName)) {
return null;
}
return restTemplate.getForObject(getAdminServiceHost(env) + CONFIG_RELEASE_API + releaseId,
ReleaseDTO[].class);
return restTemplate.getForObject(
getAdminServiceHost(env) + String.format("apps/%s/clusters/%s/namespaces", appId, clusterName),
NamespaceDTO[].class);
}
}
@Service
public static class ItemAPI extends API {
public ItemDTO[] getLatestConfigItemsByClusters(Apollo.Env env, List<Long> clusterIds) {
if (clusterIds == null || clusterIds.size() == 0) {
public ItemDTO[] findItems(String appId, Apollo.Env env, String clusterName, String namespace) {
if (StringUtils.isContainEmpty(appId, clusterName, namespace)) {
return null;
}
StringBuilder sb = new StringBuilder();
for (long clusterId : clusterIds) {
sb.append(clusterId).append(",");
}
return restTemplate.getForObject(getAdminServiceHost(env) + "/configs/latest?clusterIds="
+ sb.substring(0, sb.length() - 1), ItemDTO[].class);
return restTemplate.getForObject(getAdminServiceHost(env) + String
.format("apps/%s/clusters/%s/namespaces/%s/items", appId,
clusterName, namespace),
ItemDTO[].class);
}
}
@Service
public static class ClusterAPI extends API {
public static String CLUSTER_APP_API = "/cluster/app/";
public ClusterDTO[] getClustersByApp(Apollo.Env env, String appId) {
if (Strings.isNullOrEmpty(appId)) {
public ClusterDTO[] findClustersByApp(String appId, Apollo.Env env) {
if (StringUtils.isContainEmpty(appId)) {
return null;
}
return restTemplate.getForObject(getAdminServiceHost(env) + CLUSTER_APP_API + appId,
ClusterDTO[].class);
return restTemplate.getForObject(getAdminServiceHost(env) + String.format("apps/%s/clusters", appId),
ClusterDTO[].class);
}
}
@Service
public static class ReleaseAPI extends API{
public ReleaseDTO loadLatestRelease(String appId, Apollo.Env env, String clusterName, String namespace){
if (StringUtils.isContainEmpty(appId, clusterName, namespace)){
return null;
}
return restTemplate.getForObject(getAdminServiceHost(env) + String
.format("apps/%s/clusters/%s/namespaces/%s/releases/latest", appId,
clusterName, namespace), ReleaseDTO.class);
}
}
......
package com.ctrip.apollo.portal.controller;
import com.ctrip.apollo.Apollo;
import com.ctrip.apollo.portal.PortalSettings;
import com.google.common.base.Strings;
import com.ctrip.apollo.portal.entity.ClusterNavTree;
import com.ctrip.apollo.portal.service.AppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/envs")
public class EnvController {
@RequestMapping("/apps")
public class AppController {
@Autowired
private PortalSettings portalSettings;
private AppService appService;
@RequestMapping("")
public List<Apollo.Env> envs(){
return portalSettings.getEnvs();
@RequestMapping("/{appId}/navtree")
public ClusterNavTree nav(@PathVariable String appId) {
if (Strings.isNullOrEmpty(appId)) {
throw new IllegalArgumentException("app id can not be empty.");
}
return appService.buildClusterNavTree(appId);
}
}
package com.ctrip.apollo.portal.controller;
import com.google.common.base.Strings;
import com.ctrip.apollo.Apollo;
import com.ctrip.apollo.core.dto.AppConfigVO;
import com.ctrip.apollo.portal.constants.PortalConstants;
import com.ctrip.apollo.portal.exception.NotFoundException;
import com.ctrip.apollo.core.utils.StringUtils;
import com.ctrip.apollo.portal.entity.NamespaceVO;
import com.ctrip.apollo.portal.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -13,35 +11,21 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/configs")
@RequestMapping("")
public class ConfigController {
@Autowired
private ConfigService configService;
@RequestMapping("/{appId}/{env}/{versionId}")
public AppConfigVO detail(@PathVariable String appId, @PathVariable String env,
@PathVariable long versionId) {
if (Strings.isNullOrEmpty(appId) || Strings.isNullOrEmpty(env)) {
throw new IllegalArgumentException(
String.format("app id and env can not be empty. app id:%s , env:%s", appId, env));
@RequestMapping("/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces")
public List<NamespaceVO> findNamespaces(@PathVariable String appId, @PathVariable String env, @PathVariable String clusterName){
if (StringUtils.isContainEmpty(appId, env, clusterName)){
throw new IllegalArgumentException("app id and cluster name can not be empty");
}
Apollo.Env e = Apollo.Env.valueOf(env);
if (versionId == PortalConstants.LASTEST_VERSION_ID) {
return configService.loadLatestConfig(e, appId);
// } else if (versionId > 0) {
//
// return configService.loadReleaseConfig(e, appId, versionId);
//
}
else {
throw new NotFoundException();
}
return configService.findNampspaces(appId, Apollo.Env.valueOf(env), clusterName);
}
}
package com.ctrip.apollo.portal.entity;
import com.ctrip.apollo.Apollo;
import com.ctrip.apollo.core.dto.ClusterDTO;
import java.util.LinkedList;
import java.util.List;
public class ClusterNavTree {
private List<Node> nodes;
public void addNode(Node node){
if (nodes == null){
nodes = new LinkedList<>();
}
nodes.add(node);
}
public static class Node{
private Apollo.Env env;
private List<ClusterDTO> clusters;
public Node(Apollo.Env env){
this.env = env;
}
public Apollo.Env getEnv() {
return env;
}
public void setEnv(Apollo.Env env) {
this.env = env;
}
public List<ClusterDTO> getClusters() {
return clusters;
}
public void setClusters(List<ClusterDTO> clusters) {
this.clusters = clusters;
}
}
public List<Node> getNodes() {
return nodes;
}
public void setNodes(List<Node> nodes) {
this.nodes = nodes;
}
}
package com.ctrip.apollo.portal.entity;
import com.ctrip.apollo.core.dto.ItemDTO;
import com.ctrip.apollo.core.dto.NamespaceDTO;
import java.util.List;
public class NamespaceVO {
private NamespaceDTO namespace;
private int itemModifiedCnt;
private List<ItemVO> items;
public NamespaceDTO getNamespace() {
return namespace;
}
public void setNamespace(NamespaceDTO namespace) {
this.namespace = namespace;
}
public int getItemModifiedCnt() {
return itemModifiedCnt;
}
public void setItemModifiedCnt(int itemModifiedCnt) {
this.itemModifiedCnt = itemModifiedCnt;
}
public List<ItemVO> getItems() {
return items;
}
public void setItems(List<ItemVO> items) {
this.items = items;
}
public static class ItemVO{
private ItemDTO item;
private boolean isModified;
private String oldValue;
private String newValue;
public ItemDTO getItem() {
return item;
}
public void setItem(ItemDTO item) {
this.item = item;
}
public boolean isModified() {
return isModified;
}
public void setModified(boolean isModified) {
this.isModified = isModified;
}
public String getOldValue() {
return oldValue;
}
public void setOldValue(String oldValue) {
this.oldValue = oldValue;
}
public String getNewValue() {
return newValue;
}
public void setNewValue(String newValue) {
this.newValue = newValue;
}
}
}
package com.ctrip.apollo.portal.service;
import com.ctrip.apollo.Apollo;
import com.ctrip.apollo.portal.entity.ClusterNavTree;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AppService {
@Autowired
private ClusterService clusterService;
public ClusterNavTree buildClusterNavTree(String appId){
ClusterNavTree tree = new ClusterNavTree();
ClusterNavTree.Node localNode = new ClusterNavTree.Node(Apollo.Env.LOCAL);
localNode.setClusters(clusterService.findClusters(Apollo.Env.LOCAL, appId));
tree.addNode(localNode);
// ClusterNavTree.Node uatNode = new ClusterNavTree.Node(Apollo.Env.UAT);
// List<ClusterDTO> uatClusters = new LinkedList<>();
// uatClusters.add(defaultCluster);
// uatNode.setClusters(uatClusters);
// tree.addNode(uatNode);
return tree;
}
}
package com.ctrip.apollo.portal.service;
import com.ctrip.apollo.Apollo;
import com.ctrip.apollo.core.dto.ClusterDTO;
import com.ctrip.apollo.portal.api.AdminServiceAPI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
@Service
public class ClusterService {
@Autowired
private AdminServiceAPI.ClusterAPI clusterAPI;
public List<ClusterDTO> findClusters(Apollo.Env env, String appId){
return Arrays.asList(clusterAPI.findClustersByApp(appId, env));
}
}
......@@ -3,27 +3,11 @@ var appService = angular.module('app.service', ['ngResource']);
/** page module 定义*/
//项目主页
var application_module = angular.module('application', ['ngResource', 'ui.router', 'app.service', 'toastr', 'angular-loading-bar']);
var application_module = angular.module('application', ['ngResource','ui.router', 'app.service', 'toastr', 'angular-loading-bar', 'ngTable']);
//创建项目页面
var create_app_module = angular.module('create_app', ['ngResource', 'toastr', 'app.service', 'angular-loading-bar']);
/**router*/
application_module.config(['$stateProvider',
function ($stateProvider) {
$stateProvider
.state('config', {
templateUrl: '../../views/app/config.html',
controller: 'AppConfigController'
}).state('info', {
templateUrl: '../../views/app/info.html',
controller: 'AppInfoController'
}).state('setting', {
templateUrl: '../../views/app/setting.html'
});
}]).run(function ($state) {
$state.go('config');
});
......
appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
var app_resource = $resource('/apps/:appId', {}, {
load_navtree:{
methode: 'GET',
isArray:false,
url:'/apps/:appId/navtree'
},
load_app: {
method: 'GET',
isArray: false
......@@ -10,6 +15,17 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
}
});
return {
load_nav_tree: function loadNavTree(appId){
var d = $q.defer();
app_resource.load_navtree({
appId: appId
}, function(result){
d.resolve(result);
}, function(result){
d.reject(result);
});
return d.promise;
},
add: function add(app) {
var d = $q.defer();
app_resource.add_app({}, app, function (result) {
......
appService.service("ConfigService", ['$resource', '$q', function ($resource, $q) {
var config_source = $resource("/configs/:appId/:env/:versionId", {}, {
load_config: {
method: 'GET',
isArray: false
var config_source = $resource("", {}, {
load_all_groups: {
method:'GET',
isArray: true,
url:'/apps/:appId/env/:env/clusters/:clusterName/namespaces'
}
});
return {
load: function (appId, env, versionId) {
load_all_namespaces: function (appId, env, clusterName) {
var d = $q.defer();
config_source.load_config({
config_source.load_all_groups({
appId: appId,
env: env,
versionId: versionId
clusterName: clusterName
}, function (result) {
d.resolve(result);
}, function (result) {
de.reject(result);
d.reject(result);
});
return d.promise;
}
......
body {
color: #797979;
background: #f1f2f7;
background: #fff;
padding: 0px !important;
margin: 0px !important;
font-size: 13px;
padding-bottom: 50px;
min-height: 650px;
}
a{
cursor: pointer;
}
.container {
width: 100%;
min-height: 550px;
}
.footer {
height: 50px;
height: 100px;
width: 100%;
background: #F6F6F6;
padding-top: 10px;
padding-top: 40px;
}
/*panel*/
.panel-heading {
font-size: 16px;
height: 45px;
font-size: 14px;
background-color: #f5f5f5;
padding: 5px 20px;
}
/*sec-panel*/
.sec-panel {
/*padding-left: 5%;*/
}
.sec-panel .panel-heading {
font-size: 14px;
height: 28px;
padding: 5px 20px;
}
table th {
......@@ -49,22 +35,93 @@ table th {
background-color: #f5f5f5;
}
.app .tab-content {
background-color: #ffffff;
}
#config-info {
padding: 20px 0px;
min-height: 500px;
background-color: #ffffff;
}
#config-info .nav {
background-color: #f5f5f5;
}
#config-info .config-info-container {
padding: 20px 20px;
#config-edit {
border: 1px solid #ddd;
border-radius: 3px;
}
#config-edit .panel-heading {
border-bottom: 1px solid #ddd;
}
.tocify-header {
font-size: 14px;
}
.tocify-subheader {
font-size: 13px;
}
.Hide {
display: none;
}
.config-item-container .config-items {
height: 500px;
overflow: scroll;
}
.historyview {
padding: 50px 20px;
}
.historyview .commit {
padding: 5px 15px;
border: 1px solid #ddd;
}
.historyview img {
position: absolute;
left: -28px;
}
.historyview .media .row {
padding-left: 35px;
}
.historyview .list {
position: relative;
border-left: 3px solid #ddd;
}
#config-info nav {
margin-top: -20px;
.line {
width: 20px;
border: 1px solid #ddd;
}
.editable-table > tbody > tr > td {
padding: 4px
}
.editable-text {
padding-left: 4px;
padding-top: 4px;
padding-bottom: 4px;
display: inline-block;
}
.editable-table tbody > tr > td > .controls {
/ / width: 100 %
}
.editable-input {
padding-left: 3px;
}
.editable-input.input-sm {
height: 30px;
font-size: 14px;
padding-top: 4px;
padding-bottom: 4px;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -40,23 +40,23 @@ public class ConfigServiceTest {
private ServiceLocator serviceLocator;
@Spy
private AdminServiceAPI.ClusterAPI clusterAPI;
@Spy
private AdminServiceAPI.ConfigAPI configAPI;
// @Spy
// private AdminServiceAPI.ConfigAPI configAPI;
@Before
public void setUp() throws ServiceException {
ReflectionTestUtils.setField(clusterAPI, "restTemplate", restTemplate);
ReflectionTestUtils.setField(configAPI, "restTemplate", restTemplate);
ReflectionTestUtils.setField(clusterAPI, "serviceLocator", serviceLocator);
ReflectionTestUtils.setField(configAPI, "serviceLocator", serviceLocator);
String defaultAdminService = "http://localhost:8090";
ServiceDTO service = new ServiceDTO();
service.setHomepageUrl(defaultAdminService);
Mockito.doReturn(service).when(serviceLocator).getAdminService(Env.DEV);
// ReflectionTestUtils.setField(clusterAPI, "restTemplate", restTemplate);
// ReflectionTestUtils.setField(configAPI, "restTemplate", restTemplate);
//
// ReflectionTestUtils.setField(clusterAPI, "serviceLocator", serviceLocator);
// ReflectionTestUtils.setField(configAPI, "serviceLocator", serviceLocator);
//
// String defaultAdminService = "http://localhost:8090";
// ServiceDTO service = new ServiceDTO();
// service.setHomepageUrl(defaultAdminService);
// Mockito.doReturn(service).when(serviceLocator).getAdminService(Env.DEV);
}
// @Test
......
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