Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
apollo
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
apollo
Commits
5c6081a0
Commit
5c6081a0
authored
Jul 07, 2016
by
lepdou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
namespace as file
parent
060126fd
Changes
91
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
91 changed files
with
2446 additions
and
751 deletions
+2446
-751
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/NamespaceLockAspect.java
...ramework/apollo/adminservice/aop/NamespaceLockAspect.java
+20
-15
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppNamespaceController.java
...pollo/adminservice/controller/AppNamespaceController.java
+2
-14
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ClusterController.java
...ork/apollo/adminservice/controller/ClusterController.java
+1
-2
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceController.java
...k/apollo/adminservice/controller/NamespaceController.java
+1
-2
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Item.java
...main/java/com/ctrip/framework/apollo/biz/entity/Item.java
+2
-0
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppNamespaceRepository.java
...amework/apollo/biz/repository/AppNamespaceRepository.java
+2
-2
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AdminService.java
.../com/ctrip/framework/apollo/biz/service/AdminService.java
+1
-1
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppNamespaceService.java
...rip/framework/apollo/biz/service/AppNamespaceService.java
+28
-7
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ClusterService.java
...om/ctrip/framework/apollo/biz/service/ClusterService.java
+4
-3
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ItemService.java
...a/com/ctrip/framework/apollo/biz/service/ItemService.java
+19
-3
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ItemSetService.java
...om/ctrip/framework/apollo/biz/service/ItemSetService.java
+15
-14
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceLockService.java
...ip/framework/apollo/biz/service/NamespaceLockService.java
+3
-0
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceService.java
.../ctrip/framework/apollo/biz/service/NamespaceService.java
+17
-14
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/Validator.java
...ava/com/ctrip/framework/apollo/biz/service/Validator.java
+23
-0
apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/repository/AppNamespaceRepositoryTest.java
...ork/apollo/biz/repository/AppNamespaceRepositoryTest.java
+12
-6
apollo-biz/src/test/resources/data.sql
apollo-biz/src/test/resources/data.sql
+7
-7
apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigFile.java
.../src/main/java/com/ctrip/framework/apollo/ConfigFile.java
+32
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigService.java
...c/main/java/com/ctrip/framework/apollo/ConfigService.java
+11
-1
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigFile.java
.../ctrip/framework/apollo/internals/AbstractConfigFile.java
+61
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/ConfigManager.java
...a/com/ctrip/framework/apollo/internals/ConfigManager.java
+10
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultConfigManager.java
...trip/framework/apollo/internals/DefaultConfigManager.java
+24
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/LocalFileConfigRepository.java
...framework/apollo/internals/LocalFileConfigRepository.java
+3
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/PropertiesConfigFile.java
...trip/framework/apollo/internals/PropertiesConfigFile.java
+71
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/XmlConfigFile.java
...a/com/ctrip/framework/apollo/internals/XmlConfigFile.java
+36
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/spi/ConfigFactory.java
...in/java/com/ctrip/framework/apollo/spi/ConfigFactory.java
+9
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/spi/DefaultConfigFactory.java
.../com/ctrip/framework/apollo/spi/DefaultConfigFactory.java
+18
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/AllTests.java
...nt/src/test/java/com/ctrip/framework/apollo/AllTests.java
+3
-1
apollo-client/src/test/java/com/ctrip/framework/apollo/BaseIntegrationTest.java
.../java/com/ctrip/framework/apollo/BaseIntegrationTest.java
+5
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/ConfigServiceTest.java
...st/java/com/ctrip/framework/apollo/ConfigServiceTest.java
+51
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/integration/ConfigIntegrationTest.java
...p/framework/apollo/integration/ConfigIntegrationTest.java
+3
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/DefaultConfigManagerTest.java
.../framework/apollo/internals/DefaultConfigManagerTest.java
+56
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/PropertiesConfigFileTest.java
.../framework/apollo/internals/PropertiesConfigFileTest.java
+112
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/XmlConfigFileTest.java
...m/ctrip/framework/apollo/internals/XmlConfigFileTest.java
+109
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/spi/DefaultConfigFactoryManagerTest.java
...framework/apollo/spi/DefaultConfigFactoryManagerTest.java
+18
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/spi/DefaultConfigFactoryTest.java
.../ctrip/framework/apollo/spi/DefaultConfigFactoryTest.java
+31
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/spi/DefaultConfigRegistryTest.java
...ctrip/framework/apollo/spi/DefaultConfigRegistryTest.java
+7
-0
apollo-common/src/main/java/com/ctrip/framework/apollo/common/entity/AppNamespace.java
...om/ctrip/framework/apollo/common/entity/AppNamespace.java
+33
-4
apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/InputValidator.java
...m/ctrip/framework/apollo/common/utils/InputValidator.java
+14
-0
apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/RequestPrecondition.java
...ip/framework/apollo/common/utils/RequestPrecondition.java
+2
-0
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/ConfigController.java
...ork/apollo/configservice/controller/ConfigController.java
+27
-8
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/NotificationController.java
...ollo/configservice/controller/NotificationController.java
+21
-3
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/util/NamespaceUtil.java
...ip/framework/apollo/configservice/util/NamespaceUtil.java
+19
-0
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/AllTests.java
...va/com/ctrip/framework/apollo/configservice/AllTests.java
+3
-1
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/ConfigControllerTest.java
...apollo/configservice/controller/ConfigControllerTest.java
+103
-13
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/NotificationControllerTest.java
.../configservice/controller/NotificationControllerTest.java
+101
-5
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/ConfigControllerIntegrationTest.java
...gservice/integration/ConfigControllerIntegrationTest.java
+47
-0
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/NotificationControllerIntegrationTest.java
...ce/integration/NotificationControllerIntegrationTest.java
+65
-0
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/util/NamespaceUtilTest.java
...ramework/apollo/configservice/util/NamespaceUtilTest.java
+53
-0
apollo-configservice/src/test/resources/integration-test/test-release.sql
...vice/src/test/resources/integration-test/test-release.sql
+16
-4
apollo-core/src/main/java/com/ctrip/framework/apollo/core/ConfigConsts.java
...in/java/com/ctrip/framework/apollo/core/ConfigConsts.java
+1
-0
apollo-core/src/main/java/com/ctrip/framework/apollo/core/dto/AppNamespaceDTO.java
.../com/ctrip/framework/apollo/core/dto/AppNamespaceDTO.java
+27
-0
apollo-core/src/main/java/com/ctrip/framework/apollo/core/enums/ConfigFileFormat.java
...m/ctrip/framework/apollo/core/enums/ConfigFileFormat.java
+28
-0
apollo-demo/src/main/java/ApolloConfigDemo.java
apollo-demo/src/main/java/ApolloConfigDemo.java
+2
-0
apollo-demo/src/main/java/ApolloConfigFileDemo.java
apollo-demo/src/main/java/ApolloConfigFileDemo.java
+52
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/auth/PermissionValidator.java
...rip/framework/apollo/portal/auth/PermissionValidator.java
+17
-7
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ConfigController.java
.../framework/apollo/portal/controller/ConfigController.java
+5
-1
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceController.java
...amework/apollo/portal/controller/NamespaceController.java
+19
-7
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PermissionController.java
...mework/apollo/portal/controller/PermissionController.java
+9
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/form/NamespaceTextModel.java
...amework/apollo/portal/entity/form/NamespaceTextModel.java
+10
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/NamespaceVO.java
.../ctrip/framework/apollo/portal/entity/vo/NamespaceVO.java
+10
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/CreationListener.java
...ip/framework/apollo/portal/listener/CreationListener.java
+8
-1
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppNamespaceRepository.java
...work/apollo/portal/repository/AppNamespaceRepository.java
+4
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppNamespaceService.java
.../framework/apollo/portal/service/AppNamespaceService.java
+81
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java
...com/ctrip/framework/apollo/portal/service/AppService.java
+2
-3
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ConfigService.java
.../ctrip/framework/apollo/portal/service/ConfigService.java
+10
-1
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceService.java
...rip/framework/apollo/portal/service/NamespaceService.java
+14
-56
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/RolePermissionService.java
...ramework/apollo/portal/service/RolePermissionService.java
+1
-1
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/txtresolver/FileTextResolver.java
...k/apollo/portal/service/txtresolver/FileTextResolver.java
+42
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/txtresolver/PropertyResolver.java
...k/apollo/portal/service/txtresolver/PropertyResolver.java
+1
-1
apollo-portal/src/main/resources/static/app.html
apollo-portal/src/main/resources/static/app.html
+1
-1
apollo-portal/src/main/resources/static/app/role.html
apollo-portal/src/main/resources/static/app/role.html
+3
-3
apollo-portal/src/main/resources/static/cluster.html
apollo-portal/src/main/resources/static/cluster.html
+2
-2
apollo-portal/src/main/resources/static/config.html
apollo-portal/src/main/resources/static/config.html
+31
-291
apollo-portal/src/main/resources/static/config/sync.html
apollo-portal/src/main/resources/static/config/sync.html
+3
-3
apollo-portal/src/main/resources/static/img/cluster.png
apollo-portal/src/main/resources/static/img/cluster.png
+0
-0
apollo-portal/src/main/resources/static/namespace.html
apollo-portal/src/main/resources/static/namespace.html
+23
-2
apollo-portal/src/main/resources/static/namespace/role.html
apollo-portal/src/main/resources/static/namespace/role.html
+3
-3
apollo-portal/src/main/resources/static/scripts/controller/NamespaceController.js
...esources/static/scripts/controller/NamespaceController.js
+21
-3
apollo-portal/src/main/resources/static/scripts/controller/config/ConfigBaseInfoController.js
...tic/scripts/controller/config/ConfigBaseInfoController.js
+7
-3
apollo-portal/src/main/resources/static/scripts/controller/config/ConfigNamespaceController.js
...ic/scripts/controller/config/ConfigNamespaceController.js
+77
-210
apollo-portal/src/main/resources/static/scripts/directive/directive.js
.../src/main/resources/static/scripts/directive/directive.js
+5
-5
apollo-portal/src/main/resources/static/scripts/directive/namespace-panel-directive.js
...ces/static/scripts/directive/namespace-panel-directive.js
+241
-0
apollo-portal/src/main/resources/static/scripts/services/ConfigService.js
...c/main/resources/static/scripts/services/ConfigService.js
+2
-6
apollo-portal/src/main/resources/static/scripts/services/NamespaceLockService.js
...resources/static/scripts/services/NamespaceLockService.js
+1
-0
apollo-portal/src/main/resources/static/scripts/services/PermissionService.js
...in/resources/static/scripts/services/PermissionService.js
+15
-0
apollo-portal/src/main/resources/static/server_config.html
apollo-portal/src/main/resources/static/server_config.html
+1
-1
apollo-portal/src/main/resources/static/views/common/nav.html
...lo-portal/src/main/resources/static/views/common/nav.html
+1
-1
apollo-portal/src/main/resources/static/views/component/namespace-panel.html
...ain/resources/static/views/component/namespace-panel.html
+307
-0
apollo-portal/src/test/java/com/ctrip/framework/apollo/portal/ConfigServiceTest.java
.../com/ctrip/framework/apollo/portal/ConfigServiceTest.java
+4
-1
apollo-portal/src/test/java/com/ctrip/framework/apollo/portal/NamespaceServiceTest.java
...m/ctrip/framework/apollo/portal/NamespaceServiceTest.java
+22
-8
apollo-portal/src/test/java/com/ctrip/framework/apollo/portal/PropertyResolverTest.java
...m/ctrip/framework/apollo/portal/PropertyResolverTest.java
+2
-0
No files found.
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/NamespaceLockAspect.java
View file @
5c6081a0
...
...
@@ -11,6 +11,7 @@ import com.ctrip.framework.apollo.biz.utils.ApolloSwitcher;
import
com.ctrip.framework.apollo.core.dto.ItemChangeSets
;
import
com.ctrip.framework.apollo.core.dto.ItemDTO
;
import
com.ctrip.framework.apollo.core.exception.BadRequestException
;
import
com.ctrip.framework.apollo.core.exception.ServiceException
;
import
org.aspectj.lang.annotation.Aspect
;
import
org.aspectj.lang.annotation.Before
;
...
...
@@ -42,13 +43,14 @@ public class NamespaceLockAspect {
@Before
(
"@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, item, ..)"
)
public
void
requireLockAdvice
(
String
appId
,
String
clusterName
,
String
namespaceName
,
ItemDTO
item
)
{
public
void
requireLockAdvice
(
String
appId
,
String
clusterName
,
String
namespaceName
,
ItemDTO
item
)
{
acquireLock
(
appId
,
clusterName
,
namespaceName
,
item
.
getDataChangeLastModifiedBy
());
}
@Before
(
"@annotation(PreAcquireNamespaceLock) && args(appId, clusterName, namespaceName, changeSet, ..)"
)
public
void
requireLockAdvice
(
String
appId
,
String
clusterName
,
String
namespaceName
,
ItemChangeSets
changeSet
)
{
ItemChangeSets
changeSet
)
{
acquireLock
(
appId
,
clusterName
,
namespaceName
,
changeSet
.
getDataChangeLastModifiedBy
());
}
...
...
@@ -59,7 +61,8 @@ public class NamespaceLockAspect {
acquireLock
(
item
.
getNamespaceId
(),
operator
);
}
private
void
acquireLock
(
String
appId
,
String
clusterName
,
String
namespaceName
,
String
currentUser
)
{
private
void
acquireLock
(
String
appId
,
String
clusterName
,
String
namespaceName
,
String
currentUser
)
{
if
(
apolloSwitcher
.
isNamespaceLockSwitchOff
())
{
return
;
}
...
...
@@ -90,17 +93,15 @@ public class NamespaceLockAspect {
//lock success
}
catch
(
DataIntegrityViolationException
e
)
{
//lock fail
acquireLockFail
(
namespace
,
currentUser
);
}
catch
(
Exception
e
){
namespaceLock
=
namespaceLockService
.
findLock
(
namespaceId
);
checkLock
(
namespace
,
namespaceLock
,
currentUser
);
}
catch
(
Exception
e
)
{
logger
.
error
(
"try lock error"
,
e
);
throw
e
;
}
}
else
{
//check lock owner is current user
String
lockOwner
=
namespaceLock
.
getDataChangeCreatedBy
();
if
(!
lockOwner
.
equals
(
currentUser
))
{
acquireLockFail
(
namespace
,
currentUser
);
}
checkLock
(
namespace
,
namespaceLock
,
currentUser
);
}
}
...
...
@@ -112,15 +113,19 @@ public class NamespaceLockAspect {
namespaceLockService
.
tryLock
(
lock
);
}
private
void
acquireLockFail
(
Namespace
namespace
,
String
currentUser
){
NamespaceLock
namespaceLock
=
namespaceLockService
.
findLock
(
namespace
.
getId
());
if
(
namespaceLock
==
null
){
acquireLock
(
namespace
,
currentUser
);
private
void
checkLock
(
Namespace
namespace
,
NamespaceLock
namespaceLock
,
String
currentUser
)
{
if
(
namespaceLock
==
null
)
{
throw
new
ServiceException
(
String
.
format
(
"Check lock for %s failed, please retry."
,
namespace
.
getNamespaceName
()));
}
String
lockOwner
=
namespaceLock
.
getDataChangeCreatedBy
();
throw
new
BadRequestException
(
"namespace:"
+
namespace
.
getNamespaceName
()
+
" is modifying by "
+
lockOwner
);
if
(!
lockOwner
.
equals
(
currentUser
))
{
throw
new
BadRequestException
(
"namespace:"
+
namespace
.
getNamespaceName
()
+
" is modified by "
+
lockOwner
);
}
}
}
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppNamespaceController.java
View file @
5c6081a0
...
...
@@ -11,6 +11,7 @@ import com.ctrip.framework.apollo.common.entity.AppNamespace;
import
com.ctrip.framework.apollo.biz.service.AppNamespaceService
;
import
com.ctrip.framework.apollo.common.utils.BeanUtils
;
import
com.ctrip.framework.apollo.core.dto.AppNamespaceDTO
;
import
com.ctrip.framework.apollo.core.exception.BadRequestException
;
import
java.util.List
;
...
...
@@ -20,18 +21,6 @@ public class AppNamespaceController {
@Autowired
private
AppNamespaceService
appNamespaceService
;
@RequestMapping
(
"/apps/{appId}/appnamespace/{appnamespace}/unique"
)
public
boolean
isAppNamespaceUnique
(
@PathVariable
(
"appId"
)
String
appId
,
@PathVariable
(
"appnamespace"
)
String
appnamespace
)
{
return
appNamespaceService
.
isAppNamespaceNameUnique
(
appId
,
appnamespace
);
}
@RequestMapping
(
"/appnamespaces/public"
)
public
List
<
AppNamespaceDTO
>
findPublicAppNamespaces
(){
List
<
AppNamespace
>
appNamespaces
=
appNamespaceService
.
findPublicAppNamespaces
();
return
BeanUtils
.
batchTransform
(
AppNamespaceDTO
.
class
,
appNamespaces
);
}
@RequestMapping
(
value
=
"/apps/{appId}/appnamespaces"
,
method
=
RequestMethod
.
POST
)
public
AppNamespaceDTO
createOrUpdate
(
@RequestBody
AppNamespaceDTO
appNamespace
){
...
...
@@ -39,8 +28,7 @@ public class AppNamespaceController {
AppNamespace
managedEntity
=
appNamespaceService
.
findOne
(
entity
.
getAppId
(),
entity
.
getName
());
if
(
managedEntity
!=
null
){
BeanUtils
.
copyEntityProperties
(
entity
,
managedEntity
);
entity
=
appNamespaceService
.
update
(
managedEntity
);
throw
new
BadRequestException
(
"app namespaces already exist."
);
}
else
{
entity
=
appNamespaceService
.
createAppNamespace
(
entity
,
entity
.
getDataChangeCreatedBy
());
}
...
...
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ClusterController.java
View file @
5c6081a0
...
...
@@ -32,8 +32,7 @@ public class ClusterController {
Cluster
entity
=
BeanUtils
.
transfrom
(
Cluster
.
class
,
dto
);
Cluster
managedEntity
=
clusterService
.
findOne
(
appId
,
entity
.
getName
());
if
(
managedEntity
!=
null
)
{
BeanUtils
.
copyEntityProperties
(
entity
,
managedEntity
);
entity
=
clusterService
.
update
(
managedEntity
);
throw
new
BadRequestException
(
"cluster already exist."
);
}
else
{
entity
=
clusterService
.
save
(
entity
);
}
...
...
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceController.java
View file @
5c6081a0
...
...
@@ -33,8 +33,7 @@ public class NamespaceController {
Namespace
entity
=
BeanUtils
.
transfrom
(
Namespace
.
class
,
dto
);
Namespace
managedEntity
=
namespaceService
.
findOne
(
appId
,
clusterName
,
entity
.
getNamespaceName
());
if
(
managedEntity
!=
null
)
{
BeanUtils
.
copyEntityProperties
(
entity
,
managedEntity
);
entity
=
namespaceService
.
update
(
managedEntity
);
throw
new
BadRequestException
(
"namespace already exist."
);
}
else
{
entity
=
namespaceService
.
save
(
entity
);
}
...
...
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/entity/Item.java
View file @
5c6081a0
...
...
@@ -4,6 +4,7 @@ import com.ctrip.framework.apollo.common.entity.BaseEntity;
import
javax.persistence.Column
;
import
javax.persistence.Entity
;
import
javax.persistence.Lob
;
import
javax.persistence.Table
;
import
org.hibernate.annotations.SQLDelete
;
...
...
@@ -22,6 +23,7 @@ public class Item extends BaseEntity {
private
String
key
;
@Column
(
name
=
"value"
)
@Lob
private
String
value
;
@Column
(
name
=
"comment"
)
...
...
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppNamespaceRepository.java
View file @
5c6081a0
...
...
@@ -10,8 +10,8 @@ public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNa
AppNamespace
findByAppIdAndName
(
String
appId
,
String
namespaceName
);
AppNamespace
findByName
(
String
namespaceName
);
AppNamespace
findByName
AndIsPublicTrue
(
String
namespaceName
);
List
<
AppNamespace
>
findBy
NameNot
(
String
namespaceName
);
List
<
AppNamespace
>
findBy
AppIdAndIsPublic
(
String
appId
,
boolean
isPublic
);
}
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AdminService.java
View file @
5c6081a0
...
...
@@ -33,7 +33,7 @@ public class AdminService {
clusterService
.
createDefaultCluster
(
appId
,
createBy
);
namespaceService
.
create
Default
Namespace
(
appId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
createBy
);
namespaceService
.
create
Private
Namespace
(
appId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
createBy
);
return
app
;
}
...
...
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppNamespaceService.java
View file @
5c6081a0
...
...
@@ -9,6 +9,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
com.ctrip.framework.apollo.biz.entity.Cluster
;
import
com.ctrip.framework.apollo.biz.entity.Namespace
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.biz.entity.Audit
;
import
com.ctrip.framework.apollo.biz.repository.AppNamespaceRepository
;
...
...
@@ -22,7 +24,10 @@ public class AppNamespaceService {
@Autowired
private
AppNamespaceRepository
appNamespaceRepository
;
@Autowired
private
NamespaceService
namespaceService
;
@Autowired
private
ClusterService
clusterService
;
@Autowired
private
AuditService
auditService
;
...
...
@@ -32,9 +37,13 @@ public class AppNamespaceService {
return
Objects
.
isNull
(
appNamespaceRepository
.
findByAppIdAndName
(
appId
,
namespaceName
));
}
public
AppNamespace
findByNamespaceName
(
String
namespaceName
)
{
public
AppNamespace
find
Public
ByNamespaceName
(
String
namespaceName
)
{
Preconditions
.
checkArgument
(
namespaceName
!=
null
,
"Namespace must not be null"
);
return
appNamespaceRepository
.
findByName
(
namespaceName
);
return
appNamespaceRepository
.
findByNameAndIsPublicTrue
(
namespaceName
);
}
public
List
<
AppNamespace
>
findPrivateAppNamespace
(
String
appId
){
return
appNamespaceRepository
.
findByAppIdAndIsPublic
(
appId
,
false
);
}
public
AppNamespace
findOne
(
String
appId
,
String
namespaceName
){
...
...
@@ -68,16 +77,28 @@ public class AppNamespaceService {
appNamespace
.
setDataChangeCreatedBy
(
createBy
);
appNamespace
.
setDataChangeLastModifiedBy
(
createBy
);
appNamespace
=
appNamespaceRepository
.
save
(
appNamespace
);
//所有的cluster下面link新建的appnamespace
if
(!
appNamespace
.
isPublic
()){
String
appId
=
appNamespace
.
getAppId
();
String
namespaceName
=
appNamespace
.
getName
();
List
<
Cluster
>
clusters
=
clusterService
.
findClusters
(
appId
);
for
(
Cluster
cluster:
clusters
){
Namespace
namespace
=
new
Namespace
();
namespace
.
setClusterName
(
cluster
.
getName
());
namespace
.
setAppId
(
appId
);
namespace
.
setNamespaceName
(
namespaceName
);
namespace
.
setDataChangeCreatedBy
(
createBy
);
namespace
.
setDataChangeLastModifiedBy
(
createBy
);
namespaceService
.
save
(
namespace
);
}
}
auditService
.
audit
(
AppNamespace
.
class
.
getSimpleName
(),
appNamespace
.
getId
(),
Audit
.
OP
.
INSERT
,
createBy
);
return
appNamespace
;
}
public
List
<
AppNamespace
>
findPublicAppNamespaces
(){
return
appNamespaceRepository
.
findByNameNot
(
ConfigConsts
.
NAMESPACE_APPLICATION
);
}
public
AppNamespace
update
(
AppNamespace
appNamespace
){
AppNamespace
managedNs
=
appNamespaceRepository
.
findByAppIdAndName
(
appNamespace
.
getAppId
(),
appNamespace
.
getName
());
BeanUtils
.
copyEntityProperties
(
appNamespace
,
managedNs
);
...
...
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ClusterService.java
View file @
5c6081a0
...
...
@@ -22,12 +22,13 @@ public class ClusterService {
@Autowired
private
ClusterRepository
clusterRepository
;
@Autowired
private
AuditService
auditService
;
@Autowired
private
NamespaceService
namespaceService
;
@Autowired
private
AppNamespaceService
appNamespaceService
;
public
boolean
isClusterNameUnique
(
String
appId
,
String
clusterName
)
{
Objects
.
requireNonNull
(
appId
,
"AppId must not be null"
);
...
...
@@ -59,7 +60,7 @@ public class ClusterService {
entity
.
setId
(
0
);
//protection
Cluster
cluster
=
clusterRepository
.
save
(
entity
);
namespaceService
.
create
Default
Namespace
(
cluster
.
getAppId
(),
cluster
.
getName
(),
cluster
.
getDataChangeCreatedBy
());
namespaceService
.
create
Private
Namespace
(
cluster
.
getAppId
(),
cluster
.
getName
(),
cluster
.
getDataChangeCreatedBy
());
auditService
.
audit
(
Cluster
.
class
.
getSimpleName
(),
cluster
.
getId
(),
Audit
.
OP
.
INSERT
,
cluster
.
getDataChangeCreatedBy
());
...
...
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ItemService.java
View file @
5c6081a0
...
...
@@ -7,6 +7,7 @@ import com.ctrip.framework.apollo.biz.repository.ItemRepository;
import
com.ctrip.framework.apollo.biz.repository.NamespaceRepository
;
import
com.ctrip.framework.apollo.common.utils.BeanUtils
;
import
com.ctrip.framework.apollo.core.exception.NotFoundException
;
import
com.ctrip.framework.apollo.core.utils.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
...
...
@@ -27,18 +28,22 @@ public class ItemService {
@Autowired
private
AuditService
auditService
;
@Autowired
private
ServerConfigService
serverConfigService
;
@Transactional
public
void
delete
(
long
id
,
String
operator
)
{
public
Item
delete
(
long
id
,
String
operator
)
{
Item
item
=
itemRepository
.
findOne
(
id
);
if
(
item
==
null
)
{
return
;
throw
new
IllegalArgumentException
(
"item not exist. ID:"
+
id
)
;
}
item
.
setDeleted
(
true
);
item
.
setDataChangeLastModifiedBy
(
operator
);
itemRepository
.
save
(
item
);
Item
deletedItem
=
itemRepository
.
save
(
item
);
auditService
.
audit
(
Item
.
class
.
getSimpleName
(),
id
,
Audit
.
OP
.
DELETE
,
operator
);
return
deletedItem
;
}
public
Item
findOne
(
String
appId
,
String
clusterName
,
String
namespaceName
,
String
key
)
{
...
...
@@ -88,6 +93,8 @@ public class ItemService {
@Transactional
public
Item
save
(
Item
entity
)
{
checkItemValueLength
(
entity
.
getValue
());
entity
.
setId
(
0
);
//protection
Item
item
=
itemRepository
.
save
(
entity
);
...
...
@@ -99,6 +106,7 @@ public class ItemService {
@Transactional
public
Item
update
(
Item
item
)
{
checkItemValueLength
(
item
.
getValue
());
Item
managedItem
=
itemRepository
.
findOne
(
item
.
getId
());
BeanUtils
.
copyEntityProperties
(
item
,
managedItem
);
managedItem
=
itemRepository
.
save
(
managedItem
);
...
...
@@ -109,4 +117,12 @@ public class ItemService {
return
managedItem
;
}
private
boolean
checkItemValueLength
(
String
value
){
int
lengthLimit
=
Integer
.
valueOf
(
serverConfigService
.
getValue
(
"item.value.length.limit"
,
"20000"
));
if
(!
StringUtils
.
isEmpty
(
value
)
&&
value
.
length
()
>
lengthLimit
){
throw
new
IllegalArgumentException
(
"value too long. length limit:"
+
lengthLimit
);
}
return
true
;
}
}
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ItemSetService.java
View file @
5c6081a0
...
...
@@ -28,6 +28,9 @@ public class ItemSetService {
@Autowired
private
CommitService
commitService
;
@Autowired
private
ItemService
itemService
;
@Transactional
public
ItemChangeSets
updateSet
(
String
appId
,
String
clusterName
,
...
...
@@ -38,10 +41,9 @@ public class ItemSetService {
if
(!
CollectionUtils
.
isEmpty
(
changeSet
.
getCreateItems
()))
{
for
(
ItemDTO
item
:
changeSet
.
getCreateItems
())
{
Item
entity
=
BeanUtils
.
transfrom
(
Item
.
class
,
item
);
entity
.
setId
(
0
);
//protection
entity
.
setDataChangeCreatedBy
(
operator
);
entity
.
setDataChangeLastModifiedBy
(
operator
);
Item
createdItem
=
item
Repository
.
save
(
entity
);
Item
createdItem
=
item
Service
.
save
(
entity
);
configChangeContentBuilder
.
createItem
(
createdItem
);
}
auditService
.
audit
(
"ItemSet"
,
null
,
Audit
.
OP
.
INSERT
,
operator
);
...
...
@@ -50,11 +52,11 @@ public class ItemSetService {
if
(!
CollectionUtils
.
isEmpty
(
changeSet
.
getUpdateItems
()))
{
for
(
ItemDTO
item
:
changeSet
.
getUpdateItems
())
{
Item
entity
=
BeanUtils
.
transfrom
(
Item
.
class
,
item
);
Item
managedItem
=
itemRepository
.
findOne
(
entity
.
getId
());
Item
beforeUpdateItem
=
BeanUtils
.
transfrom
(
Item
.
class
,
managedItem
);
BeanUtils
.
copyEntityProperties
(
entity
,
managedItem
);
managedItem
.
setDataChangeLastModifiedBy
(
operator
);
Item
updatedItem
=
item
Repository
.
save
(
managedItem
);
Item
beforeUpdateItem
=
itemRepository
.
findOne
(
entity
.
getId
()
);
entity
.
setDataChangeLastModifiedBy
(
operator
);
Item
updatedItem
=
item
Service
.
update
(
entity
);
configChangeContentBuilder
.
updateItem
(
beforeUpdateItem
,
updatedItem
);
}
...
...
@@ -63,25 +65,24 @@ public class ItemSetService {
if
(!
CollectionUtils
.
isEmpty
(
changeSet
.
getDeleteItems
()))
{
for
(
ItemDTO
item
:
changeSet
.
getDeleteItems
())
{
Item
entity
=
BeanUtils
.
transfrom
(
Item
.
class
,
item
);
entity
.
setDeleted
(
true
);
entity
.
setDataChangeLastModifiedBy
(
operator
);
Item
deletedItem
=
itemRepository
.
save
(
entity
);
Item
deletedItem
=
itemService
.
delete
(
item
.
getId
(),
operator
);
configChangeContentBuilder
.
deleteItem
(
deletedItem
);
}
auditService
.
audit
(
"ItemSet"
,
null
,
Audit
.
OP
.
DELETE
,
operator
);
}
String
configChangeContent
=
configChangeContentBuilder
.
build
();
if
(!
StringUtils
.
isEmpty
(
configChangeContent
)){
createCommit
(
appId
,
clusterName
,
namespaceName
,
configChangeContentBuilder
.
build
(),
changeSet
.
getDataChangeLastModifiedBy
());
if
(!
StringUtils
.
isEmpty
(
configChangeContent
))
{
createCommit
(
appId
,
clusterName
,
namespaceName
,
configChangeContentBuilder
.
build
(),
changeSet
.
getDataChangeLastModifiedBy
());
}
return
changeSet
;
}
private
void
createCommit
(
String
appId
,
String
clusterName
,
String
namespaceName
,
String
configChangeContent
,
String
operator
){
private
void
createCommit
(
String
appId
,
String
clusterName
,
String
namespaceName
,
String
configChangeContent
,
String
operator
)
{
Commit
commit
=
new
Commit
();
commit
.
setAppId
(
appId
);
...
...
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceLockService.java
View file @
5c6081a0
...
...
@@ -5,6 +5,7 @@ import com.ctrip.framework.apollo.biz.repository.NamespaceLockRepository;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
@Service
public
class
NamespaceLockService
{
...
...
@@ -17,10 +18,12 @@ public class NamespaceLockService {
return
namespaceLockRepository
.
findByNamespaceId
(
namespaceId
);
}
@Transactional
public
NamespaceLock
tryLock
(
NamespaceLock
lock
){
return
namespaceLockRepository
.
save
(
lock
);
}
@Transactional
public
void
unlock
(
Long
namespaceId
){
namespaceLockRepository
.
deleteByNamespaceId
(
namespaceId
);
}
...
...
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceService.java
View file @
5c6081a0
...
...
@@ -11,8 +11,8 @@ import org.springframework.transaction.annotation.Transactional;
import
com.ctrip.framework.apollo.biz.entity.Audit
;
import
com.ctrip.framework.apollo.biz.entity.Namespace
;
import
com.ctrip.framework.apollo.biz.repository.NamespaceRepository
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.common.utils.BeanUtils
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.exception.ServiceException
;
@Service
...
...
@@ -20,9 +20,10 @@ public class NamespaceService {
@Autowired
private
NamespaceRepository
namespaceRepository
;
@Autowired
private
AuditService
auditService
;
@Autowired
private
AppNamespaceService
appNamespaceService
;
public
boolean
isNamespaceUnique
(
String
appId
,
String
cluster
,
String
namespace
)
{
Objects
.
requireNonNull
(
appId
,
"AppId must not be null"
);
...
...
@@ -91,19 +92,21 @@ public class NamespaceService {
}
@Transactional
public
void
createDefaultNamespace
(
String
appId
,
String
clusterName
,
String
createBy
)
{
if
(!
isNamespaceUnique
(
appId
,
clusterName
,
appId
))
{
throw
new
ServiceException
(
"namespace not unique"
);
public
void
createPrivateNamespace
(
String
appId
,
String
clusterName
,
String
createBy
)
{
//load all private app namespace
List
<
AppNamespace
>
privateAppNamespaces
=
appNamespaceService
.
findPrivateAppNamespace
(
appId
);
//create all private namespace
for
(
AppNamespace
appNamespace:
privateAppNamespaces
){
Namespace
ns
=
new
Namespace
();
ns
.
setAppId
(
appId
);
ns
.
setClusterName
(
clusterName
);
ns
.
setNamespaceName
(
appNamespace
.
getName
());
ns
.
setDataChangeCreatedBy
(
createBy
);
ns
.
setDataChangeLastModifiedBy
(
createBy
);
namespaceRepository
.
save
(
ns
);
auditService
.
audit
(
Namespace
.
class
.
getSimpleName
(),
ns
.
getId
(),
Audit
.
OP
.
INSERT
,
createBy
);
}
Namespace
ns
=
new
Namespace
();
ns
.
setAppId
(
appId
);
ns
.
setClusterName
(
clusterName
);
ns
.
setNamespaceName
(
ConfigConsts
.
NAMESPACE_APPLICATION
);
ns
.
setDataChangeCreatedBy
(
createBy
);
ns
.
setDataChangeLastModifiedBy
(
createBy
);
namespaceRepository
.
save
(
ns
);
auditService
.
audit
(
Namespace
.
class
.
getSimpleName
(),
ns
.
getId
(),
Audit
.
OP
.
INSERT
,
createBy
);
}
}
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/Validator.java
0 → 100644
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
biz
.
service
;
import
com.ctrip.framework.apollo.core.exception.BadRequestException
;
import
com.ctrip.framework.apollo.core.utils.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
@Component
public
class
Validator
{
@Autowired
private
ServerConfigService
serverConfigService
;
public
boolean
checkItemValueLength
(
String
value
){
int
lengthLimit
=
Integer
.
valueOf
(
serverConfigService
.
getValue
(
"item.value.length.limit"
,
"65536"
));
if
(!
StringUtils
.
isEmpty
(
value
)
&&
value
.
length
()
>
lengthLimit
){
throw
new
BadRequestException
(
"value too long. length limit:"
+
lengthLimit
);
}
return
true
;
}
}
apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/repository/AppNamespaceRepositoryTest.java
View file @
5c6081a0
...
...
@@ -2,9 +2,7 @@ package com.ctrip.framework.apollo.biz.repository;
import
com.ctrip.framework.apollo.biz.BizTestConfiguration
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
org.junit.Assert
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -13,7 +11,8 @@ import org.springframework.test.annotation.Rollback;
import
org.springframework.test.context.junit4.SpringJUnit4ClassRunner
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.List
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNull
;
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@SpringApplicationConfiguration
(
classes
=
BizTestConfiguration
.
class
)
...
...
@@ -25,9 +24,16 @@ public class AppNamespaceRepositoryTest {
private
AppNamespaceRepository
repository
;
@Test
public
void
testFindAllPublicAppNamespaces
(){
List
<
AppNamespace
>
appNamespaceList
=
repository
.
findByNameNot
(
ConfigConsts
.
NAMESPACE_APPLICATION
);
Assert
.
assertEquals
(
4
,
appNamespaceList
.
size
());
public
void
testFindByNameAndIsPublicTrue
()
throws
Exception
{
AppNamespace
appNamespace
=
repository
.
findByNameAndIsPublicTrue
(
"fx.apollo.config"
);
assertEquals
(
"100003171"
,
appNamespace
.
getAppId
());
}
@Test
public
void
testFindByNameAndNoPublicNamespace
()
throws
Exception
{
AppNamespace
appNamespace
=
repository
.
findByNameAndIsPublicTrue
(
"application"
);
assertNull
(
appNamespace
);
}
}
apollo-biz/src/test/resources/data.sql
View file @
5c6081a0
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'100003171'
,
'application'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'100003171'
,
'fx.apollo.config'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'100003172'
,
'application'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'100003172'
,
'fx.apollo.admin'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'100003173'
,
'application'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'100003173'
,
'fx.apollo.portal'
);
INSERT
INTO
AppNamespace
(
AppID
,
Name
)
VALUES
(
'fxhermesproducer'
,
'fx.hermes.producer'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'100003171'
,
'application'
,
false
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'100003171'
,
'fx.apollo.config'
,
true
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'100003172'
,
'application'
,
false
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'100003172'
,
'fx.apollo.admin'
,
true
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'100003173'
,
'application'
,
false
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'100003173'
,
'fx.apollo.portal'
,
true
);
INSERT
INTO
AppNamespace
(
AppID
,
Name
,
IsPublic
)
VALUES
(
'fxhermesproducer'
,
'fx.hermes.producer'
,
true
);
apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigFile.java
0 → 100644
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
interface
ConfigFile
{
/**
* Get file content of the namespace
* @return file content, {@code null} if there is no content
*/
String
getContent
();
/**
* Whether the config file has any content
* @return true if it has content, false otherwise.
*/
boolean
hasContent
();
/**
* Get the namespace of this config file instance
* @return the namespace
*/
String
getNamespace
();
/**
* Get the file format of this config file instance
* @return the config file format enum
*/
ConfigFileFormat
getConfigFileFormat
();
}
apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigService.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.exceptions.ApolloConfigException
;
import
com.ctrip.framework.apollo.internals.ConfigManager
;
import
com.ctrip.framework.apollo.spi.ConfigFactory
;
...
...
@@ -38,10 +39,13 @@ public class ConfigService {
* @return config instance
*/
public
static
Config
getConfig
(
String
namespace
)
{
return
getManager
().
getConfig
(
namespace
);
}
public
static
ConfigFile
getConfigFile
(
String
namespacePrefix
,
ConfigFileFormat
configFileFormat
)
{
return
getManager
().
getConfigFile
(
namespacePrefix
,
configFileFormat
);
}
private
static
ConfigManager
getManager
()
{
try
{
return
s_instance
.
m_container
.
lookup
(
ConfigManager
.
class
);
...
...
@@ -77,6 +81,12 @@ public class ConfigService {
public
Config
create
(
String
namespace
)
{
return
config
;
}
@Override
public
ConfigFile
createConfigFile
(
String
namespace
,
ConfigFileFormat
configFileFormat
)
{
return
null
;
}
});
}
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigFile.java
0 → 100644
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.util.ExceptionUtil
;
import
com.dianping.cat.Cat
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.util.Properties
;
import
java.util.concurrent.atomic.AtomicReference
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
abstract
class
AbstractConfigFile
implements
ConfigFile
,
RepositoryChangeListener
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
AbstractConfigFile
.
class
);
protected
ConfigRepository
m_configRepository
;
protected
String
m_namespace
;
protected
AtomicReference
<
Properties
>
m_configProperties
;
public
AbstractConfigFile
(
String
namespace
,
ConfigRepository
configRepository
)
{
m_configRepository
=
configRepository
;
m_namespace
=
namespace
;
m_configProperties
=
new
AtomicReference
<>();
initialize
();
}
private
void
initialize
()
{
try
{
m_configProperties
.
set
(
m_configRepository
.
getConfig
());
}
catch
(
Throwable
ex
)
{
Cat
.
logError
(
ex
);
logger
.
warn
(
"Init Apollo Config File failed - namespace: {}, reason: {}."
,
m_namespace
,
ExceptionUtil
.
getDetailMessage
(
ex
));
}
finally
{
//register the change listener no matter config repository is working or not
//so that whenever config repository is recovered, config could get changed
m_configRepository
.
addChangeListener
(
this
);
}
}
@Override
public
String
getNamespace
()
{
return
m_namespace
;
}
@Override
public
synchronized
void
onRepositoryChange
(
String
namespace
,
Properties
newProperties
)
{
if
(
newProperties
.
equals
(
m_configProperties
.
get
()))
{
return
;
}
Properties
newConfigProperties
=
new
Properties
();
newConfigProperties
.
putAll
(
newProperties
);
m_configProperties
.
set
(
newConfigProperties
);
Cat
.
logEvent
(
"Apollo.Client.ConfigChanges"
,
m_namespace
);
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/ConfigManager.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
/**
* @author Jason Song(song_s@ctrip.com)
...
...
@@ -12,4 +14,12 @@ public interface ConfigManager {
* @return the config instance for the namespace
*/
public
Config
getConfig
(
String
namespace
);
/**
* Get the config file instance for the namespace specified.
* @param namespacePrefix the namespace
* @param configFileFormat the config file format
* @return the config file instance for the namespace
*/
public
ConfigFile
getConfigFile
(
String
namespacePrefix
,
ConfigFileFormat
configFileFormat
);
}
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultConfigManager.java
View file @
5c6081a0
...
...
@@ -3,6 +3,8 @@ package com.ctrip.framework.apollo.internals;
import
com.google.common.collect.Maps
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.spi.ConfigFactory
;
import
com.ctrip.framework.apollo.spi.ConfigFactoryManager
;
...
...
@@ -20,6 +22,7 @@ public class DefaultConfigManager implements ConfigManager {
private
ConfigFactoryManager
m_factoryManager
;
private
Map
<
String
,
Config
>
m_configs
=
Maps
.
newConcurrentMap
();
private
Map
<
String
,
ConfigFile
>
m_configFiles
=
Maps
.
newConcurrentMap
();
@Override
public
Config
getConfig
(
String
namespace
)
{
...
...
@@ -40,4 +43,25 @@ public class DefaultConfigManager implements ConfigManager {
return
config
;
}
@Override
public
ConfigFile
getConfigFile
(
String
namespacePrefix
,
ConfigFileFormat
configFileFormat
)
{
String
namespace
=
String
.
format
(
"%s.%s"
,
namespacePrefix
,
configFileFormat
.
getValue
());
ConfigFile
configFile
=
m_configFiles
.
get
(
namespace
);
if
(
configFile
==
null
)
{
synchronized
(
this
)
{
configFile
=
m_configFiles
.
get
(
namespace
);
if
(
configFile
==
null
)
{
ConfigFactory
factory
=
m_factoryManager
.
getFactory
(
namespace
);
configFile
=
factory
.
createConfigFile
(
namespace
,
configFileFormat
);
m_configFiles
.
put
(
namespace
,
configFile
);
}
}
}
return
configFile
;
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/LocalFileConfigRepository.java
View file @
5c6081a0
...
...
@@ -70,6 +70,9 @@ public class LocalFileConfigRepository extends AbstractConfigRepository
try
{
String
defaultCacheDir
=
m_configUtil
.
getDefaultLocalCacheDir
();
Path
path
=
Paths
.
get
(
defaultCacheDir
);
if
(!
Files
.
exists
(
path
))
{
Files
.
createDirectories
(
path
);
}
if
(
Files
.
exists
(
path
)
&&
Files
.
isWritable
(
path
))
{
return
new
File
(
defaultCacheDir
,
CONFIG_DIR
);
}
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/PropertiesConfigFile.java
0 → 100644
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.exceptions.ApolloConfigException
;
import
com.ctrip.framework.apollo.util.ExceptionUtil
;
import
com.dianping.cat.Cat
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.io.IOException
;
import
java.io.StringWriter
;
import
java.util.Properties
;
import
java.util.concurrent.atomic.AtomicReference
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
PropertiesConfigFile
extends
AbstractConfigFile
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
PropertiesConfigFile
.
class
);
protected
AtomicReference
<
String
>
m_contentCache
;
public
PropertiesConfigFile
(
String
namespace
,
ConfigRepository
configRepository
)
{
super
(
namespace
,
configRepository
);
m_contentCache
=
new
AtomicReference
<>();
}
@Override
public
String
getContent
()
{
if
(
m_contentCache
.
get
()
==
null
)
{
m_contentCache
.
set
(
doGetContent
());
}
return
m_contentCache
.
get
();
}
String
doGetContent
()
{
if
(
m_configProperties
.
get
()
==
null
)
{
return
null
;
}
StringWriter
writer
=
new
StringWriter
();
try
{
m_configProperties
.
get
().
store
(
writer
,
null
);
return
writer
.
getBuffer
().
toString
();
}
catch
(
IOException
ex
)
{
ApolloConfigException
exception
=
new
ApolloConfigException
(
String
.
format
(
"Parse properties file content failed for namespace: %s, cause: %s"
,
m_namespace
,
ExceptionUtil
.
getDetailMessage
(
ex
)));
Cat
.
logError
(
exception
);
throw
exception
;
}
}
@Override
public
boolean
hasContent
()
{
return
m_configProperties
.
get
()
!=
null
&&
!
m_configProperties
.
get
().
isEmpty
();
}
@Override
public
ConfigFileFormat
getConfigFileFormat
()
{
return
ConfigFileFormat
.
Properties
;
}
@Override
public
synchronized
void
onRepositoryChange
(
String
namespace
,
Properties
newProperties
)
{
super
.
onRepositoryChange
(
namespace
,
newProperties
);
m_contentCache
.
set
(
null
);
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/XmlConfigFile.java
0 → 100644
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
XmlConfigFile
extends
AbstractConfigFile
{
public
XmlConfigFile
(
String
namespace
,
ConfigRepository
configRepository
)
{
super
(
namespace
,
configRepository
);
}
@Override
public
String
getContent
()
{
if
(
m_configProperties
.
get
()
==
null
)
{
return
null
;
}
return
m_configProperties
.
get
().
getProperty
(
ConfigConsts
.
CONFIG_FILE_CONTENT_KEY
);
}
@Override
public
boolean
hasContent
()
{
if
(
m_configProperties
.
get
()
==
null
)
{
return
false
;
}
return
m_configProperties
.
get
().
containsKey
(
ConfigConsts
.
CONFIG_FILE_CONTENT_KEY
);
}
@Override
public
ConfigFileFormat
getConfigFileFormat
()
{
return
ConfigFileFormat
.
XML
;
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/spi/ConfigFactory.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
spi
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
/**
* @author Jason Song(song_s@ctrip.com)
...
...
@@ -13,4 +15,11 @@ public interface ConfigFactory {
* @return the newly created config instance
*/
public
Config
create
(
String
namespace
);
/**
* Create the config file instance for the namespace
* @param namespace the namespace
* @return the newly created config file instance
*/
public
ConfigFile
createConfigFile
(
String
namespace
,
ConfigFileFormat
configFileFormat
);
}
apollo-client/src/main/java/com/ctrip/framework/apollo/spi/DefaultConfigFactory.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
spi
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.internals.ConfigRepository
;
import
com.ctrip.framework.apollo.internals.DefaultConfig
;
import
com.ctrip.framework.apollo.internals.LocalFileConfigRepository
;
import
com.ctrip.framework.apollo.internals.PropertiesConfigFile
;
import
com.ctrip.framework.apollo.internals.RemoteConfigRepository
;
import
com.ctrip.framework.apollo.internals.XmlConfigFile
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -23,6 +28,19 @@ public class DefaultConfigFactory implements ConfigFactory {
return
defaultConfig
;
}
@Override
public
ConfigFile
createConfigFile
(
String
namespace
,
ConfigFileFormat
configFileFormat
)
{
ConfigRepository
configRepository
=
createLocalConfigRepository
(
namespace
);
switch
(
configFileFormat
)
{
case
Properties:
return
new
PropertiesConfigFile
(
namespace
,
configRepository
);
case
XML:
return
new
XmlConfigFile
(
namespace
,
configRepository
);
}
return
null
;
}
LocalFileConfigRepository
createLocalConfigRepository
(
String
namespace
)
{
LocalFileConfigRepository
localFileConfigRepository
=
new
LocalFileConfigRepository
(
namespace
);
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/AllTests.java
View file @
5c6081a0
...
...
@@ -5,8 +5,10 @@ import com.ctrip.framework.apollo.integration.ConfigIntegrationTest;
import
com.ctrip.framework.apollo.internals.DefaultConfigManagerTest
;
import
com.ctrip.framework.apollo.internals.DefaultConfigTest
;
import
com.ctrip.framework.apollo.internals.LocalFileConfigRepositoryTest
;
import
com.ctrip.framework.apollo.internals.PropertiesConfigFileTest
;
import
com.ctrip.framework.apollo.internals.RemoteConfigRepositoryTest
;
import
com.ctrip.framework.apollo.internals.SimpleConfigTest
;
import
com.ctrip.framework.apollo.internals.XmlConfigFileTest
;
import
com.ctrip.framework.apollo.spi.DefaultConfigFactoryManagerTest
;
import
com.ctrip.framework.apollo.spi.DefaultConfigFactoryTest
;
import
com.ctrip.framework.apollo.spi.DefaultConfigRegistryTest
;
...
...
@@ -21,7 +23,7 @@ import org.junit.runners.Suite.SuiteClasses;
ConfigServiceTest
.
class
,
DefaultConfigRegistryTest
.
class
,
DefaultConfigFactoryManagerTest
.
class
,
DefaultConfigManagerTest
.
class
,
DefaultConfigTest
.
class
,
LocalFileConfigRepositoryTest
.
class
,
RemoteConfigRepositoryTest
.
class
,
SimpleConfigTest
.
class
,
DefaultConfigFactoryTest
.
class
,
ConfigIntegrationTest
.
class
,
ExceptionUtilTest
.
class
ConfigIntegrationTest
.
class
,
ExceptionUtilTest
.
class
,
XmlConfigFileTest
.
class
,
PropertiesConfigFileTest
.
class
})
public
class
AllTests
{
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/BaseIntegrationTest.java
View file @
5c6081a0
...
...
@@ -176,6 +176,11 @@ public abstract class BaseIntegrationTest extends ComponentTestCase {
public
int
getLongPollQPS
()
{
return
200
;
}
@Override
public
String
getDefaultLocalCacheDir
()
{
return
ClassLoaderUtil
.
getClassPath
();
}
}
/**
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/ConfigServiceTest.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.internals.AbstractConfig
;
import
com.ctrip.framework.apollo.spi.ConfigFactory
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
...
...
@@ -62,6 +63,20 @@ public class ConfigServiceTest extends ComponentTestCase {
assertEquals
(
null
,
config
.
getProperty
(
"unknown"
,
null
));
}
@Test
public
void
testMockConfigFactoryForConfigFile
()
throws
Exception
{
String
someNamespacePrefix
=
"mock"
;
ConfigFileFormat
someConfigFileFormat
=
ConfigFileFormat
.
Properties
;
String
someNamespace
=
String
.
format
(
"%s.%s"
,
someNamespacePrefix
,
someConfigFileFormat
.
getValue
());
defineComponent
(
ConfigFactory
.
class
,
someNamespace
,
MockConfigFactory
.
class
);
ConfigFile
configFile
=
ConfigService
.
getConfigFile
(
someNamespacePrefix
,
someConfigFileFormat
);
assertEquals
(
someNamespace
,
configFile
.
getNamespace
());
assertEquals
(
someNamespace
+
":"
+
someConfigFileFormat
.
getValue
(),
configFile
.
getContent
());
}
private
static
class
MockConfig
extends
AbstractConfig
{
private
final
String
m_namespace
;
...
...
@@ -79,11 +94,47 @@ public class ConfigServiceTest extends ComponentTestCase {
}
}
private
static
class
MockConfigFile
implements
ConfigFile
{
private
ConfigFileFormat
m_configFileFormat
;
private
String
m_namespace
;
public
MockConfigFile
(
String
namespace
,
ConfigFileFormat
configFileFormat
)
{
m_namespace
=
namespace
;
m_configFileFormat
=
configFileFormat
;
}
@Override
public
String
getContent
()
{
return
m_namespace
+
":"
+
m_configFileFormat
.
getValue
();
}
@Override
public
boolean
hasContent
()
{
return
true
;
}
@Override
public
String
getNamespace
()
{
return
m_namespace
;
}
@Override
public
ConfigFileFormat
getConfigFileFormat
()
{
return
m_configFileFormat
;
}
}
public
static
class
MockConfigFactory
implements
ConfigFactory
{
@Override
public
Config
create
(
String
namespace
)
{
return
new
MockConfig
(
namespace
);
}
@Override
public
ConfigFile
createConfigFile
(
String
namespace
,
ConfigFileFormat
configFileFormat
)
{
return
new
MockConfigFile
(
namespace
,
configFileFormat
);
}
}
public
static
class
MockConfigUtil
extends
ConfigUtil
{
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/integration/ConfigIntegrationTest.java
View file @
5c6081a0
...
...
@@ -57,6 +57,9 @@ public class ConfigIntegrationTest extends BaseIntegrationTest {
defaultNamespace
=
ConfigConsts
.
NAMESPACE_APPLICATION
;
someReleaseKey
=
"1"
;
configDir
=
new
File
(
ClassLoaderUtil
.
getClassPath
()
+
"config-cache"
);
if
(
configDir
.
exists
())
{
configDir
.
delete
();
}
configDir
.
mkdirs
();
}
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/DefaultConfigManagerTest.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.spi.ConfigFactory
;
import
com.ctrip.framework.apollo.spi.ConfigFactoryManager
;
import
com.ctrip.framework.apollo.spi.ConfigRegistry
;
import
org.junit.Before
;
import
org.junit.Test
;
...
...
@@ -11,18 +14,21 @@ import org.unidal.lookup.ComponentTestCase;
import
static
org
.
hamcrest
.
core
.
IsEqual
.
equalTo
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
mockito
.
Mockito
.
mock
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
DefaultConfigManagerTest
extends
ComponentTestCase
{
private
DefaultConfigManager
defaultConfigManager
;
private
static
String
someConfigContent
;
@Before
public
void
setUp
()
throws
Exception
{
super
.
setUp
();
defineComponent
(
ConfigFactoryManager
.
class
,
MockConfigManager
.
class
);
defaultConfigManager
=
(
DefaultConfigManager
)
lookup
(
ConfigManager
.
class
);
someConfigContent
=
"someContent"
;
}
@Test
...
...
@@ -48,6 +54,34 @@ public class DefaultConfigManagerTest extends ComponentTestCase {
config
,
equalTo
(
anotherConfig
));
}
@Test
public
void
testGetConfigFile
()
throws
Exception
{
String
someNamespacePrefix
=
"someName"
;
ConfigFileFormat
someConfigFileFormat
=
ConfigFileFormat
.
Properties
;
ConfigFile
configFile
=
defaultConfigManager
.
getConfigFile
(
someNamespacePrefix
,
someConfigFileFormat
);
assertEquals
(
someConfigFileFormat
,
configFile
.
getConfigFileFormat
());
assertEquals
(
someConfigContent
,
configFile
.
getContent
());
}
@Test
public
void
testGetConfigFileMultipleTimesWithSameNamespace
()
throws
Exception
{
String
someNamespacePrefix
=
"someName"
;
ConfigFileFormat
someConfigFileFormat
=
ConfigFileFormat
.
Properties
;
ConfigFile
someConfigFile
=
defaultConfigManager
.
getConfigFile
(
someNamespacePrefix
,
someConfigFileFormat
);
ConfigFile
anotherConfigFile
=
defaultConfigManager
.
getConfigFile
(
someNamespacePrefix
,
someConfigFileFormat
);
assertThat
(
"Get config file multiple times with the same namespace should return the same config file instance"
,
someConfigFile
,
equalTo
(
anotherConfigFile
));
}
public
static
class
MockConfigManager
implements
ConfigFactoryManager
{
@Override
...
...
@@ -62,6 +96,28 @@ public class DefaultConfigManagerTest extends ComponentTestCase {
}
};
}
@Override
public
ConfigFile
createConfigFile
(
String
namespace
,
final
ConfigFileFormat
configFileFormat
)
{
ConfigRepository
someConfigRepository
=
mock
(
ConfigRepository
.
class
);
return
new
AbstractConfigFile
(
namespace
,
someConfigRepository
)
{
@Override
public
String
getContent
()
{
return
someConfigContent
;
}
@Override
public
boolean
hasContent
()
{
return
true
;
}
@Override
public
ConfigFileFormat
getConfigFileFormat
()
{
return
configFileFormat
;
}
};
}
};
}
}
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/PropertiesConfigFileTest.java
0 → 100644
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.Mock
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
java.util.Properties
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Mockito
.
when
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
PropertiesConfigFileTest
{
private
String
someNamespace
;
@Mock
private
ConfigRepository
configRepository
;
@Before
public
void
setUp
()
throws
Exception
{
someNamespace
=
"someName"
;
}
@Test
public
void
testWhenHasContent
()
throws
Exception
{
Properties
someProperties
=
new
Properties
();
String
someKey
=
"someKey"
;
String
someValue
=
"someValue"
;
someProperties
.
setProperty
(
someKey
,
someValue
);
when
(
configRepository
.
getConfig
()).
thenReturn
(
someProperties
);
PropertiesConfigFile
configFile
=
new
PropertiesConfigFile
(
someNamespace
,
configRepository
);
assertEquals
(
ConfigFileFormat
.
Properties
,
configFile
.
getConfigFileFormat
());
assertEquals
(
someNamespace
,
configFile
.
getNamespace
());
assertTrue
(
configFile
.
hasContent
());
assertTrue
(
configFile
.
getContent
().
contains
(
String
.
format
(
"%s=%s"
,
someKey
,
someValue
)));
}
@Test
public
void
testWhenHasNoContent
()
throws
Exception
{
when
(
configRepository
.
getConfig
()).
thenReturn
(
null
);
PropertiesConfigFile
configFile
=
new
PropertiesConfigFile
(
someNamespace
,
configRepository
);
assertFalse
(
configFile
.
hasContent
());
assertNull
(
configFile
.
getContent
());
}
@Test
public
void
testWhenConfigRepositoryHasError
()
throws
Exception
{
when
(
configRepository
.
getConfig
()).
thenThrow
(
new
RuntimeException
(
"someError"
));
PropertiesConfigFile
configFile
=
new
PropertiesConfigFile
(
someNamespace
,
configRepository
);
assertFalse
(
configFile
.
hasContent
());
assertNull
(
configFile
.
getContent
());
}
@Test
public
void
testOnRepositoryChange
()
throws
Exception
{
Properties
someProperties
=
new
Properties
();
String
someKey
=
"someKey"
;
String
someValue
=
"someValue"
;
String
anotherValue
=
"anotherValue"
;
someProperties
.
setProperty
(
someKey
,
someValue
);
when
(
configRepository
.
getConfig
()).
thenReturn
(
someProperties
);
PropertiesConfigFile
configFile
=
new
PropertiesConfigFile
(
someNamespace
,
configRepository
);
assertTrue
(
configFile
.
getContent
().
contains
(
String
.
format
(
"%s=%s"
,
someKey
,
someValue
)));
Properties
anotherProperties
=
new
Properties
();
anotherProperties
.
setProperty
(
someKey
,
anotherValue
);
configFile
.
onRepositoryChange
(
someNamespace
,
anotherProperties
);
assertFalse
(
configFile
.
getContent
().
contains
(
String
.
format
(
"%s=%s"
,
someKey
,
someValue
)));
assertTrue
(
configFile
.
getContent
().
contains
(
String
.
format
(
"%s=%s"
,
someKey
,
anotherValue
)));
}
@Test
public
void
testWhenConfigRepositoryHasErrorAndThenRecovered
()
throws
Exception
{
Properties
someProperties
=
new
Properties
();
String
someKey
=
"someKey"
;
String
someValue
=
"someValue"
;
someProperties
.
setProperty
(
someKey
,
someValue
);
when
(
configRepository
.
getConfig
()).
thenThrow
(
new
RuntimeException
(
"someError"
));
PropertiesConfigFile
configFile
=
new
PropertiesConfigFile
(
someNamespace
,
configRepository
);
assertFalse
(
configFile
.
hasContent
());
assertNull
(
configFile
.
getContent
());
configFile
.
onRepositoryChange
(
someNamespace
,
someProperties
);
assertTrue
(
configFile
.
hasContent
());
assertTrue
(
configFile
.
getContent
().
contains
(
String
.
format
(
"%s=%s"
,
someKey
,
someValue
)));
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/XmlConfigFileTest.java
0 → 100644
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.Mock
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
java.util.Properties
;
import
static
org
.
junit
.
Assert
.*;
import
static
org
.
mockito
.
Mockito
.
when
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
XmlConfigFileTest
{
private
String
someNamespace
;
@Mock
private
ConfigRepository
configRepository
;
@Before
public
void
setUp
()
throws
Exception
{
someNamespace
=
"someName"
;
}
@Test
public
void
testWhenHasContent
()
throws
Exception
{
Properties
someProperties
=
new
Properties
();
String
key
=
ConfigConsts
.
CONFIG_FILE_CONTENT_KEY
;
String
someValue
=
"someValue"
;
someProperties
.
setProperty
(
key
,
someValue
);
when
(
configRepository
.
getConfig
()).
thenReturn
(
someProperties
);
XmlConfigFile
configFile
=
new
XmlConfigFile
(
someNamespace
,
configRepository
);
assertEquals
(
ConfigFileFormat
.
XML
,
configFile
.
getConfigFileFormat
());
assertEquals
(
someNamespace
,
configFile
.
getNamespace
());
assertTrue
(
configFile
.
hasContent
());
assertEquals
(
someValue
,
configFile
.
getContent
());
}
@Test
public
void
testWhenHasNoContent
()
throws
Exception
{
when
(
configRepository
.
getConfig
()).
thenReturn
(
null
);
XmlConfigFile
configFile
=
new
XmlConfigFile
(
someNamespace
,
configRepository
);
assertFalse
(
configFile
.
hasContent
());
assertNull
(
configFile
.
getContent
());
}
@Test
public
void
testWhenConfigRepositoryHasError
()
throws
Exception
{
when
(
configRepository
.
getConfig
()).
thenThrow
(
new
RuntimeException
(
"someError"
));
XmlConfigFile
configFile
=
new
XmlConfigFile
(
someNamespace
,
configRepository
);
assertFalse
(
configFile
.
hasContent
());
assertNull
(
configFile
.
getContent
());
}
@Test
public
void
testOnRepositoryChange
()
throws
Exception
{
Properties
someProperties
=
new
Properties
();
String
key
=
ConfigConsts
.
CONFIG_FILE_CONTENT_KEY
;
String
someValue
=
"someValue"
;
String
anotherValue
=
"anotherValue"
;
someProperties
.
setProperty
(
key
,
someValue
);
when
(
configRepository
.
getConfig
()).
thenReturn
(
someProperties
);
XmlConfigFile
configFile
=
new
XmlConfigFile
(
someNamespace
,
configRepository
);
assertEquals
(
someValue
,
configFile
.
getContent
());
Properties
anotherProperties
=
new
Properties
();
anotherProperties
.
setProperty
(
key
,
anotherValue
);
configFile
.
onRepositoryChange
(
someNamespace
,
anotherProperties
);
assertEquals
(
anotherValue
,
configFile
.
getContent
());
}
@Test
public
void
testWhenConfigRepositoryHasErrorAndThenRecovered
()
throws
Exception
{
Properties
someProperties
=
new
Properties
();
String
key
=
ConfigConsts
.
CONFIG_FILE_CONTENT_KEY
;
String
someValue
=
"someValue"
;
someProperties
.
setProperty
(
key
,
someValue
);
when
(
configRepository
.
getConfig
()).
thenThrow
(
new
RuntimeException
(
"someError"
));
XmlConfigFile
configFile
=
new
XmlConfigFile
(
someNamespace
,
configRepository
);
assertFalse
(
configFile
.
hasContent
());
assertNull
(
configFile
.
getContent
());
configFile
.
onRepositoryChange
(
someNamespace
,
someProperties
);
assertTrue
(
configFile
.
hasContent
());
assertEquals
(
someValue
,
configFile
.
getContent
());
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/spi/DefaultConfigFactoryManagerTest.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
spi
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
org.junit.Before
;
import
org.junit.Test
;
...
...
@@ -75,6 +77,12 @@ public class DefaultConfigFactoryManagerTest extends ComponentTestCase {
public
Config
create
(
String
namespace
)
{
return
null
;
}
@Override
public
ConfigFile
createConfigFile
(
String
namespace
,
ConfigFileFormat
configFileFormat
)
{
return
null
;
}
};
@Override
...
...
@@ -96,6 +104,11 @@ public class DefaultConfigFactoryManagerTest extends ComponentTestCase {
public
Config
create
(
String
namespace
)
{
return
null
;
}
@Override
public
ConfigFile
createConfigFile
(
String
namespace
,
ConfigFileFormat
configFileFormat
)
{
return
null
;
}
}
public
static
class
AnotherConfigFactory
implements
ConfigFactory
{
...
...
@@ -103,6 +116,11 @@ public class DefaultConfigFactoryManagerTest extends ComponentTestCase {
public
Config
create
(
String
namespace
)
{
return
null
;
}
@Override
public
ConfigFile
createConfigFile
(
String
namespace
,
ConfigFileFormat
configFileFormat
)
{
return
null
;
}
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/spi/DefaultConfigFactoryTest.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
spi
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.internals.DefaultConfig
;
import
com.ctrip.framework.apollo.internals.LocalFileConfigRepository
;
import
com.ctrip.framework.apollo.internals.PropertiesConfigFile
;
import
com.ctrip.framework.apollo.internals.XmlConfigFile
;
import
org.junit.Before
;
import
org.junit.Test
;
...
...
@@ -14,6 +18,7 @@ import static org.hamcrest.core.Is.is;
import
static
org
.
hamcrest
.
core
.
IsInstanceOf
.
instanceOf
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Mockito
.
doReturn
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
spy
;
...
...
@@ -51,4 +56,30 @@ public class DefaultConfigFactoryTest extends ComponentTestCase {
assertEquals
(
someValue
,
result
.
getProperty
(
someKey
,
null
));
}
@Test
public
void
testCreateConfigFile
()
throws
Exception
{
String
someNamespace
=
"someName"
;
String
anotherNamespace
=
"anotherName"
;
Properties
someProperties
=
new
Properties
();
LocalFileConfigRepository
someLocalConfigRepo
=
mock
(
LocalFileConfigRepository
.
class
);
when
(
someLocalConfigRepo
.
getConfig
()).
thenReturn
(
someProperties
);
doReturn
(
someLocalConfigRepo
).
when
(
defaultConfigFactory
).
createLocalConfigRepository
(
someNamespace
);
doReturn
(
someLocalConfigRepo
).
when
(
defaultConfigFactory
).
createLocalConfigRepository
(
anotherNamespace
);
ConfigFile
propertyConfigFile
=
defaultConfigFactory
.
createConfigFile
(
someNamespace
,
ConfigFileFormat
.
Properties
);
ConfigFile
xmlConfigFile
=
defaultConfigFactory
.
createConfigFile
(
anotherNamespace
,
ConfigFileFormat
.
XML
);
assertThat
(
"Should create PropertiesConfigFile for properties format"
,
propertyConfigFile
,
is
(
instanceOf
(
PropertiesConfigFile
.
class
)));
assertEquals
(
someNamespace
,
propertyConfigFile
.
getNamespace
());
assertThat
(
"Should create XmlConfigFile for xml format"
,
xmlConfigFile
,
is
(
instanceOf
(
XmlConfigFile
.
class
)));
assertEquals
(
anotherNamespace
,
xmlConfigFile
.
getNamespace
());
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/spi/DefaultConfigRegistryTest.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
spi
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
org.junit.Before
;
import
org.junit.Test
;
...
...
@@ -46,5 +48,10 @@ public class DefaultConfigRegistryTest extends ComponentTestCase {
public
Config
create
(
String
namespace
)
{
return
null
;
}
@Override
public
ConfigFile
createConfigFile
(
String
namespace
,
ConfigFileFormat
configFileFormat
)
{
return
null
;
}
}
}
apollo-common/src/main/java/com/ctrip/framework/apollo/common/entity/AppNamespace.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
common
.
entity
;
import
javax.persistence.Column
;
import
javax.persistence.Entity
;
import
javax.persistence.Table
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
org.bouncycastle.util.Strings
;
import
org.hibernate.annotations.SQLDelete
;
import
org.hibernate.annotations.Where
;
import
javax.persistence.Column
;
import
javax.persistence.Entity
;
import
javax.persistence.Table
;
@Entity
@Table
(
name
=
"AppNamespace"
)
@SQLDelete
(
sql
=
"Update AppNamespace set isDeleted = 1 where id = ?"
)
...
...
@@ -20,6 +23,12 @@ public class AppNamespace extends BaseEntity {
@Column
(
name
=
"AppId"
,
nullable
=
false
)
private
String
appId
;
@Column
(
name
=
"Format"
,
nullable
=
false
)
private
String
format
;
@Column
(
name
=
"IsPublic"
,
columnDefinition
=
"Bit default '0'"
)
private
boolean
isPublic
=
false
;
@Column
(
name
=
"Comment"
)
private
String
comment
;
...
...
@@ -47,8 +56,28 @@ public class AppNamespace extends BaseEntity {
this
.
name
=
name
;
}
public
boolean
isPublic
()
{
return
isPublic
;
}
public
void
setPublic
(
boolean
aPublic
)
{
isPublic
=
aPublic
;
}
public
ConfigFileFormat
getFormatAsEnum
()
{
return
ConfigFileFormat
.
fromString
(
this
.
format
);
}
public
String
getFormat
()
{
return
format
;
}
public
void
setFormat
(
String
format
)
{
this
.
format
=
format
;
}
public
String
toString
()
{
return
toStringHelper
().
add
(
"name"
,
name
).
add
(
"appId"
,
appId
).
add
(
"comment"
,
comment
)
.
toString
();
.
add
(
"format"
,
format
).
add
(
"isPublic"
,
isPublic
).
toString
();
}
}
apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/InputValidator.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
common
.
utils
;
import
com.ctrip.framework.apollo.core.utils.StringUtils
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
...
...
@@ -8,12 +10,24 @@ import java.util.regex.Pattern;
*/
public
class
InputValidator
{
public
static
final
String
INVALID_CLUSTER_NAMESPACE_MESSAGE
=
"只允许输入数字,字母和符号 - _ ."
;
public
static
final
String
INVALID_NAMESPACE_NAMESPACE_MESSAGE
=
"不允许以.json|.yml|.yaml|.xml|.properties结尾"
;
public
static
final
String
CLUSTER_NAMESPACE_VALIDATOR
=
"[0-9a-zA-z_.-]+"
;
public
static
final
String
APP_NAMESPACE_VALIDATOR
=
"[a-zA-z0-9._-]+(?<!\\.(json|yml|yaml|xml|properties))$"
;
private
static
final
Pattern
CLUSTER_NAMESPACE_PATTERN
=
Pattern
.
compile
(
CLUSTER_NAMESPACE_VALIDATOR
);
private
static
final
Pattern
APP_NAMESPACE_PATTERN
=
Pattern
.
compile
(
APP_NAMESPACE_VALIDATOR
);
public
static
boolean
isValidClusterNamespace
(
String
input
)
{
Matcher
matcher
=
CLUSTER_NAMESPACE_PATTERN
.
matcher
(
input
);
return
matcher
.
matches
();
}
public
static
boolean
isValidAppNamespace
(
String
name
){
if
(
StringUtils
.
isEmpty
(
name
)){
return
false
;
}
return
CLUSTER_NAMESPACE_PATTERN
.
matcher
(
name
.
toLowerCase
()).
matches
()
&&
APP_NAMESPACE_PATTERN
.
matcher
(
name
).
matches
();
}
}
apollo-common/src/main/java/com/ctrip/framework/apollo/common/utils/RequestPrecondition.java
View file @
5c6081a0
...
...
@@ -4,6 +4,7 @@ package com.ctrip.framework.apollo.common.utils;
import
com.ctrip.framework.apollo.core.exception.BadRequestException
;
import
com.ctrip.framework.apollo.core.utils.StringUtils
;
public
class
RequestPrecondition
{
private
static
String
CONTAIN_EMPTY_ARGUMENT
=
"request payload should not be contain empty."
;
...
...
@@ -12,6 +13,7 @@ public class RequestPrecondition {
private
static
String
ILLEGAL_NUMBER
=
"number should be positive"
;
public
static
void
checkArgument
(
String
...
args
)
{
checkArgument
(!
StringUtils
.
isContainEmpty
(
args
),
CONTAIN_EMPTY_ARGUMENT
);
}
...
...
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/ConfigController.java
View file @
5c6081a0
...
...
@@ -12,6 +12,7 @@ import com.ctrip.framework.apollo.common.entity.AppNamespace;
import
com.ctrip.framework.apollo.biz.entity.Release
;
import
com.ctrip.framework.apollo.biz.service.AppNamespaceService
;
import
com.ctrip.framework.apollo.biz.service.ConfigService
;
import
com.ctrip.framework.apollo.configservice.util.NamespaceUtil
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.dto.ApolloConfig
;
import
com.dianping.cat.Cat
;
...
...
@@ -41,6 +42,8 @@ public class ConfigController {
private
ConfigService
configService
;
@Autowired
private
AppNamespaceService
appNamespaceService
;
@Autowired
private
NamespaceUtil
namespaceUtil
;
private
static
final
Gson
gson
=
new
Gson
();
private
static
final
Type
configurationTypeReference
=
...
...
@@ -55,6 +58,11 @@ public class ConfigController {
@RequestParam
(
value
=
"releaseKey"
,
defaultValue
=
"-1"
)
String
clientSideReleaseKey
,
@RequestParam
(
value
=
"ip"
,
required
=
false
)
String
clientIp
,
HttpServletResponse
response
)
throws
IOException
{
String
originalNamespace
=
namespace
;
//strip out .properties suffix
namespace
=
namespaceUtil
.
filterNamespaceName
(
namespace
);
List
<
Release
>
releases
=
Lists
.
newLinkedList
();
Release
currentAppRelease
=
loadConfig
(
appId
,
clusterName
,
namespace
,
dataCenter
);
...
...
@@ -66,8 +74,8 @@ public class ConfigController {
appClusterNameLoaded
=
currentAppRelease
.
getClusterName
();
}
//if namespace
is not 'application', should check if it'
s a public configuration
if
(!
Objects
.
equals
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
namespace
))
{
//if namespace
does not belong to this appId, should check if there i
s a public configuration
if
(!
namespaceBelongsToAppId
(
appId
,
namespace
))
{
Release
publicRelease
=
this
.
findPublicConfig
(
appId
,
clusterName
,
namespace
,
dataCenter
);
if
(!
Objects
.
isNull
(
publicRelease
))
{
releases
.
add
(
publicRelease
);
...
...
@@ -78,9 +86,9 @@ public class ConfigController {
response
.
sendError
(
HttpServletResponse
.
SC_NOT_FOUND
,
String
.
format
(
"Could not load configurations with appId: %s, clusterName: %s, namespace: %s"
,
appId
,
clusterName
,
n
amespace
));
appId
,
clusterName
,
originalN
amespace
));
Cat
.
logEvent
(
"Apollo.Config.NotFound"
,
assembleKey
(
appId
,
clusterName
,
n
amespace
,
dataCenter
));
assembleKey
(
appId
,
clusterName
,
originalN
amespace
,
dataCenter
));
return
null
;
}
...
...
@@ -91,24 +99,35 @@ public class ConfigController {
// Client side configuration is the same with server side, return 304
response
.
setStatus
(
HttpServletResponse
.
SC_NOT_MODIFIED
);
Cat
.
logEvent
(
"Apollo.Config.NotModified"
,
assembleKey
(
appId
,
appClusterNameLoaded
,
n
amespace
,
dataCenter
));
assembleKey
(
appId
,
appClusterNameLoaded
,
originalN
amespace
,
dataCenter
));
return
null
;
}
ApolloConfig
apolloConfig
=
new
ApolloConfig
(
appId
,
appClusterNameLoaded
,
n
amespace
,
mergedReleaseKey
);
ApolloConfig
apolloConfig
=
new
ApolloConfig
(
appId
,
appClusterNameLoaded
,
originalN
amespace
,
mergedReleaseKey
);
apolloConfig
.
setConfigurations
(
mergeReleaseConfigurations
(
releases
));
Cat
.
logEvent
(
"Apollo.Config.Found"
,
assembleKey
(
appId
,
appClusterNameLoaded
,
n
amespace
,
dataCenter
));
Cat
.
logEvent
(
"Apollo.Config.Found"
,
assembleKey
(
appId
,
appClusterNameLoaded
,
originalN
amespace
,
dataCenter
));
return
apolloConfig
;
}
private
boolean
namespaceBelongsToAppId
(
String
appId
,
String
namespaceName
)
{
//Every app has an 'application' namespace
if
(
Objects
.
equals
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
namespaceName
))
{
return
true
;
}
AppNamespace
appNamespace
=
appNamespaceService
.
findOne
(
appId
,
namespaceName
);
return
appNamespace
!=
null
;
}
/**
* @param applicationId the application which uses public config
* @param namespace the namespace
* @param dataCenter the datacenter
*/
private
Release
findPublicConfig
(
String
applicationId
,
String
clusterName
,
String
namespace
,
String
dataCenter
)
{
AppNamespace
appNamespace
=
appNamespaceService
.
findByNamespaceName
(
namespace
);
AppNamespace
appNamespace
=
appNamespaceService
.
find
Public
ByNamespaceName
(
namespace
);
//check whether the namespace's appId equals to current one
if
(
Objects
.
isNull
(
appNamespace
)
||
Objects
.
equals
(
applicationId
,
appNamespace
.
getAppId
()))
{
...
...
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/NotificationController.java
View file @
5c6081a0
...
...
@@ -16,6 +16,7 @@ import com.ctrip.framework.apollo.biz.message.Topics;
import
com.ctrip.framework.apollo.biz.service.AppNamespaceService
;
import
com.ctrip.framework.apollo.biz.service.ReleaseMessageService
;
import
com.ctrip.framework.apollo.biz.utils.EntityManagerUtil
;
import
com.ctrip.framework.apollo.configservice.util.NamespaceUtil
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.dto.ApolloConfigNotification
;
import
com.dianping.cat.Cat
;
...
...
@@ -60,6 +61,9 @@ public class NotificationController implements ReleaseMessageListener {
@Autowired
private
EntityManagerUtil
entityManagerUtil
;
@Autowired
private
NamespaceUtil
namespaceUtil
;
@RequestMapping
(
method
=
RequestMethod
.
GET
)
public
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
pollNotification
(
@RequestParam
(
value
=
"appId"
)
String
appId
,
...
...
@@ -68,10 +72,13 @@ public class NotificationController implements ReleaseMessageListener {
@RequestParam
(
value
=
"dataCenter"
,
required
=
false
)
String
dataCenter
,
@RequestParam
(
value
=
"notificationId"
,
defaultValue
=
"-1"
)
long
notificationId
,
@RequestParam
(
value
=
"ip"
,
required
=
false
)
String
clientIp
)
{
//strip out .properties suffix
namespace
=
namespaceUtil
.
filterNamespaceName
(
namespace
);
Set
<
String
>
watchedKeys
=
assembleWatchKeys
(
appId
,
cluster
,
namespace
,
dataCenter
);
//Listen on more namespaces
, since it's not the default
namespace
if
(!
Objects
.
equals
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
namespace
))
{
//Listen on more namespaces
if it's a public
namespace
if
(!
namespaceBelongsToAppId
(
appId
,
namespace
))
{
watchedKeys
.
addAll
(
this
.
findPublicConfigWatchKey
(
appId
,
cluster
,
namespace
,
dataCenter
));
}
...
...
@@ -124,7 +131,7 @@ public class NotificationController implements ReleaseMessageListener {
private
Set
<
String
>
findPublicConfigWatchKey
(
String
applicationId
,
String
clusterName
,
String
namespace
,
String
dataCenter
)
{
AppNamespace
appNamespace
=
appNamespaceService
.
findByNamespaceName
(
namespace
);
AppNamespace
appNamespace
=
appNamespaceService
.
find
Public
ByNamespaceName
(
namespace
);
//check whether the namespace's appId equals to current one
if
(
Objects
.
isNull
(
appNamespace
)
||
Objects
.
equals
(
applicationId
,
appNamespace
.
getAppId
()))
{
...
...
@@ -187,6 +194,17 @@ public class NotificationController implements ReleaseMessageListener {
logger
.
info
(
"Notification completed"
);
}
private
boolean
namespaceBelongsToAppId
(
String
appId
,
String
namespaceName
)
{
//Every app has an 'application' namespace
if
(
Objects
.
equals
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
namespaceName
))
{
return
true
;
}
AppNamespace
appNamespace
=
appNamespaceService
.
findOne
(
appId
,
namespaceName
);
return
appNamespace
!=
null
;
}
private
void
logWatchedKeysToCat
(
Set
<
String
>
watchedKeys
,
String
eventName
)
{
for
(
String
watchedKey
:
watchedKeys
)
{
Cat
.
logEvent
(
eventName
,
watchedKey
);
...
...
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/util/NamespaceUtil.java
0 → 100644
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
configservice
.
util
;
import
org.springframework.stereotype.Component
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Component
public
class
NamespaceUtil
{
public
String
filterNamespaceName
(
String
namespaceName
)
{
if
(
namespaceName
.
toLowerCase
().
endsWith
(
".properties"
))
{
int
dotIndex
=
namespaceName
.
lastIndexOf
(
"."
);
return
namespaceName
.
substring
(
0
,
dotIndex
);
}
return
namespaceName
;
}
}
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/AllTests.java
View file @
5c6081a0
...
...
@@ -4,6 +4,7 @@ import com.ctrip.framework.apollo.configservice.controller.ConfigControllerTest;
import
com.ctrip.framework.apollo.configservice.controller.NotificationControllerTest
;
import
com.ctrip.framework.apollo.configservice.integration.ConfigControllerIntegrationTest
;
import
com.ctrip.framework.apollo.configservice.integration.NotificationControllerIntegrationTest
;
import
com.ctrip.framework.apollo.configservice.util.NamespaceUtilTest
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.Suite
;
...
...
@@ -11,7 +12,8 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith
(
Suite
.
class
)
@SuiteClasses
({
ConfigControllerTest
.
class
,
NotificationControllerTest
.
class
,
ConfigControllerIntegrationTest
.
class
,
NotificationControllerIntegrationTest
.
class
})
ConfigControllerIntegrationTest
.
class
,
NotificationControllerIntegrationTest
.
class
,
NamespaceUtilTest
.
class
})
public
class
AllTests
{
}
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/ConfigControllerTest.java
View file @
5c6081a0
This diff is collapsed.
Click to expand it.
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/NotificationControllerTest.java
View file @
5c6081a0
...
...
@@ -4,12 +4,13 @@ import com.google.common.base.Joiner;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Multimap
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.biz.entity.ReleaseMessage
;
import
com.ctrip.framework.apollo.biz.message.Topics
;
import
com.ctrip.framework.apollo.biz.service.AppNamespaceService
;
import
com.ctrip.framework.apollo.biz.service.ReleaseMessageService
;
import
com.ctrip.framework.apollo.biz.utils.EntityManagerUtil
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.configservice.util.NamespaceUtil
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.dto.ApolloConfigNotification
;
...
...
@@ -51,6 +52,9 @@ public class NotificationControllerTest {
private
ReleaseMessageService
releaseMessageService
;
@Mock
private
EntityManagerUtil
entityManagerUtil
;
@Mock
private
NamespaceUtil
namespaceUtil
;
private
Multimap
<
String
,
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>>
deferredResults
;
...
...
@@ -60,6 +64,7 @@ public class NotificationControllerTest {
ReflectionTestUtils
.
setField
(
controller
,
"appNamespaceService"
,
appNamespaceService
);
ReflectionTestUtils
.
setField
(
controller
,
"releaseMessageService"
,
releaseMessageService
);
ReflectionTestUtils
.
setField
(
controller
,
"entityManagerUtil"
,
entityManagerUtil
);
ReflectionTestUtils
.
setField
(
controller
,
"namespaceUtil"
,
namespaceUtil
);
someAppId
=
"someAppId"
;
someCluster
=
"someCluster"
;
...
...
@@ -70,6 +75,9 @@ public class NotificationControllerTest {
someNotificationId
=
1
;
someClientIp
=
"someClientIp"
;
when
(
namespaceUtil
.
filterNamespaceName
(
defaultNamespace
)).
thenReturn
(
defaultNamespace
);
when
(
namespaceUtil
.
filterNamespaceName
(
somePublicNamespace
)).
thenReturn
(
somePublicNamespace
);
deferredResults
=
(
Multimap
<
String
,
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>>)
ReflectionTestUtils
.
getField
(
controller
,
"deferredResults"
);
...
...
@@ -95,6 +103,55 @@ public class NotificationControllerTest {
}
}
@Test
public
void
testPollNotificationWithDefaultNamespaceAsFile
()
throws
Exception
{
String
namespace
=
String
.
format
(
"%s.%s"
,
defaultNamespace
,
"properties"
);
when
(
namespaceUtil
.
filterNamespaceName
(
namespace
)).
thenReturn
(
defaultNamespace
);
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
deferredResult
=
controller
.
pollNotification
(
someAppId
,
someCluster
,
namespace
,
someDataCenter
,
someNotificationId
,
someClientIp
);
List
<
String
>
clusters
=
Lists
.
newArrayList
(
someCluster
,
someDataCenter
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
);
assertEquals
(
clusters
.
size
(),
deferredResults
.
size
());
for
(
String
cluster
:
clusters
)
{
String
key
=
Joiner
.
on
(
ConfigConsts
.
CLUSTER_NAMESPACE_SEPARATOR
)
.
join
(
someAppId
,
cluster
,
defaultNamespace
);
assertTrue
(
deferredResults
.
get
(
key
).
contains
(
deferredResult
));
}
}
@Test
public
void
testPollNotificationWithPrivateNamespaceAsFile
()
throws
Exception
{
String
namespace
=
String
.
format
(
"someNamespace.xml"
);
AppNamespace
appNamespace
=
mock
(
AppNamespace
.
class
);
when
(
namespaceUtil
.
filterNamespaceName
(
namespace
)).
thenReturn
(
namespace
);
when
(
appNamespaceService
.
findOne
(
someAppId
,
namespace
)).
thenReturn
(
appNamespace
);
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
deferredResult
=
controller
.
pollNotification
(
someAppId
,
someCluster
,
namespace
,
someDataCenter
,
someNotificationId
,
someClientIp
);
List
<
String
>
clusters
=
Lists
.
newArrayList
(
someCluster
,
someDataCenter
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
);
assertEquals
(
clusters
.
size
(),
deferredResults
.
size
());
for
(
String
cluster
:
clusters
)
{
String
key
=
Joiner
.
on
(
ConfigConsts
.
CLUSTER_NAMESPACE_SEPARATOR
)
.
join
(
someAppId
,
cluster
,
namespace
);
assertTrue
(
deferredResults
.
get
(
key
).
contains
(
deferredResult
));
}
}
@Test
public
void
testPollNotificationWithDefaultNamespaceWithNotificationIdOutDated
()
throws
Exception
{
long
notificationId
=
someNotificationId
+
1
;
...
...
@@ -156,7 +213,6 @@ public class NotificationControllerTest {
.
join
(
someAppId
,
cluster
,
defaultNamespace
);
assertTrue
(
deferredResults
.
get
(
key
).
contains
(
deferredResult
));
}
}
@Test
...
...
@@ -165,7 +221,7 @@ public class NotificationControllerTest {
AppNamespace
somePublicAppNamespace
=
assmbleAppNamespace
(
somePublicAppId
,
somePublicNamespace
);
when
(
appNamespaceService
.
findByNamespaceName
(
somePublicNamespace
))
when
(
appNamespaceService
.
find
Public
ByNamespaceName
(
somePublicNamespace
))
.
thenReturn
(
somePublicAppNamespace
);
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
...
...
@@ -193,6 +249,46 @@ public class NotificationControllerTest {
}
}
@Test
public
void
testPollNotificationWithPublicNamespaceAsFile
()
throws
Exception
{
String
somePublicNamespaceAsFile
=
String
.
format
(
"%s.%s"
,
somePublicNamespace
,
"xml"
);
String
somePublicAppId
=
"somePublicAppId"
;
AppNamespace
somePublicAppNamespace
=
assmbleAppNamespace
(
somePublicAppId
,
somePublicNamespace
);
when
(
namespaceUtil
.
filterNamespaceName
(
somePublicNamespaceAsFile
))
.
thenReturn
(
somePublicNamespace
);
when
(
appNamespaceService
.
findPublicByNamespaceName
(
somePublicNamespace
))
.
thenReturn
(
somePublicAppNamespace
);
when
(
appNamespaceService
.
findOne
(
someAppId
,
somePublicNamespace
)).
thenReturn
(
null
);
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
deferredResult
=
controller
.
pollNotification
(
someAppId
,
someCluster
,
somePublicNamespaceAsFile
,
someDataCenter
,
someNotificationId
,
someClientIp
);
List
<
String
>
clusters
=
Lists
.
newArrayList
(
someCluster
,
someDataCenter
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
);
assertEquals
(
clusters
.
size
()
*
2
,
deferredResults
.
size
());
for
(
String
cluster
:
clusters
)
{
String
publicKey
=
Joiner
.
on
(
ConfigConsts
.
CLUSTER_NAMESPACE_SEPARATOR
)
.
join
(
someAppId
,
cluster
,
somePublicNamespace
);
assertTrue
(
deferredResults
.
get
(
publicKey
).
contains
(
deferredResult
));
}
for
(
String
cluster
:
clusters
)
{
String
publicKey
=
Joiner
.
on
(
ConfigConsts
.
CLUSTER_NAMESPACE_SEPARATOR
)
.
join
(
somePublicAppId
,
cluster
,
somePublicNamespace
);
assertTrue
(
deferredResults
.
get
(
publicKey
).
contains
(
deferredResult
));
}
}
@Test
public
void
testPollNotificationWithPublicNamespaceWithNotificationIdOutDated
()
throws
Exception
{
long
notificationId
=
someNotificationId
+
1
;
...
...
@@ -206,7 +302,7 @@ public class NotificationControllerTest {
AppNamespace
somePublicAppNamespace
=
assmbleAppNamespace
(
somePublicAppId
,
somePublicNamespace
);
when
(
appNamespaceService
.
findByNamespaceName
(
somePublicNamespace
))
when
(
appNamespaceService
.
find
Public
ByNamespaceName
(
somePublicNamespace
))
.
thenReturn
(
somePublicAppNamespace
);
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
...
...
@@ -253,7 +349,7 @@ public class NotificationControllerTest {
AppNamespace
somePublicAppNamespace
=
assmbleAppNamespace
(
somePublicAppId
,
somePublicNamespace
);
when
(
appNamespaceService
.
findByNamespaceName
(
somePublicNamespace
))
when
(
appNamespaceService
.
find
Public
ByNamespaceName
(
somePublicNamespace
))
.
thenReturn
(
somePublicAppNamespace
);
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
...
...
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/ConfigControllerIntegrationTest.java
View file @
5c6081a0
...
...
@@ -47,6 +47,20 @@ public class ConfigControllerIntegrationTest extends AbstractBaseIntegrationTest
assertEquals
(
"v1"
,
result
.
getConfigurations
().
get
(
"k1"
));
}
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testQueryConfigFileWithDefaultClusterAndDefaultNamespaceOK
()
throws
Exception
{
ResponseEntity
<
ApolloConfig
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configs/{appId}/{clusterName}/{namespace}"
,
ApolloConfig
.
class
,
getHostUrl
(),
someAppId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
ConfigConsts
.
NAMESPACE_APPLICATION
+
".properties"
);
ApolloConfig
result
=
response
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
response
.
getStatusCode
());
assertEquals
(
"TEST-RELEASE-KEY1"
,
result
.
getReleaseKey
());
assertEquals
(
"v1"
,
result
.
getConfigurations
().
get
(
"k1"
));
}
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
...
...
@@ -61,6 +75,21 @@ public class ConfigControllerIntegrationTest extends AbstractBaseIntegrationTest
assertEquals
(
"v2"
,
result
.
getConfigurations
().
get
(
"k2"
));
}
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testQueryConfigFileWithNamespaceOK
()
throws
Exception
{
ResponseEntity
<
ApolloConfig
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configs/{appId}/{clusterName}/{namespace}"
,
ApolloConfig
.
class
,
getHostUrl
(),
someAppId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
someNamespace
+
".xml"
);
ApolloConfig
result
=
response
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
response
.
getStatusCode
());
assertEquals
(
"TEST-RELEASE-KEY5"
,
result
.
getReleaseKey
());
assertEquals
(
"v1-file"
,
result
.
getConfigurations
().
get
(
"k1"
));
assertEquals
(
"v2-file"
,
result
.
getConfigurations
().
get
(
"k2"
));
}
@Test
public
void
testQueryConfigError
()
throws
Exception
{
String
someNamespaceNotExists
=
"someNamespaceNotExists"
;
...
...
@@ -168,6 +197,24 @@ public class ConfigControllerIntegrationTest extends AbstractBaseIntegrationTest
assertEquals
(
somePublicNamespace
,
result
.
getNamespaceName
());
assertEquals
(
"override-v1"
,
result
.
getConfigurations
().
get
(
"k1"
));
assertEquals
(
"default-v2"
,
result
.
getConfigurations
().
get
(
"k2"
));
}
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testQueryPrivateConfigFileWithPublicNamespaceExists
()
throws
Exception
{
String
namespaceName
=
"anotherNamespace"
;
ResponseEntity
<
ApolloConfig
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configs/{appId}/{clusterName}/{namespace}"
,
ApolloConfig
.
class
,
getHostUrl
(),
someAppId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
namespaceName
);
ApolloConfig
result
=
response
.
getBody
();
assertEquals
(
"TEST-RELEASE-KEY6"
,
result
.
getReleaseKey
());
assertEquals
(
someAppId
,
result
.
getAppId
());
assertEquals
(
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
result
.
getCluster
());
assertEquals
(
namespaceName
,
result
.
getNamespaceName
());
assertEquals
(
"v1-file"
,
result
.
getConfigurations
().
get
(
"k1"
));
assertEquals
(
null
,
result
.
getConfigurations
().
get
(
"k2"
));
}
}
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/NotificationControllerIntegrationTest.java
View file @
5c6081a0
...
...
@@ -65,6 +65,47 @@ public class NotificationControllerIntegrationTest extends AbstractBaseIntegrati
assertNotEquals
(
0
,
notification
.
getNotificationId
());
}
@Test
(
timeout
=
5000L
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testPollNotificationWithDefaultNamespaceAsFile
()
throws
Exception
{
AtomicBoolean
stop
=
new
AtomicBoolean
();
periodicSendMessage
(
assembleKey
(
someAppId
,
someCluster
,
defaultNamespace
),
stop
);
ResponseEntity
<
ApolloConfigNotification
>
result
=
restTemplate
.
getForEntity
(
"{baseurl}/notifications?appId={appId}&cluster={clusterName}&namespace={namespace}"
,
ApolloConfigNotification
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
defaultNamespace
+
".properties"
);
stop
.
set
(
true
);
ApolloConfigNotification
notification
=
result
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
result
.
getStatusCode
());
assertEquals
(
defaultNamespace
,
notification
.
getNamespaceName
());
assertNotEquals
(
0
,
notification
.
getNotificationId
());
}
@Test
(
timeout
=
5000L
)
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testPollNotificationWithPrivateNamespaceAsFile
()
throws
Exception
{
String
namespace
=
"someNamespace.xml"
;
AtomicBoolean
stop
=
new
AtomicBoolean
();
periodicSendMessage
(
assembleKey
(
someAppId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
namespace
),
stop
);
ResponseEntity
<
ApolloConfigNotification
>
result
=
restTemplate
.
getForEntity
(
"{baseurl}/notifications?appId={appId}&cluster={clusterName}&namespace={namespace}"
,
ApolloConfigNotification
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
namespace
);
stop
.
set
(
true
);
ApolloConfigNotification
notification
=
result
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
result
.
getStatusCode
());
assertEquals
(
namespace
,
notification
.
getNamespaceName
());
assertNotEquals
(
0
,
notification
.
getNotificationId
());
}
@Test
(
timeout
=
5000L
)
@Sql
(
scripts
=
"/integration-test/test-release-message.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
...
...
@@ -144,6 +185,30 @@ public class NotificationControllerIntegrationTest extends AbstractBaseIntegrati
assertNotEquals
(
0
,
notification
.
getNotificationId
());
}
@Test
(
timeout
=
5000L
)
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testPollNotificationWthPublicNamespaceAsFile
()
throws
Exception
{
String
publicAppId
=
"somePublicAppId"
;
String
someDC
=
"someDC"
;
AtomicBoolean
stop
=
new
AtomicBoolean
();
periodicSendMessage
(
assembleKey
(
publicAppId
,
someDC
,
somePublicNamespace
),
stop
);
ResponseEntity
<
ApolloConfigNotification
>
result
=
restTemplate
.
getForEntity
(
"{baseurl}/notifications?appId={appId}&cluster={clusterName}&namespace={namespace}&dataCenter={dataCenter}"
,
ApolloConfigNotification
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
somePublicNamespace
+
".properties"
,
someDC
);
stop
.
set
(
true
);
ApolloConfigNotification
notification
=
result
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
result
.
getStatusCode
());
assertEquals
(
somePublicNamespace
,
notification
.
getNamespaceName
());
assertNotEquals
(
0
,
notification
.
getNotificationId
());
}
@Test
(
timeout
=
5000L
)
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/test-release-message.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
...
...
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/util/NamespaceUtilTest.java
0 → 100644
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
configservice
.
util
;
import
org.junit.Before
;
import
org.junit.Test
;
import
static
org
.
junit
.
Assert
.*;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
NamespaceUtilTest
{
private
NamespaceUtil
namespaceUtil
;
@Before
public
void
setUp
()
throws
Exception
{
namespaceUtil
=
new
NamespaceUtil
();
}
@Test
public
void
testFilterNamespaceName
()
throws
Exception
{
String
someName
=
"a.properties"
;
assertEquals
(
"a"
,
namespaceUtil
.
filterNamespaceName
(
someName
));
}
@Test
public
void
testFilterNamespaceNameUnchanged
()
throws
Exception
{
String
someName
=
"a.xml"
;
assertEquals
(
someName
,
namespaceUtil
.
filterNamespaceName
(
someName
));
}
@Test
public
void
testFilterNamespaceNameWithMultiplePropertiesSuffix
()
throws
Exception
{
String
someName
=
"a.properties.properties"
;
assertEquals
(
"a.properties"
,
namespaceUtil
.
filterNamespaceName
(
someName
));
}
@Test
public
void
testFilterNamespaceNameWithRandomCase
()
throws
Exception
{
String
someName
=
"AbC.ProPErties"
;
assertEquals
(
"AbC"
,
namespaceUtil
.
filterNamespaceName
(
someName
));
}
@Test
public
void
testFilterNamespaceNameWithRandomCaseUnchanged
()
throws
Exception
{
String
someName
=
"AbCD.xMl"
;
assertEquals
(
someName
,
namespaceUtil
.
filterNamespaceName
(
someName
));
}
}
apollo-configservice/src/test/resources/integration-test/test-release.sql
View file @
5c6081a0
...
...
@@ -6,16 +6,22 @@ INSERT INTO Cluster (AppId, Name) VALUES ('someAppId', 'someCluster');
INSERT
INTO
Cluster
(
AppId
,
Name
)
VALUES
(
'somePublicAppId'
,
'default'
);
INSERT
INTO
Cluster
(
AppId
,
Name
)
VALUES
(
'somePublicAppId'
,
'someDC'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'someAppId'
,
'application'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'someAppId'
,
'someNamespace'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'somePublicAppId'
,
'application'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
)
VALUES
(
'somePublicAppId'
,
'somePublicNamespace'
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'someAppId'
,
'application'
,
false
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'someAppId'
,
'someNamespace'
,
true
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'someAppId'
,
'someNamespace.xml'
,
false
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'someAppId'
,
'anotherNamespace'
,
false
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'somePublicAppId'
,
'application'
,
false
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'somePublicAppId'
,
'somePublicNamespace'
,
true
);
INSERT
INTO
AppNamespace
(
AppId
,
Name
,
IsPublic
)
VALUES
(
'somePublicAppId'
,
'anotherNamespace'
,
true
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'someAppId'
,
'default'
,
'application'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'someAppId'
,
'default'
,
'someNamespace.xml'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'someAppId'
,
'default'
,
'anotherNamespace'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'someAppId'
,
'someCluster'
,
'someNamespace'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'somePublicAppId'
,
'default'
,
'application'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'somePublicAppId'
,
'someDC'
,
'somePublicNamespace'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'someAppId'
,
'default'
,
'somePublicNamespace'
);
INSERT
INTO
Namespace
(
AppId
,
ClusterName
,
NamespaceName
)
VALUES
(
'somePublicAppId'
,
'default'
,
'anotherNamespace'
);
INSERT
INTO
RELEASE
(
id
,
ReleaseKey
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
990
,
'TEST-RELEASE-KEY1'
,
'INTEGRATION-TEST-DEFAULT'
,
'First Release'
,
'someAppId'
,
'default'
,
'application'
,
'{"k1":"v1"}'
);
...
...
@@ -25,3 +31,9 @@ INSERT INTO RELEASE (id, ReleaseKey, Name, Comment, AppId, ClusterName, Namespac
VALUES
(
992
,
'TEST-RELEASE-KEY3'
,
'INTEGRATION-TEST-PUBLIC-DEFAULT'
,
'First Release'
,
'somePublicAppId'
,
'default'
,
'somePublicNamespace'
,
'{"k1":"default-v1", "k2":"default-v2"}'
);
INSERT
INTO
RELEASE
(
id
,
ReleaseKey
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
993
,
'TEST-RELEASE-KEY4'
,
'INTEGRATION-TEST-PUBLIC-NAMESPACE'
,
'First Release'
,
'somePublicAppId'
,
'someDC'
,
'somePublicNamespace'
,
'{"k1":"someDC-v1", "k2":"someDC-v2"}'
);
INSERT
INTO
RELEASE
(
id
,
ReleaseKey
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
989
,
'TEST-RELEASE-KEY5'
,
'INTEGRATION-TEST-PRIVATE-CONFIG-FILE'
,
'First Release'
,
'someAppId'
,
'default'
,
'someNamespace.xml'
,
'{"k1":"v1-file", "k2":"v2-file"}'
);
INSERT
INTO
RELEASE
(
id
,
ReleaseKey
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
988
,
'TEST-RELEASE-KEY6'
,
'INTEGRATION-TEST-PRIVATE-CONFIG-FILE'
,
'First Release'
,
'someAppId'
,
'default'
,
'anotherNamespace'
,
'{"k1":"v1-file"}'
);
INSERT
INTO
RELEASE
(
id
,
ReleaseKey
,
Name
,
Comment
,
AppId
,
ClusterName
,
NamespaceName
,
Configurations
)
VALUES
(
987
,
'TEST-RELEASE-KEY7'
,
'INTEGRATION-TEST-PUBLIC-CONFIG-FILE'
,
'First Release'
,
'somePublicAppId'
,
'default'
,
'anotherNamespace'
,
'{"k2":"v2-file"}'
);
apollo-core/src/main/java/com/ctrip/framework/apollo/core/ConfigConsts.java
View file @
5c6081a0
...
...
@@ -5,4 +5,5 @@ public interface ConfigConsts {
String
CLUSTER_NAME_DEFAULT
=
"default"
;
String
CLUSTER_NAMESPACE_SEPARATOR
=
"+"
;
String
APOLLO_CLUSTER_KEY
=
"apollo.cluster"
;
String
FILE_NAMESPACE_KEY_NAME
=
"content"
;
}
apollo-core/src/main/java/com/ctrip/framework/apollo/core/dto/AppNamespaceDTO.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
core
.
dto
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
public
class
AppNamespaceDTO
extends
BaseDTO
{
private
long
id
;
...
...
@@ -9,6 +12,10 @@ public class AppNamespaceDTO extends BaseDTO{
private
String
comment
;
private
String
format
;
private
boolean
isPublic
=
false
;
public
long
getId
()
{
return
id
;
}
...
...
@@ -33,6 +40,26 @@ public class AppNamespaceDTO extends BaseDTO{
this
.
appId
=
appId
;
}
public
ConfigFileFormat
getFormatAsEnum
()
{
return
ConfigFileFormat
.
fromString
(
this
.
format
);
}
public
String
getFormat
()
{
return
format
;
}
public
void
setFormat
(
String
format
)
{
this
.
format
=
format
;
}
public
boolean
isPublic
()
{
return
isPublic
;
}
public
void
setPublic
(
boolean
aPublic
)
{
isPublic
=
aPublic
;
}
public
String
getComment
()
{
return
comment
;
}
...
...
apollo-core/src/main/java/com/ctrip/framework/apollo/core/enums/ConfigFileFormat.java
0 → 100644
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
core
.
enums
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
enum
ConfigFileFormat
{
Properties
(
"properties"
),
XML
(
"xml"
);
private
String
value
;
ConfigFileFormat
(
String
value
)
{
this
.
value
=
value
;
}
public
String
getValue
()
{
return
value
;
}
public
static
ConfigFileFormat
fromString
(
String
value
){
switch
(
value
){
case
"properties"
:
return
Properties
;
case
"xml"
:
return
XML
;
}
throw
new
IllegalArgumentException
(
value
+
" can not map enum"
);
}
}
apollo-demo/src/main/java/ApolloConfigDemo.java
View file @
5c6081a0
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigChangeListener
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.ConfigService
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.model.ConfigChange
;
import
com.ctrip.framework.apollo.model.ConfigChangeEvent
;
...
...
apollo-demo/src/main/java/ApolloConfigFileDemo.java
0 → 100644
View file @
5c6081a0
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.ConfigService
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
ApolloConfigFileDemo
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ApolloConfigDemo
.
class
);
private
ConfigFile
configFile
;
private
String
namespacePrefix
=
"application"
;
public
ApolloConfigFileDemo
()
{
configFile
=
ConfigService
.
getConfigFile
(
namespacePrefix
,
ConfigFileFormat
.
XML
);
}
private
void
print
()
{
if
(!
configFile
.
hasContent
())
{
System
.
out
.
println
(
"No config file content found for "
+
namespacePrefix
);
return
;
}
System
.
out
.
println
(
"=== Config File Content for "
+
namespacePrefix
+
" is as follows: "
);
System
.
out
.
println
(
configFile
.
getContent
());
}
public
static
void
main
(
String
[]
args
)
throws
IOException
{
ApolloConfigFileDemo
apolloConfigFileDemo
=
new
ApolloConfigFileDemo
();
System
.
out
.
println
(
"Apollo Config File Demo. Please input print to get the config file content."
);
while
(
true
)
{
System
.
out
.
print
(
"> "
);
String
input
=
new
BufferedReader
(
new
InputStreamReader
(
System
.
in
)).
readLine
();
if
(
input
==
null
||
input
.
length
()
==
0
)
{
continue
;
}
input
=
input
.
trim
();
if
(
input
.
equalsIgnoreCase
(
"print"
))
{
apolloConfigFileDemo
.
print
();
}
if
(
input
.
equalsIgnoreCase
(
"quit"
))
{
System
.
exit
(
0
);
}
}
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/auth/PermissionValidator.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
auth
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.portal.constant.PermissionType
;
import
com.ctrip.framework.apollo.portal.service.RolePermissionService
;
import
com.ctrip.framework.apollo.portal.util.RoleUtils
;
...
...
@@ -15,36 +16,45 @@ public class PermissionValidator {
@Autowired
private
RolePermissionService
rolePermissionService
;
public
boolean
hasModifyNamespacePermission
(
String
appId
,
String
namespaceName
){
public
boolean
hasModifyNamespacePermission
(
String
appId
,
String
namespaceName
)
{
return
rolePermissionService
.
userHasPermission
(
userInfoHolder
.
getUser
().
getUserId
(),
PermissionType
.
MODIFY_NAMESPACE
,
RoleUtils
.
buildNamespaceTargetId
(
appId
,
namespaceName
));
PermissionType
.
MODIFY_NAMESPACE
,
RoleUtils
.
buildNamespaceTargetId
(
appId
,
namespaceName
));
}
public
boolean
hasReleaseNamespacePermission
(
String
appId
,
String
namespaceName
){
public
boolean
hasReleaseNamespacePermission
(
String
appId
,
String
namespaceName
)
{
return
rolePermissionService
.
userHasPermission
(
userInfoHolder
.
getUser
().
getUserId
(),
PermissionType
.
RELEASE_NAMESPACE
,
RoleUtils
.
buildNamespaceTargetId
(
appId
,
namespaceName
));
}
public
boolean
hasAssignRolePermission
(
String
appId
){
public
boolean
hasAssignRolePermission
(
String
appId
)
{
return
rolePermissionService
.
userHasPermission
(
userInfoHolder
.
getUser
().
getUserId
(),
PermissionType
.
ASSIGN_ROLE
,
appId
);
}
public
boolean
hasCreateNamespacePermission
(
String
appId
){
public
boolean
hasCreateNamespacePermission
(
String
appId
)
{
return
rolePermissionService
.
userHasPermission
(
userInfoHolder
.
getUser
().
getUserId
(),
PermissionType
.
CREATE_NAMESPACE
,
appId
);
}
public
boolean
hasCreateClusterPermission
(
String
appId
){
public
boolean
hasCreateClusterPermission
(
String
appId
)
{
return
rolePermissionService
.
userHasPermission
(
userInfoHolder
.
getUser
().
getUserId
(),
PermissionType
.
CREATE_CLUSTER
,
appId
);
}
public
boolean
hasCreateAppNamespacePermission
(
String
appId
,
AppNamespace
appNamespace
)
{
boolean
isPublicAppNamespace
=
appNamespace
.
isPublic
();
if
(
isPublicAppNamespace
){
return
hasCreateNamespacePermission
(
appId
);
}
else
{
return
rolePermissionService
.
isSuperAdmin
(
userInfoHolder
.
getUser
().
getUserId
());
}
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ConfigController.java
View file @
5c6081a0
...
...
@@ -12,6 +12,7 @@ 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.NamespaceReleaseModel
;
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.http.HttpStatus
;
...
...
@@ -33,11 +34,13 @@ public class ConfigController {
@Autowired
private
ConfigService
configService
;
@Autowired
private
ServerConfigService
serverConfigService
;
@PreAuthorize
(
value
=
"@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)"
)
@RequestMapping
(
value
=
"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items"
,
method
=
RequestMethod
.
PUT
,
consumes
=
{
"application/json"
})
public
void
modifyItems
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
public
void
modifyItems
ByText
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
,
@RequestBody
NamespaceTextModel
model
)
{
...
...
@@ -131,4 +134,5 @@ public class ConfigController {
return
item
!=
null
&&
!
StringUtils
.
isContainEmpty
(
item
.
getKey
());
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceController.java
View file @
5c6081a0
...
...
@@ -4,6 +4,7 @@ import com.ctrip.framework.apollo.common.entity.App;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.common.utils.InputValidator
;
import
com.ctrip.framework.apollo.core.dto.NamespaceDTO
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.core.exception.BadRequestException
;
import
com.ctrip.framework.apollo.core.utils.StringUtils
;
...
...
@@ -11,6 +12,7 @@ import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import
com.ctrip.framework.apollo.portal.entity.form.NamespaceCreationModel
;
import
com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO
;
import
com.ctrip.framework.apollo.portal.listener.AppNamespaceCreationEvent
;
import
com.ctrip.framework.apollo.portal.service.AppNamespaceService
;
import
com.ctrip.framework.apollo.portal.service.AppService
;
import
com.ctrip.framework.apollo.portal.service.NamespaceService
;
...
...
@@ -46,15 +48,18 @@ public class NamespaceController {
private
UserInfoHolder
userInfoHolder
;
@Autowired
private
NamespaceService
namespaceService
;
@Autowired
private
AppNamespaceService
appNamespaceService
;
@RequestMapping
(
"/appnamespaces/public"
)
public
List
<
AppNamespace
>
findPublicAppNamespaces
()
{
return
n
amespaceService
.
findPublicAppNamespaces
();
return
appN
amespaceService
.
findPublicAppNamespaces
();
}
@PreAuthorize
(
value
=
"@permissionValidator.hasCreateNamespacePermission(#appId)"
)
@RequestMapping
(
value
=
"/apps/{appId}/namespaces"
,
method
=
RequestMethod
.
POST
)
public
ResponseEntity
<
Void
>
createNamespace
(
@PathVariable
String
appId
,
@RequestBody
List
<
NamespaceCreationModel
>
models
)
{
public
ResponseEntity
<
Void
>
createNamespace
(
@PathVariable
String
appId
,
@RequestBody
List
<
NamespaceCreationModel
>
models
)
{
checkModel
(!
CollectionUtils
.
isEmpty
(
models
));
...
...
@@ -73,24 +78,31 @@ public class NamespaceController {
return
ResponseEntity
.
ok
().
build
();
}
@PreAuthorize
(
value
=
"@permissionValidator.hasCreateAppNamespacePermission(#appId, #appNamespace)"
)
@RequestMapping
(
value
=
"/apps/{appId}/appnamespaces"
,
method
=
RequestMethod
.
POST
)
public
void
createAppNamespace
(
@PathVariable
String
appId
,
@RequestBody
AppNamespace
appNamespace
)
{
checkArgument
(
appNamespace
.
getAppId
(),
appNamespace
.
getName
());
if
(!
InputValidator
.
isValidClusterNamespace
(
appNamespace
.
getName
()))
{
throw
new
BadRequestException
(
String
.
format
(
"Namespace格式错误: %s"
,
InputValidator
.
INVALID_CLUSTER_NAMESPACE_MESSAGE
));
if
(!
InputValidator
.
isValidAppNamespace
(
appNamespace
.
getName
()))
{
throw
new
BadRequestException
(
String
.
format
(
"Namespace格式错误: %s"
,
InputValidator
.
INVALID_CLUSTER_NAMESPACE_MESSAGE
+
" & "
+
InputValidator
.
INVALID_NAMESPACE_NAMESPACE_MESSAGE
));
}
//add app org id as prefix
App
app
=
appService
.
load
(
appId
);
appNamespace
.
setName
(
String
.
format
(
"%s.%s"
,
app
.
getOrgId
(),
appNamespace
.
getName
()));
if
(
appNamespace
.
getFormatAsEnum
()
==
ConfigFileFormat
.
Properties
)
{
appNamespace
.
setName
(
String
.
format
(
"%s.%s"
,
app
.
getOrgId
(),
appNamespace
.
getName
()));
}
else
{
appNamespace
.
setName
(
String
.
format
(
"%s.%s.%s"
,
app
.
getOrgId
(),
appNamespace
.
getName
(),
appNamespace
.
getFormat
()));
}
String
operator
=
userInfoHolder
.
getUser
().
getUserId
();
if
(
StringUtils
.
isEmpty
(
appNamespace
.
getDataChangeCreatedBy
()))
{
appNamespace
.
setDataChangeCreatedBy
(
operator
);
}
appNamespace
.
setDataChangeLastModifiedBy
(
operator
);
AppNamespace
createdAppNamespace
=
n
amespaceService
.
createAppNamespaceInLocal
(
appNamespace
);
AppNamespace
createdAppNamespace
=
appN
amespaceService
.
createAppNamespaceInLocal
(
appNamespace
);
publisher
.
publishEvent
(
new
AppNamespaceCreationEvent
(
createdAppNamespace
));
...
...
@@ -100,7 +112,7 @@ public class NamespaceController {
public
List
<
NamespaceVO
>
findNamespaces
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
)
{
return
namespaceService
.
findNam
p
spaces
(
appId
,
Env
.
valueOf
(
env
),
clusterName
);
return
namespaceService
.
findNam
e
spaces
(
appId
,
Env
.
valueOf
(
env
),
clusterName
);
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/PermissionController.java
View file @
5c6081a0
...
...
@@ -61,6 +61,15 @@ public class PermissionController {
return
ResponseEntity
.
ok
().
body
(
permissionCondition
);
}
@RequestMapping
(
"/permissions/root"
)
public
ResponseEntity
<
PermissionCondition
>
hasRootPermission
(){
PermissionCondition
permissionCondition
=
new
PermissionCondition
();
permissionCondition
.
setHasPermission
(
rolePermissionService
.
isSuperAdmin
(
userInfoHolder
.
getUser
().
getUserId
()));
return
ResponseEntity
.
ok
().
body
(
permissionCondition
);
}
@RequestMapping
(
"/apps/{appId}/namespaces/{namespaceName}/role_users"
)
public
NamespaceRolesAssignedUsers
getNamespaceRoles
(
@PathVariable
String
appId
,
@PathVariable
String
namespaceName
){
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/form/NamespaceTextModel.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
entity
.
form
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.core.utils.StringUtils
;
...
...
@@ -11,8 +12,10 @@ public class NamespaceTextModel implements Verifiable {
private
String
clusterName
;
private
String
namespaceName
;
private
int
namespaceId
;
private
String
format
;
private
String
configText
;
@Override
public
boolean
isInvalid
(){
return
StringUtils
.
isContainEmpty
(
appId
,
env
,
clusterName
,
namespaceName
)
||
namespaceId
<=
0
;
...
...
@@ -65,4 +68,11 @@ public class NamespaceTextModel implements Verifiable {
this
.
configText
=
configText
;
}
public
ConfigFileFormat
getFormat
()
{
return
ConfigFileFormat
.
fromString
(
this
.
format
);
}
public
void
setFormat
(
String
format
)
{
this
.
format
=
format
;
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/NamespaceVO.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
entity
.
vo
;
import
com.ctrip.framework.apollo.core.dto.ItemDTO
;
import
com.ctrip.framework.apollo.core.dto.NamespaceDTO
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
java.util.List
;
...
...
@@ -8,6 +9,7 @@ public class NamespaceVO {
private
NamespaceDTO
namespace
;
private
int
itemModifiedCnt
;
private
List
<
ItemVO
>
items
;
private
String
format
;
public
NamespaceDTO
getNamespace
()
{
...
...
@@ -34,6 +36,14 @@ public class NamespaceVO {
this
.
items
=
items
;
}
public
String
getFormat
()
{
return
format
;
}
public
void
setFormat
(
String
format
)
{
this
.
format
=
format
;
}
public
static
class
ItemVO
{
private
ItemDTO
item
;
private
boolean
isModified
;
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/CreationListener.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
listener
;
import
com.ctrip.framework.apollo.common.utils.BeanUtils
;
import
com.ctrip.framework.apollo.common.utils.ExceptionUtils
;
import
com.ctrip.framework.apollo.core.dto.AppDTO
;
import
com.ctrip.framework.apollo.core.dto.AppNamespaceDTO
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.portal.PortalSettings
;
import
com.ctrip.framework.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.framework.apollo.portal.service.RoleInitializationService
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -28,6 +28,8 @@ public class CreationListener {
private
AdminServiceAPI
.
AppAPI
appAPI
;
@Autowired
private
AdminServiceAPI
.
NamespaceAPI
namespaceAPI
;
@Autowired
private
RoleInitializationService
roleInitializationService
;
@EventListener
public
void
onAppCreationEvent
(
AppCreationEvent
event
)
{
...
...
@@ -53,6 +55,11 @@ public class CreationListener {
logger
.
error
(
"call namespaceAPI.createOrUpdateAppNamespace error. [{app}, {env}]"
,
dto
.
getAppId
(),
env
,
e
);
}
}
//如果是私有的app namespace 要默认初始化权限
if
(!
dto
.
isPublic
())
{
roleInitializationService
.
initNamespaceRoles
(
dto
.
getAppId
(),
dto
.
getName
());
}
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppNamespaceRepository.java
View file @
5c6081a0
...
...
@@ -12,6 +12,10 @@ public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNa
AppNamespace
findByName
(
String
namespaceName
);
AppNamespace
findByNameAndIsPublic
(
String
namespaceName
,
boolean
isPublic
);
List
<
AppNamespace
>
findByNameNot
(
String
namespaceName
);
List
<
AppNamespace
>
findByNameNotAndIsPublic
(
String
namespaceName
,
boolean
isPublic
);
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppNamespaceService.java
0 → 100644
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
service
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.common.utils.BeanUtils
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.exception.BadRequestException
;
import
com.ctrip.framework.apollo.core.exception.ServiceException
;
import
com.ctrip.framework.apollo.portal.auth.UserInfoHolder
;
import
com.ctrip.framework.apollo.portal.repository.AppNamespaceRepository
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.List
;
import
java.util.Objects
;
@Service
public
class
AppNamespaceService
{
@Autowired
private
UserInfoHolder
userInfoHolder
;
@Autowired
private
AppNamespaceRepository
appNamespaceRepository
;
/**
* 公共的app ns,能被其它项目关联到的app ns
* @return
*/
public
List
<
AppNamespace
>
findPublicAppNamespaces
()
{
return
appNamespaceRepository
.
findByNameNotAndIsPublic
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
true
);
}
public
AppNamespace
findPublicAppNamespace
(
String
namespaceName
){
return
appNamespaceRepository
.
findByNameAndIsPublic
(
namespaceName
,
true
);
}
public
AppNamespace
findByAppIdAndName
(
String
appId
,
String
namespaceName
){
return
appNamespaceRepository
.
findByAppIdAndName
(
appId
,
namespaceName
);
}
@Transactional
public
void
createDefaultAppNamespace
(
String
appId
)
{
if
(!
isAppNamespaceNameUnique
(
appId
,
appId
))
{
throw
new
ServiceException
(
"appnamespace not unique"
);
}
AppNamespace
appNs
=
new
AppNamespace
();
appNs
.
setAppId
(
appId
);
appNs
.
setName
(
ConfigConsts
.
NAMESPACE_APPLICATION
);
appNs
.
setComment
(
"default app namespace"
);
String
userId
=
userInfoHolder
.
getUser
().
getUserId
();
appNs
.
setDataChangeCreatedBy
(
userId
);
appNs
.
setDataChangeLastModifiedBy
(
userId
);
appNamespaceRepository
.
save
(
appNs
);
}
public
boolean
isAppNamespaceNameUnique
(
String
appId
,
String
namespaceName
)
{
Objects
.
requireNonNull
(
appId
,
"AppId must not be null"
);
Objects
.
requireNonNull
(
namespaceName
,
"Namespace must not be null"
);
return
Objects
.
isNull
(
appNamespaceRepository
.
findByAppIdAndName
(
appId
,
namespaceName
));
}
@Transactional
public
AppNamespace
createAppNamespaceInLocal
(
AppNamespace
appNamespace
)
{
//not unique
if
(
appNamespaceRepository
.
findByName
(
appNamespace
.
getName
())
!=
null
){
throw
new
BadRequestException
(
appNamespace
.
getName
()
+
"已存在"
);
}
AppNamespace
managedAppNamespace
=
appNamespaceRepository
.
findByAppIdAndName
(
appNamespace
.
getAppId
(),
appNamespace
.
getName
());
//update
if
(
managedAppNamespace
!=
null
){
BeanUtils
.
copyEntityProperties
(
appNamespace
,
managedAppNamespace
);
return
appNamespaceRepository
.
save
(
managedAppNamespace
);
}
else
{
return
appNamespaceRepository
.
save
(
appNamespace
);
}
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java
View file @
5c6081a0
...
...
@@ -8,7 +8,6 @@ import java.util.List;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.ApplicationEventPublisher
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.web.client.HttpStatusCodeException
;
...
...
@@ -34,7 +33,7 @@ public class AppService {
@Autowired
private
ClusterService
clusterService
;
@Autowired
private
NamespaceService
n
amespaceService
;
private
AppNamespaceService
appN
amespaceService
;
@Autowired
private
RoleInitializationService
roleInitializationService
;
...
...
@@ -92,7 +91,7 @@ public class AppService {
throw
new
BadRequestException
(
String
.
format
(
"app id %s already exists!"
,
app
.
getAppId
()));
}
else
{
App
createdApp
=
appRepository
.
save
(
app
);
n
amespaceService
.
createDefaultAppNamespace
(
appId
);
appN
amespaceService
.
createDefaultAppNamespace
(
appId
);
//role
roleInitializationService
.
initAppRoles
(
createdApp
);
return
createdApp
;
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ConfigService.java
View file @
5c6081a0
...
...
@@ -4,12 +4,14 @@ package com.ctrip.framework.apollo.portal.service;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.web.client.HttpClientErrorException
;
import
com.ctrip.framework.apollo.common.utils.BeanUtils
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.core.dto.ItemChangeSets
;
import
com.ctrip.framework.apollo.core.dto.ItemDTO
;
...
...
@@ -43,8 +45,14 @@ public class ConfigService {
private
AdminServiceAPI
.
ItemAPI
itemAPI
;
@Autowired
private
AdminServiceAPI
.
ReleaseAPI
releaseAPI
;
@Autowired
@Qualifier
(
"fileTextResolver"
)
private
ConfigTextResolver
fileTextResolver
;
@Autowired
private
ConfigTextResolver
resolver
;
@Qualifier
(
"propertyResolver"
)
private
ConfigTextResolver
propertyResolver
;
/**
...
...
@@ -60,6 +68,7 @@ public class ConfigService {
long
namespaceId
=
model
.
getNamespaceId
();
String
configText
=
model
.
getConfigText
();
ConfigTextResolver
resolver
=
model
.
getFormat
()
==
ConfigFileFormat
.
Properties
?
propertyResolver
:
fileTextResolver
;
ItemChangeSets
changeSets
=
resolver
.
resolve
(
namespaceId
,
configText
,
itemAPI
.
findItems
(
appId
,
env
,
clusterName
,
namespaceName
));
if
(
changeSets
.
isEmpty
())
{
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceService.java
View file @
5c6081a0
...
...
@@ -5,41 +5,33 @@ import com.google.gson.Gson;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.common.utils.BeanUtils
;
import
com.ctrip.framework.apollo.common.utils.ExceptionUtils
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.dto.AppNamespaceDTO
;
import
com.ctrip.framework.apollo.core.dto.ItemDTO
;
import
com.ctrip.framework.apollo.core.dto.NamespaceDTO
;
import
com.ctrip.framework.apollo.core.dto.ReleaseDTO
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.core.exception.BadRequestException
;
import
com.ctrip.framework.apollo.core.exception.ServiceException
;
import
com.ctrip.framework.apollo.core.utils.StringUtils
;
import
com.ctrip.framework.apollo.portal.PortalSettings
;
import
com.ctrip.framework.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.framework.apollo.portal.auth.UserInfoHolder
;
import
com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO
;
import
com.ctrip.framework.apollo.portal.repository.AppNamespaceRepository
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.web.client.HttpClientErrorException
;
import
org.springframework.web.client.HttpStatusCodeException
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Objects
;
@Service
public
class
NamespaceService
{
private
Logger
logger
=
LoggerFactory
.
getLogger
(
NamespaceService
.
class
);
private
Gson
gson
=
new
Gson
();
@Autowired
private
UserInfoHolder
userInfoHolder
;
...
...
@@ -49,19 +41,13 @@ public class NamespaceService {
private
AdminServiceAPI
.
ReleaseAPI
releaseAPI
;
@Autowired
private
AdminServiceAPI
.
NamespaceAPI
namespaceAPI
;
@Autowired
private
PortalSettings
portalSettings
;
@Autowired
private
AppNamespaceRepository
appNamespaceRepository
;
@Autowired
private
RoleInitializationService
roleInitializationService
;
private
Gson
gson
=
new
Gson
()
;
@Autowired
private
AppNamespaceService
appNamespaceService
;
public
List
<
AppNamespace
>
findPublicAppNamespaces
()
{
return
appNamespaceRepository
.
findByNameNot
(
ConfigConsts
.
NAMESPACE_APPLICATION
);
}
public
NamespaceDTO
createNamespace
(
Env
env
,
NamespaceDTO
namespace
)
{
if
(
StringUtils
.
isEmpty
(
namespace
.
getDataChangeCreatedBy
()))
{
...
...
@@ -74,48 +60,11 @@ public class NamespaceService {
return
createdNamespace
;
}
@Transactional
public
void
createDefaultAppNamespace
(
String
appId
)
{
if
(!
isAppNamespaceNameUnique
(
appId
,
appId
))
{
throw
new
ServiceException
(
"appnamespace not unique"
);
}
AppNamespace
appNs
=
new
AppNamespace
();
appNs
.
setAppId
(
appId
);
appNs
.
setName
(
ConfigConsts
.
NAMESPACE_APPLICATION
);
appNs
.
setComment
(
"default app namespace"
);
String
userId
=
userInfoHolder
.
getUser
().
getUserId
();
appNs
.
setDataChangeCreatedBy
(
userId
);
appNs
.
setDataChangeLastModifiedBy
(
userId
);
appNamespaceRepository
.
save
(
appNs
);
}
public
boolean
isAppNamespaceNameUnique
(
String
appId
,
String
namespaceName
)
{
Objects
.
requireNonNull
(
appId
,
"AppId must not be null"
);
Objects
.
requireNonNull
(
namespaceName
,
"Namespace must not be null"
);
return
Objects
.
isNull
(
appNamespaceRepository
.
findByAppIdAndName
(
appId
,
namespaceName
));
}
@Transactional
public
AppNamespace
createAppNamespaceInLocal
(
AppNamespace
appNamespace
)
{
//not unique
if
(
appNamespaceRepository
.
findByName
(
appNamespace
.
getName
())
!=
null
){
throw
new
BadRequestException
(
appNamespace
.
getName
()
+
"已存在"
);
}
AppNamespace
managedAppNamespace
=
appNamespaceRepository
.
findByAppIdAndName
(
appNamespace
.
getAppId
(),
appNamespace
.
getName
());
//update
if
(
managedAppNamespace
!=
null
){
BeanUtils
.
copyEntityProperties
(
appNamespace
,
managedAppNamespace
);
return
appNamespaceRepository
.
save
(
managedAppNamespace
);
}
else
{
return
appNamespaceRepository
.
save
(
appNamespace
);
}
}
/**
* load cluster all namespace info with items
*/
public
List
<
NamespaceVO
>
findNam
p
spaces
(
String
appId
,
Env
env
,
String
clusterName
)
{
public
List
<
NamespaceVO
>
findNam
e
spaces
(
String
appId
,
Env
env
,
String
clusterName
)
{
List
<
NamespaceDTO
>
namespaces
=
namespaceAPI
.
findNamespaceByCluster
(
appId
,
env
,
clusterName
);
if
(
namespaces
==
null
||
namespaces
.
size
()
==
0
)
{
...
...
@@ -144,6 +93,15 @@ public class NamespaceService {
NamespaceVO
namespaceVO
=
new
NamespaceVO
();
namespaceVO
.
setNamespace
(
namespace
);
//先从当前appId下面找,包含私有的和公共的
AppNamespace
appNamespace
=
appNamespaceService
.
findByAppIdAndName
(
appId
,
namespace
.
getNamespaceName
());
//再从公共的app namespace里面找
if
(
appNamespace
==
null
)
{
appNamespace
=
appNamespaceService
.
findPublicAppNamespace
(
namespace
.
getNamespaceName
());
}
namespaceVO
.
setFormat
(
appNamespace
.
getFormat
());
List
<
NamespaceVO
.
ItemVO
>
itemVos
=
new
LinkedList
<>();
namespaceVO
.
setItems
(
itemVos
);
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/RolePermissionService.java
View file @
5c6081a0
...
...
@@ -199,7 +199,7 @@ public class RolePermissionService implements InitializingBean {
return
false
;
}
p
rivate
boolean
isSuperAdmin
(
String
userId
)
{
p
ublic
boolean
isSuperAdmin
(
String
userId
)
{
return
superAdminUsers
.
contains
(
userId
);
}
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/txtresolver/FileTextResolver.java
0 → 100644
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
service
.
txtresolver
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.dto.ItemChangeSets
;
import
com.ctrip.framework.apollo.core.dto.ItemDTO
;
import
com.ctrip.framework.apollo.core.utils.StringUtils
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.CollectionUtils
;
import
java.util.List
;
@Component
(
"fileTextResolver"
)
public
class
FileTextResolver
implements
ConfigTextResolver
{
@Override
public
ItemChangeSets
resolve
(
long
namespaceId
,
String
configText
,
List
<
ItemDTO
>
baseItems
)
{
ItemChangeSets
changeSets
=
new
ItemChangeSets
();
if
(
StringUtils
.
isEmpty
(
configText
))
{
return
changeSets
;
}
if
(
CollectionUtils
.
isEmpty
(
baseItems
))
{
changeSets
.
addCreateItem
(
createItem
(
namespaceId
,
configText
));
}
else
{
ItemDTO
beforeItem
=
baseItems
.
get
(
0
);
if
(!
configText
.
equals
(
beforeItem
.
getValue
()))
{
//update
changeSets
.
addUpdateItem
(
createItem
(
namespaceId
,
configText
));
}
}
return
changeSets
;
}
private
ItemDTO
createItem
(
long
namespaceId
,
String
value
)
{
ItemDTO
item
=
new
ItemDTO
();
item
.
setNamespaceId
(
namespaceId
);
item
.
setValue
(
value
);
item
.
setKey
(
ConfigConsts
.
FILE_NAMESPACE_KEY_NAME
);
return
item
;
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/txtresolver/PropertyResolver.java
View file @
5c6081a0
...
...
@@ -18,7 +18,7 @@ import java.util.Set;
* update comment and blank item implement by create new item and delete old item.
* update normal key/value item implement by update.
*/
@Component
@Component
(
"propertyResolver"
)
public
class
PropertyResolver
implements
ConfigTextResolver
{
private
static
final
String
KV_SEPARATOR
=
"="
;
...
...
apollo-portal/src/main/resources/static/app.html
View file @
5c6081a0
...
...
@@ -88,7 +88,7 @@
<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/services/OrganizationService.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/directive.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/directive
/directive
.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/controller/AppController.js"
></script>
</body>
...
...
apollo-portal/src/main/resources/static/app/role.html
View file @
5c6081a0
...
...
@@ -24,8 +24,8 @@
</h4>
</div>
<div
class=
"col-md-5 text-right"
>
<a
type=
"button"
class=
"btn btn-
success
"
data-dismiss=
"modal"
href=
"/config.html?#appid={{pageContext.appId}}"
>
返回
<a
type=
"button"
class=
"btn btn-
info
"
data-dismiss=
"modal"
href=
"/config.html?#appid={{pageContext.appId}}"
>
返回
到项目首页
</a>
</div>
</div>
...
...
@@ -101,7 +101,7 @@
<script
type=
"application/javascript"
src=
"../scripts/AppUtils.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/PageCommon.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/directive.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/directive
/directive
.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/controller/role/AppRoleController.js"
></script>
</body>
...
...
apollo-portal/src/main/resources/static/cluster.html
View file @
5c6081a0
...
...
@@ -25,7 +25,7 @@
<h4>
创建集群
</h4>
</div>
<div
class=
"col-md-6 text-right"
>
<a
type=
"button"
class=
"btn btn-
primary"
href=
"/config.html?#/appid={{appId}}"
>
返回
<a
type=
"button"
class=
"btn btn-
info"
href=
"/config.html?#/appid={{appId}}"
>
返回到项目首页
</a>
</div>
</div>
...
...
@@ -106,7 +106,7 @@
<script
type=
"application/javascript"
src=
"scripts/services/UserService.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/services/ClusterService.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/AppUtils.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/directive.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/directive
/directive
.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/controller/ClusterController.js"
></script>
</body>
...
...
apollo-portal/src/main/resources/static/config.html
View file @
5c6081a0
This diff is collapsed.
Click to expand it.
apollo-portal/src/main/resources/static/config/sync.html
View file @
5c6081a0
...
...
@@ -34,8 +34,8 @@
<button
type=
"button"
class=
"btn btn-success"
ng-show=
"syncItemStep == 2 && hasDiff"
ng-click=
"syncItems()"
>
同步
</button>
<button
type=
"button"
class=
"btn btn-
success
"
data-dismiss=
"modal"
ng-show=
"syncItemStep == 3"
ng-click=
"backToAppHomePage()"
>
返回
<button
type=
"button"
class=
"btn btn-
info
"
data-dismiss=
"modal"
ng-show=
"syncItemStep == 3"
ng-click=
"backToAppHomePage()"
>
返回
到项目首页
</button>
</div>
</div>
...
...
@@ -212,6 +212,6 @@
<script
type=
"application/javascript"
src=
"../scripts/controller/config/SyncConfigController.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/PageCommon.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/directive.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/directive
/directive
.js"
></script>
</body>
</html>
apollo-portal/src/main/resources/static/img/cluster.png
0 → 100644
View file @
5c6081a0
2.12 KB
apollo-portal/src/main/resources/static/namespace.html
View file @
5c6081a0
...
...
@@ -24,7 +24,7 @@
<div
class=
"row"
>
<div
class=
"col-md-6"
>
新建Namespace
</div>
<div
class=
"col-md-6 text-right"
>
<button
type=
"button"
class=
"btn btn-
success"
ng-show=
"step == 2"
ng-click=
"back()"
>
返回
<button
type=
"button"
class=
"btn btn-
info"
ng-show=
"step == 2"
ng-click=
"back()"
>
返回到项目首页
</button>
</div>
</div>
...
...
@@ -69,8 +69,28 @@
ng-required=
"type == 'create'"
>
</div>
</div>
<div
class=
"col-sm-2"
ng-if=
"hasRootPermission"
>
<select
class=
"form-control"
ng-model=
"appNamespace.format"
>
<option
value=
"properties"
>
properties
</option>
<option
value=
"xml"
>
xml
</option>
</select>
</div>
<span
ng-bind=
"concatNamespace()"
style=
"line-height: 34px;"
></span>
</div>
<div
class=
"form-group"
ng-show=
"type == 'create' && hasRootPermission"
>
<label
class=
"col-sm-3 control-label"
>
<apollorequiredfiled></apollorequiredfiled>
类型
</label>
<div
class=
"col-sm-4"
>
<label
class=
"radio-inline"
>
<input
type=
"radio"
name=
"namespaceType"
value=
"true"
ng-value=
"true"
ng-model=
"appNamespace.isPublic"
>
public
</label>
<label
class=
"radio-inline"
>
<input
type=
"radio"
name=
"namespaceType"
value=
"false"
ng-value=
"false"
ng-model=
"appNamespace.isPublic"
>
private
</label>
</div>
</div>
<div
class=
"form-group"
ng-show=
"type == 'create'"
>
<label
class=
"col-sm-3 control-label"
>
备注
</label>
<div
class=
"col-sm-7"
>
...
...
@@ -128,10 +148,11 @@
<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/NamespaceService.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/services/PermissionService.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/AppUtils.js"
></script>
<!--directive-->
<script
type=
"application/javascript"
src=
"scripts/directive.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/directive
/directive
.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/controller/NamespaceController.js"
></script>
...
...
apollo-portal/src/main/resources/static/namespace/role.html
View file @
5c6081a0
...
...
@@ -24,8 +24,8 @@
</h4>
</div>
<div
class=
"col-md-5 text-right"
>
<a
type=
"button"
class=
"btn btn-
success
"
data-dismiss=
"modal"
href=
"/config.html?#appid={{pageContext.appId}}"
>
返回
<a
type=
"button"
class=
"btn btn-
info
"
data-dismiss=
"modal"
href=
"/config.html?#appid={{pageContext.appId}}"
>
返回
到项目首页
</a>
</div>
</div>
...
...
@@ -131,7 +131,7 @@
<script
type=
"application/javascript"
src=
"../scripts/AppUtils.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/PageCommon.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/directive.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/directive
/directive
.js"
></script>
<script
type=
"application/javascript"
src=
"../scripts/controller/role/NamespaceRoleController.js"
></script>
</body>
...
...
apollo-portal/src/main/resources/static/scripts/controller/NamespaceController.js
View file @
5c6081a0
namespace_module
.
controller
(
"
LinkNamespaceController
"
,
[
'
$scope
'
,
'
$location
'
,
'
$window
'
,
'
toastr
'
,
'
AppService
'
,
'
AppUtil
'
,
'
NamespaceService
'
,
function
(
$scope
,
$location
,
$window
,
toastr
,
AppService
,
AppUtil
,
NamespaceService
)
{
'
PermissionService
'
,
function
(
$scope
,
$location
,
$window
,
toastr
,
AppService
,
AppUtil
,
NamespaceService
,
PermissionService
)
{
var
params
=
AppUtil
.
parseParams
(
$location
.
$$url
);
$scope
.
appId
=
params
.
appid
;
...
...
@@ -8,6 +10,10 @@ namespace_module.controller("LinkNamespaceController",
$scope
.
step
=
1
;
PermissionService
.
has_root_permission
().
then
(
function
(
result
)
{
$scope
.
hasRootPermission
=
result
.
hasPermission
;
});
NamespaceService
.
find_public_namespaces
().
then
(
function
(
result
)
{
var
publicNamespaces
=
[];
result
.
forEach
(
function
(
item
)
{
...
...
@@ -35,7 +41,13 @@ namespace_module.controller("LinkNamespaceController",
$scope
.
appNamespace
=
{
appId
:
$scope
.
appId
,
name
:
''
,
comment
:
''
comment
:
''
,
isPublic
:
false
,
format
:
'
xml
'
};
$scope
.
switchNSType
=
function
(
type
)
{
$scope
.
appNamespace
.
isPublic
=
type
;
};
$scope
.
concatNamespace
=
function
()
{
...
...
@@ -95,7 +107,13 @@ namespace_module.controller("LinkNamespaceController",
function
(
result
)
{
$scope
.
step
=
2
;
setInterval
(
function
()
{
$window
.
location
.
reload
();
if
(
$scope
.
appNamespace
.
isPublic
)
{
$window
.
location
.
reload
();
}
else
{
//private的直接link并且跳转到授权页面
$window
.
location
.
href
=
"
/namespace/role.html?#/appid=
"
+
$scope
.
appId
+
"
&namespaceName=
"
+
$scope
.
appNamespace
.
name
;
}
},
1000
);
},
function
(
result
)
{
toastr
.
error
(
AppUtil
.
errorMsg
(
result
),
"
创建失败
"
);
...
...
apollo-portal/src/main/resources/static/scripts/controller/config/ConfigBaseInfoController.js
View file @
5c6081a0
...
...
@@ -34,6 +34,7 @@ application_module.controller("ConfigBaseInfoController",
var
node
=
{};
//first nav
node
.
text
=
env
.
env
;
// node.icon = 'glyphicon glyphicon-console';
var
clusterNodes
=
[];
//如果env下面只有一个default集群则不显示集群列表
...
...
@@ -57,8 +58,10 @@ application_module.controller("ConfigBaseInfoController",
}
clusterNode
.
text
=
cluster
.
name
;
// clusterNode.icon = 'glyphicon glyphicon-object-align-vertical';
parentNode
.
push
(
node
.
text
);
clusterNode
.
tags
=
parentNode
;
clusterNode
.
tags
=
[
'
集群
'
];
clusterNode
.
parentNode
=
parentNode
;
clusterNodes
.
push
(
clusterNode
);
});
}
...
...
@@ -73,13 +76,14 @@ application_module.controller("ConfigBaseInfoController",
levels
:
99
,
expandIcon
:
''
,
collapseIcon
:
''
,
showTags
:
true
,
onNodeSelected
:
function
(
event
,
data
)
{
if
(
!
data
.
tags
)
{
//first nav node
if
(
!
data
.
parentNode
)
{
//first nav node
$rootScope
.
pageContext
.
env
=
data
.
text
;
$rootScope
.
pageContext
.
clusterName
=
'
default
'
;
}
else
{
//second cluster node
$rootScope
.
pageContext
.
env
=
data
.
tags
[
0
];
$rootScope
.
pageContext
.
env
=
data
.
parentNode
[
0
];
$rootScope
.
pageContext
.
clusterName
=
data
.
text
;
}
...
...
apollo-portal/src/main/resources/static/scripts/controller/config/ConfigNamespaceController.js
View file @
5c6081a0
This diff is collapsed.
Click to expand it.
apollo-portal/src/main/resources/static/scripts/directive.js
→
apollo-portal/src/main/resources/static/scripts/directive
/directive
.js
View file @
5c6081a0
...
...
@@ -2,7 +2,7 @@
directive_module
.
directive
(
'
apollonav
'
,
function
(
$compile
,
$window
,
toastr
,
AppUtil
,
AppService
,
EnvService
,
UserService
)
{
return
{
restrict
:
'
E
'
,
templateUrl
:
'
../views/common/nav.html
'
,
templateUrl
:
'
../
../
views/common/nav.html
'
,
transclude
:
true
,
replace
:
true
,
link
:
function
(
scope
,
element
,
attrs
)
{
...
...
@@ -120,7 +120,7 @@ directive_module.directive('apollonav', function ($compile, $window, toastr, App
directive_module
.
directive
(
'
apolloclusterselector
'
,
function
(
$compile
,
$window
,
AppService
,
AppUtil
,
toastr
)
{
return
{
restrict
:
'
E
'
,
templateUrl
:
'
../views/component/env-selector.html
'
,
templateUrl
:
'
../
../
views/component/env-selector.html
'
,
transclude
:
true
,
replace
:
true
,
scope
:
{
...
...
@@ -218,7 +218,7 @@ directive_module.directive('apollorequiredfiled', function ($compile, $window) {
directive_module
.
directive
(
'
apolloconfirmdialog
'
,
function
(
$compile
,
$window
)
{
return
{
restrict
:
'
E
'
,
templateUrl
:
'
../views/component/confirm-dialog.html
'
,
templateUrl
:
'
../
../
views/component/confirm-dialog.html
'
,
transclude
:
true
,
replace
:
true
,
scope
:
{
...
...
@@ -244,7 +244,7 @@ directive_module.directive('apolloconfirmdialog', function ($compile, $window) {
directive_module
.
directive
(
'
apolloentrance
'
,
function
(
$compile
,
$window
)
{
return
{
restrict
:
'
E
'
,
templateUrl
:
'
../views/component/entrance.html
'
,
templateUrl
:
'
../
../
views/component/entrance.html
'
,
transclude
:
true
,
replace
:
true
,
scope
:
{
...
...
@@ -262,7 +262,7 @@ directive_module.directive('apolloentrance', function ($compile, $window) {
directive_module
.
directive
(
'
apollouserselector
'
,
function
(
$compile
,
$window
)
{
return
{
restrict
:
'
E
'
,
templateUrl
:
'
../views/component/user-selector.html
'
,
templateUrl
:
'
../
../
views/component/user-selector.html
'
,
transclude
:
true
,
replace
:
true
,
scope
:
{
...
...
apollo-portal/src/main/resources/static/scripts/directive/namespace-panel-directive.js
0 → 100644
View file @
5c6081a0
This diff is collapsed.
Click to expand it.
apollo-portal/src/main/resources/static/scripts/services/ConfigService.js
View file @
5c6081a0
...
...
@@ -72,7 +72,7 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
return
d
.
promise
;
},
modify_items
:
function
(
appId
,
env
,
clusterName
,
namespaceName
,
configText
,
namespaceId
,
comment
)
{
modify_items
:
function
(
appId
,
env
,
clusterName
,
namespaceName
,
model
)
{
var
d
=
$q
.
defer
();
config_source
.
modify_items
({
appId
:
appId
,
...
...
@@ -80,11 +80,7 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
clusterName
:
clusterName
,
namespaceName
:
namespaceName
},
{
configText
:
configText
,
namespaceId
:
namespaceId
,
comment
:
comment
},
function
(
result
)
{
model
,
function
(
result
)
{
d
.
resolve
(
result
);
},
function
(
result
)
{
...
...
apollo-portal/src/main/resources/static/scripts/services/NamespaceLockService.js
View file @
5c6081a0
...
...
@@ -5,6 +5,7 @@ appService.service('NamespaceLockService', ['$resource', '$q', function ($resour
url
:
'
apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/lock
'
}
});
return
{
get_namespace_lock
:
function
(
appId
,
env
,
clusterName
,
namespaceName
)
{
var
d
=
$q
.
defer
();
...
...
apollo-portal/src/main/resources/static/scripts/services/PermissionService.js
View file @
5c6081a0
...
...
@@ -8,6 +8,10 @@ appService.service('PermissionService', ['$resource', '$q', function ($resource,
method
:
'
GET
'
,
url
:
'
/apps/:appId/namespaces/:namespaceName/permissions/:permissionType
'
},
has_root_permission
:{
method
:
'
GET
'
,
url
:
'
/permissions/root
'
},
get_namespace_role_users
:
{
method
:
'
GET
'
,
url
:
'
/apps/:appId/namespaces/:namespaceName/role_users
'
...
...
@@ -110,6 +114,17 @@ appService.service('PermissionService', ['$resource', '$q', function ($resource,
has_release_namespace_permission
:
function
(
appId
,
namespaceName
)
{
return
hasNamespacePermission
(
appId
,
namespaceName
,
'
ReleaseNamespace
'
);
},
has_root_permission
:
function
()
{
var
d
=
$q
.
defer
();
permission_resource
.
has_root_permission
({
},
function
(
result
)
{
d
.
resolve
(
result
);
},
function
(
result
)
{
d
.
reject
(
result
);
});
return
d
.
promise
;
},
assign_modify_namespace_role
:
function
(
appId
,
namespaceName
,
user
)
{
return
assignNamespaceRoleToUser
(
appId
,
namespaceName
,
'
ModifyNamespace
'
,
user
);
},
...
...
apollo-portal/src/main/resources/static/server_config.html
View file @
5c6081a0
...
...
@@ -78,7 +78,7 @@
<script
src=
"vendor/bootstrap/js/bootstrap.min.js"
type=
"text/javascript"
></script>
<script
type=
"application/javascript"
src=
"scripts/app.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/directive.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/directive
/directive
.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/AppUtils.js"
></script>
<script
type=
"application/javascript"
src=
"scripts/services/AppService.js"
></script>
...
...
apollo-portal/src/main/resources/static/views/common/nav.html
View file @
5c6081a0
...
...
@@ -10,7 +10,7 @@
<div
class=
"collapse navbar-collapse"
id=
"bs-example-navbar-collapse-1"
>
<ul
class=
"nav navbar-nav navbar-right"
>
<li><a
href=
"http://conf.ctripcorp.com/
pages/viewpage.action?pageId=98435462
"
target=
"_blank"
>
<li><a
href=
"http://conf.ctripcorp.com/
display/FRAM/Apollo
"
target=
"_blank"
>
Help
</span>
</a></li>
<li
class=
"dropdown"
>
...
...
apollo-portal/src/main/resources/static/views/component/namespace-panel.html
0 → 100644
View file @
5c6081a0
This diff is collapsed.
Click to expand it.
apollo-portal/src/test/java/com/ctrip/framework/apollo/portal/ConfigServiceTest.java
View file @
5c6081a0
...
...
@@ -4,6 +4,7 @@ import com.ctrip.framework.apollo.core.ConfigConsts;
import
com.ctrip.framework.apollo.core.dto.ItemChangeSets
;
import
com.ctrip.framework.apollo.core.dto.ItemDTO
;
import
com.ctrip.framework.apollo.core.dto.NamespaceDTO
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.framework.apollo.portal.auth.UserInfoHolder
;
...
...
@@ -21,6 +22,7 @@ import org.junit.runner.RunWith;
import
org.mockito.InjectMocks
;
import
org.mockito.Mock
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
java.util.Arrays
;
import
java.util.List
;
...
...
@@ -47,6 +49,7 @@ public class ConfigServiceTest {
@Before
public
void
setup
()
{
ReflectionTestUtils
.
setField
(
configService
,
"propertyResolver"
,
resolver
);
}
@Test
...
...
@@ -61,7 +64,7 @@ public class ConfigServiceTest {
model
.
setClusterName
(
clusterName
);
model
.
setAppId
(
appId
);
model
.
setConfigText
(
"a=b\nb=c\nc=d\nd=e"
);
model
.
setFormat
(
ConfigFileFormat
.
Properties
.
getValue
());
List
<
ItemDTO
>
itemDTOs
=
mockBaseItemHas3Key
();
ItemChangeSets
changeSets
=
new
ItemChangeSets
();
changeSets
.
addCreateItem
(
new
ItemDTO
(
"d"
,
"c"
,
""
,
4
));
...
...
apollo-portal/src/test/java/com/ctrip/framework/apollo/portal/NamespaceServiceTest.java
View file @
5c6081a0
package
com
.
ctrip
.
framework
.
apollo
.
portal
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.core.dto.ItemDTO
;
import
com.ctrip.framework.apollo.core.dto.NamespaceDTO
;
import
com.ctrip.framework.apollo.core.dto.ReleaseDTO
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO
;
import
com.ctrip.framework.apollo.portal.service.AppNamespaceService
;
import
com.ctrip.framework.apollo.portal.service.NamespaceService
;
import
com.ctrip.framework.apollo.portal.service.txtresolver.PropertyResolver
;
...
...
@@ -20,6 +23,7 @@ import java.util.Arrays;
import
java.util.List
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
@RunWith
(
MockitoJUnitRunner
.
class
)
...
...
@@ -33,6 +37,8 @@ public class NamespaceServiceTest {
private
AdminServiceAPI
.
ItemAPI
itemAPI
;
@Mock
private
PropertyResolver
resolver
;
@Mock
private
AppNamespaceService
appNamespaceService
;
@InjectMocks
private
NamespaceService
namespaceService
;
...
...
@@ -47,18 +53,21 @@ public class NamespaceServiceTest {
String
clusterName
=
"default"
;
String
namespaceName
=
"application"
;
AppNamespace
applicationAppNamespace
=
mock
(
AppNamespace
.
class
);
AppNamespace
hermesAppNamespace
=
mock
(
AppNamespace
.
class
);
NamespaceDTO
application
=
new
NamespaceDTO
();
application
.
setId
(
1
);
application
.
setClusterName
(
clusterName
);
application
.
setAppId
(
appId
);
application
.
setNamespaceName
(
namespaceName
);
NamespaceDTO
herm
a
s
=
new
NamespaceDTO
();
herm
a
s
.
setId
(
2
);
herm
a
s
.
setClusterName
(
"default"
);
herm
a
s
.
setAppId
(
appId
);
herm
as
.
setNamespaceName
(
"herma
s"
);
List
<
NamespaceDTO
>
namespaces
=
Arrays
.
asList
(
application
,
herm
a
s
);
NamespaceDTO
herm
e
s
=
new
NamespaceDTO
();
herm
e
s
.
setId
(
2
);
herm
e
s
.
setClusterName
(
"default"
);
herm
e
s
.
setAppId
(
appId
);
herm
es
.
setNamespaceName
(
"herme
s"
);
List
<
NamespaceDTO
>
namespaces
=
Arrays
.
asList
(
application
,
herm
e
s
);
ReleaseDTO
someRelease
=
new
ReleaseDTO
();
someRelease
.
setConfigurations
(
"{\"a\":\"123\",\"b\":\"123\"}"
);
...
...
@@ -69,12 +78,17 @@ public class NamespaceServiceTest {
ItemDTO
i4
=
new
ItemDTO
(
"c"
,
"1"
,
""
,
4
);
List
<
ItemDTO
>
someItems
=
Arrays
.
asList
(
i1
,
i2
,
i3
,
i4
);
when
(
applicationAppNamespace
.
getFormat
()).
thenReturn
(
ConfigFileFormat
.
Properties
.
getValue
());
when
(
hermesAppNamespace
.
getFormat
()).
thenReturn
(
ConfigFileFormat
.
XML
.
getValue
());
when
(
appNamespaceService
.
findByAppIdAndName
(
appId
,
namespaceName
))
.
thenReturn
(
applicationAppNamespace
);
when
(
appNamespaceService
.
findPublicAppNamespace
(
"hermes"
)).
thenReturn
(
hermesAppNamespace
);
when
(
namespaceAPI
.
findNamespaceByCluster
(
appId
,
Env
.
DEV
,
clusterName
)).
thenReturn
(
namespaces
);
when
(
releaseAPI
.
loadLatestRelease
(
appId
,
Env
.
DEV
,
clusterName
,
namespaceName
)).
thenReturn
(
someRelease
);
when
(
releaseAPI
.
loadLatestRelease
(
appId
,
Env
.
DEV
,
clusterName
,
"herm
a
s"
)).
thenReturn
(
someRelease
);
when
(
releaseAPI
.
loadLatestRelease
(
appId
,
Env
.
DEV
,
clusterName
,
"herm
e
s"
)).
thenReturn
(
someRelease
);
when
(
itemAPI
.
findItems
(
appId
,
Env
.
DEV
,
clusterName
,
namespaceName
)).
thenReturn
(
someItems
);
List
<
NamespaceVO
>
namespaceVOs
=
namespaceService
.
findNam
p
spaces
(
appId
,
Env
.
DEV
,
clusterName
);
List
<
NamespaceVO
>
namespaceVOs
=
namespaceService
.
findNam
e
spaces
(
appId
,
Env
.
DEV
,
clusterName
);
assertEquals
(
2
,
namespaceVOs
.
size
());
NamespaceVO
namespaceVO
=
namespaceVOs
.
get
(
0
);
assertEquals
(
4
,
namespaceVO
.
getItems
().
size
());
...
...
apollo-portal/src/test/java/com/ctrip/framework/apollo/portal/PropertyResolverTest.java
View file @
5c6081a0
...
...
@@ -9,6 +9,7 @@ import com.ctrip.framework.apollo.portal.service.txtresolver.ConfigTextResolver;
import
org.junit.Assert
;
import
org.junit.Test
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
java.util.Arrays
;
import
java.util.Collections
;
...
...
@@ -17,6 +18,7 @@ import java.util.List;
public
class
PropertyResolverTest
extends
AbstractPortalTest
{
@Autowired
@Qualifier
(
"propertyResolver"
)
private
ConfigTextResolver
resolver
;
@Test
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment