Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
zhangjian1949
apollo
提交
f435f27d
apollo
项目概览
zhangjian1949
/
apollo
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
apollo
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f435f27d
编写于
7月 13, 2016
作者:
J
Jason Song
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add config file controller to support get config as plain properties file
上级
f5bc9f83
变更
24
隐藏空白更改
内联
并排
Showing
24 changed file
with
691 addition
and
111 deletion
+691
-111
apollo-adminservice/pom.xml
apollo-adminservice/pom.xml
+1
-1
apollo-assembly/pom.xml
apollo-assembly/pom.xml
+1
-1
apollo-biz/pom.xml
apollo-biz/pom.xml
+1
-1
apollo-buildtools/pom.xml
apollo-buildtools/pom.xml
+1
-1
apollo-client/pom.xml
apollo-client/pom.xml
+1
-1
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/PropertiesConfigFile.java
...trip/framework/apollo/internals/PropertiesConfigFile.java
+4
-27
apollo-common/pom.xml
apollo-common/pom.xml
+1
-1
apollo-configservice/pom.xml
apollo-configservice/pom.xml
+1
-1
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServiceAutoConfiguration.java
.../apollo/configservice/ConfigServiceAutoConfiguration.java
+5
-0
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/ConfigFileController.java
...apollo/configservice/controller/ConfigFileController.java
+187
-0
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/NotificationController.java
...ollo/configservice/controller/NotificationController.java
+9
-66
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/util/WatchKeysUtil.java
...ip/framework/apollo/configservice/util/WatchKeysUtil.java
+88
-0
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/AllTests.java
...va/com/ctrip/framework/apollo/configservice/AllTests.java
+4
-1
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/ConfigFileControllerTest.java
...lo/configservice/controller/ConfigFileControllerTest.java
+164
-0
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/NotificationControllerTest.java
.../configservice/controller/NotificationControllerTest.java
+5
-1
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/AbstractBaseIntegrationTest.java
...onfigservice/integration/AbstractBaseIntegrationTest.java
+39
-0
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/ConfigFileControllerIntegrationTest.java
...vice/integration/ConfigFileControllerIntegrationTest.java
+128
-0
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/NotificationControllerIntegrationTest.java
...ce/integration/NotificationControllerIntegrationTest.java
+2
-4
apollo-core/pom.xml
apollo-core/pom.xml
+1
-1
apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/PropertiesUtil.java
...com/ctrip/framework/apollo/core/utils/PropertiesUtil.java
+42
-0
apollo-demo/pom.xml
apollo-demo/pom.xml
+1
-1
apollo-demo/src/main/java/ApolloConfigFileDemo.java
apollo-demo/src/main/java/ApolloConfigFileDemo.java
+3
-1
apollo-portal/pom.xml
apollo-portal/pom.xml
+1
-1
pom.xml
pom.xml
+1
-1
未找到文件。
apollo-adminservice/pom.xml
浏览文件 @
f435f27d
...
...
@@ -4,7 +4,7 @@
<parent>
<groupId>
com.ctrip.framework.apollo
</groupId>
<artifactId>
apollo
</artifactId>
<version>
0.0.
5
</version>
<version>
0.0.
6-SNAPSHOT
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<modelVersion>
4.0.0
</modelVersion>
...
...
apollo-assembly/pom.xml
浏览文件 @
f435f27d
...
...
@@ -4,7 +4,7 @@
<parent>
<groupId>
com.ctrip.framework.apollo
</groupId>
<artifactId>
apollo
</artifactId>
<version>
0.0.
5
</version>
<version>
0.0.
6-SNAPSHOT
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<modelVersion>
4.0.0
</modelVersion>
...
...
apollo-biz/pom.xml
浏览文件 @
f435f27d
...
...
@@ -4,7 +4,7 @@
<parent>
<artifactId>
apollo
</artifactId>
<groupId>
com.ctrip.framework.apollo
</groupId>
<version>
0.0.
5
</version>
<version>
0.0.
6-SNAPSHOT
</version>
</parent>
<modelVersion>
4.0.0
</modelVersion>
<artifactId>
apollo-biz
</artifactId>
...
...
apollo-buildtools/pom.xml
浏览文件 @
f435f27d
...
...
@@ -4,7 +4,7 @@
<parent>
<groupId>
com.ctrip.framework.apollo
</groupId>
<artifactId>
apollo
</artifactId>
<version>
0.0.
5
</version>
<version>
0.0.
6-SNAPSHOT
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<modelVersion>
4.0.0
</modelVersion>
...
...
apollo-client/pom.xml
浏览文件 @
f435f27d
...
...
@@ -4,7 +4,7 @@
<parent>
<groupId>
com.ctrip.framework.apollo
</groupId>
<artifactId>
apollo
</artifactId>
<version>
0.0.
5
</version>
<version>
0.0.
6-SNAPSHOT
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<modelVersion>
4.0.0
</modelVersion>
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/PropertiesConfigFile.java
浏览文件 @
f435f27d
package
com.ctrip.framework.apollo.internals
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.core.utils.PropertiesUtil
;
import
com.ctrip.framework.apollo.exceptions.ApolloConfigException
;
import
com.ctrip.framework.apollo.util.ExceptionUtil
;
import
com.dianping.cat.Cat
;
...
...
@@ -8,8 +9,6 @@ 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
;
...
...
@@ -38,13 +37,10 @@ public class PropertiesConfigFile extends AbstractConfigFile {
if
(
m_configProperties
.
get
()
==
null
)
{
return
null
;
}
StringWriter
writer
=
new
StringWriter
();
try
{
m_configProperties
.
get
().
store
(
writer
,
null
);
StringBuffer
stringBuffer
=
writer
.
getBuffer
();
filterPropertiesComment
(
stringBuffer
);
return
stringBuffer
.
toString
();
}
catch
(
IOException
ex
)
{
return
PropertiesUtil
.
toString
(
m_configProperties
.
get
());
}
catch
(
Throwable
ex
)
{
ApolloConfigException
exception
=
new
ApolloConfigException
(
String
.
format
(
"Parse properties file content failed for namespace: %s, cause: %s"
,
...
...
@@ -54,25 +50,6 @@ public class PropertiesConfigFile extends AbstractConfigFile {
}
}
/**
* filter out the first comment line
* @param stringBuffer the string buffer
* @return true if filtered successfully, false otherwise
*/
boolean
filterPropertiesComment
(
StringBuffer
stringBuffer
)
{
//check whether has comment in the first line
if
(
stringBuffer
.
charAt
(
0
)
!=
'#'
)
{
return
false
;
}
int
commentLineIndex
=
stringBuffer
.
indexOf
(
"\n"
);
if
(
commentLineIndex
==
-
1
)
{
return
false
;
}
stringBuffer
.
delete
(
0
,
commentLineIndex
+
1
);
return
true
;
}
@Override
public
boolean
hasContent
()
{
return
m_configProperties
.
get
()
!=
null
&&
!
m_configProperties
.
get
().
isEmpty
();
...
...
apollo-common/pom.xml
浏览文件 @
f435f27d
...
...
@@ -4,7 +4,7 @@
<parent>
<groupId>
com.ctrip.framework.apollo
</groupId>
<artifactId>
apollo
</artifactId>
<version>
0.0.
5
</version>
<version>
0.0.
6-SNAPSHOT
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<modelVersion>
4.0.0
</modelVersion>
...
...
apollo-configservice/pom.xml
浏览文件 @
f435f27d
...
...
@@ -4,7 +4,7 @@
<parent>
<groupId>
com.ctrip.framework.apollo
</groupId>
<artifactId>
apollo
</artifactId>
<version>
0.0.
5
</version>
<version>
0.0.
6-SNAPSHOT
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<modelVersion>
4.0.0
</modelVersion>
...
...
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServiceAutoConfiguration.java
浏览文件 @
f435f27d
package
com.ctrip.framework.apollo.configservice
;
import
com.ctrip.framework.apollo.biz.message.ReleaseMessageScanner
;
import
com.ctrip.framework.apollo.configservice.controller.ConfigFileController
;
import
com.ctrip.framework.apollo.configservice.controller.NotificationController
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -14,10 +15,14 @@ import org.springframework.context.annotation.Configuration;
public
class
ConfigServiceAutoConfiguration
{
@Autowired
private
NotificationController
notificationController
;
@Autowired
private
ConfigFileController
configFileController
;
@Bean
public
ReleaseMessageScanner
releaseMessageScanner
()
{
ReleaseMessageScanner
releaseMessageScanner
=
new
ReleaseMessageScanner
();
//handle server cache first
releaseMessageScanner
.
addMessageListener
(
configFileController
);
releaseMessageScanner
.
addMessageListener
(
notificationController
);
return
releaseMessageScanner
;
}
...
...
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/ConfigFileController.java
0 → 100644
浏览文件 @
f435f27d
package
com.ctrip.framework.apollo.configservice.controller
;
import
com.google.common.base.Joiner
;
import
com.google.common.base.Strings
;
import
com.google.common.cache.Cache
;
import
com.google.common.cache.CacheBuilder
;
import
com.google.common.cache.RemovalListener
;
import
com.google.common.cache.RemovalNotification
;
import
com.google.common.cache.Weigher
;
import
com.google.common.collect.HashMultimap
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Multimap
;
import
com.google.common.collect.Multimaps
;
import
com.ctrip.framework.apollo.biz.entity.ReleaseMessage
;
import
com.ctrip.framework.apollo.biz.message.ReleaseMessageListener
;
import
com.ctrip.framework.apollo.biz.message.Topics
;
import
com.ctrip.framework.apollo.configservice.util.NamespaceUtil
;
import
com.ctrip.framework.apollo.configservice.util.WatchKeysUtil
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.dto.ApolloConfig
;
import
com.ctrip.framework.apollo.core.dto.ApolloConfigNotification
;
import
com.ctrip.framework.apollo.core.utils.PropertiesUtil
;
import
com.dianping.cat.Cat
;
import
org.hibernate.cache.spi.CacheKey
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.context.request.async.DeferredResult
;
import
java.io.IOException
;
import
java.io.StringWriter
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.Properties
;
import
java.util.Set
;
import
java.util.concurrent.TimeUnit
;
import
javax.servlet.http.HttpServletResponse
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RestController
@RequestMapping
(
"/configfiles"
)
public
class
ConfigFileController
implements
ReleaseMessageListener
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ConfigFileController
.
class
);
private
static
final
Joiner
STRING_JOINER
=
Joiner
.
on
(
ConfigConsts
.
CLUSTER_NAMESPACE_SEPARATOR
);
private
static
final
long
MAX_CACHE_SIZE
=
50
*
1024
*
1024
;
// 50MB
private
static
final
long
EXPIRE_AFTER_WRITE
=
10
;
private
final
HttpHeaders
responseHeaders
;
private
final
ResponseEntity
<
String
>
NOT_FOUND_RESPONSE
;
private
Cache
<
String
,
String
>
localCache
;
private
final
Multimap
<
String
,
String
>
watchedKeys2CacheKey
=
Multimaps
.
synchronizedSetMultimap
(
HashMultimap
.
create
());
private
final
Multimap
<
String
,
String
>
cacheKey2WatchedKeys
=
Multimaps
.
synchronizedSetMultimap
(
HashMultimap
.
create
());
@Autowired
private
ConfigController
configController
;
@Autowired
private
NamespaceUtil
namespaceUtil
;
@Autowired
private
WatchKeysUtil
watchKeysUtil
;
public
ConfigFileController
()
{
localCache
=
CacheBuilder
.
newBuilder
()
.
expireAfterWrite
(
EXPIRE_AFTER_WRITE
,
TimeUnit
.
MINUTES
)
.
weigher
(
new
Weigher
<
String
,
String
>()
{
@Override
public
int
weigh
(
String
key
,
String
value
)
{
return
value
==
null
?
0
:
value
.
length
();
}
})
.
maximumWeight
(
MAX_CACHE_SIZE
)
.
removalListener
(
new
RemovalListener
<
String
,
String
>()
{
@Override
public
void
onRemoval
(
RemovalNotification
<
String
,
String
>
notification
)
{
String
cacheKey
=
notification
.
getKey
();
logger
.
debug
(
"removing cache key: {}"
,
cacheKey
);
if
(!
cacheKey2WatchedKeys
.
containsKey
(
cacheKey
))
{
return
;
}
//create a new list to avoid ConcurrentModificationException
List
<
String
>
watchedKeys
=
new
ArrayList
<>(
cacheKey2WatchedKeys
.
get
(
cacheKey
));
for
(
String
watchedKey
:
watchedKeys
)
{
watchedKeys2CacheKey
.
remove
(
watchedKey
,
cacheKey
);
}
cacheKey2WatchedKeys
.
removeAll
(
cacheKey
);
logger
.
debug
(
"removed cache key: {}"
,
cacheKey
);
}
})
.
build
();
responseHeaders
=
new
HttpHeaders
();
responseHeaders
.
add
(
"Content-Type"
,
"text/plain;charset=UTF-8"
);
NOT_FOUND_RESPONSE
=
new
ResponseEntity
<>(
HttpStatus
.
NOT_FOUND
);
}
@RequestMapping
(
value
=
"/{appId}/{clusterName}/{namespace:.+}"
,
method
=
RequestMethod
.
GET
)
public
ResponseEntity
<
String
>
queryConfigAsFile
(
@PathVariable
String
appId
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespace
,
@RequestParam
(
value
=
"dataCenter"
,
required
=
false
)
String
dataCenter
,
@RequestParam
(
value
=
"ip"
,
required
=
false
)
String
clientIp
,
HttpServletResponse
response
)
throws
IOException
{
//strip out .properties suffix
namespace
=
namespaceUtil
.
filterNamespaceName
(
namespace
);
//TODO add clientIp as key parts?
String
cacheKey
=
assembleCacheKey
(
appId
,
clusterName
,
namespace
,
dataCenter
);
String
result
=
localCache
.
getIfPresent
(
cacheKey
);
if
(
Strings
.
isNullOrEmpty
(
result
))
{
ApolloConfig
apolloConfig
=
configController
.
queryConfig
(
appId
,
clusterName
,
namespace
,
dataCenter
,
"-1"
,
clientIp
,
response
);
if
(
apolloConfig
==
null
||
apolloConfig
.
getConfigurations
()
==
null
)
{
return
NOT_FOUND_RESPONSE
;
}
Properties
properties
=
new
Properties
();
properties
.
putAll
(
apolloConfig
.
getConfigurations
());
result
=
PropertiesUtil
.
toString
(
properties
);
localCache
.
put
(
cacheKey
,
result
);
logger
.
debug
(
"adding cache for key: {}"
,
cacheKey
);
Set
<
String
>
watchedKeys
=
watchKeysUtil
.
assembleAllWatchKeys
(
appId
,
clusterName
,
namespace
,
dataCenter
);
for
(
String
watchedKey
:
watchedKeys
)
{
watchedKeys2CacheKey
.
put
(
watchedKey
,
cacheKey
);
}
cacheKey2WatchedKeys
.
putAll
(
cacheKey
,
watchedKeys
);
logger
.
debug
(
"added cache for key: {}"
,
cacheKey
);
}
return
new
ResponseEntity
<>(
result
,
responseHeaders
,
HttpStatus
.
OK
);
}
String
assembleCacheKey
(
String
appId
,
String
clusterName
,
String
namespace
,
String
dataCenter
)
{
List
<
String
>
keyParts
=
Lists
.
newArrayList
(
appId
,
clusterName
,
namespace
);
if
(!
Strings
.
isNullOrEmpty
(
dataCenter
))
{
keyParts
.
add
(
dataCenter
);
}
return
STRING_JOINER
.
join
(
keyParts
);
}
@Override
public
void
handleMessage
(
ReleaseMessage
message
,
String
channel
)
{
logger
.
info
(
"message received - channel: {}, message: {}"
,
channel
,
message
);
String
content
=
message
.
getMessage
();
if
(!
Topics
.
APOLLO_RELEASE_TOPIC
.
equals
(
channel
)
||
Strings
.
isNullOrEmpty
(
content
))
{
return
;
}
if
(!
watchedKeys2CacheKey
.
containsKey
(
content
))
{
return
;
}
//create a new list to avoid ConcurrentModificationException
List
<
String
>
cacheKeys
=
new
ArrayList
<>(
watchedKeys2CacheKey
.
get
(
content
));
for
(
String
cacheKey
:
cacheKeys
)
{
logger
.
debug
(
"invalidate cache key: {}"
,
cacheKey
);
localCache
.
invalidate
(
cacheKey
);
}
}
}
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/controller/NotificationController.java
浏览文件 @
f435f27d
package
com.ctrip.framework.apollo.configservice.controller
;
import
com.google.common.base.Joiner
;
import
com.google.common.base.Splitter
;
import
com.google.common.base.Strings
;
import
com.google.common.collect.HashMultimap
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Multimap
;
import
com.google.common.collect.Multimaps
;
import
com.google.common.collect.Sets
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.biz.entity.ReleaseMessage
;
import
com.ctrip.framework.apollo.biz.message.ReleaseMessageListener
;
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.configservice.util.WatchKeysUtil
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.dto.ApolloConfigNotification
;
import
com.dianping.cat.Cat
;
...
...
@@ -33,7 +30,6 @@ import org.springframework.web.bind.annotation.RestController;
import
org.springframework.web.context.request.async.DeferredResult
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.Set
;
/**
...
...
@@ -48,12 +44,11 @@ public class NotificationController implements ReleaseMessageListener {
deferredResults
=
Multimaps
.
synchronizedSetMultimap
(
HashMultimap
.
create
());
private
static
final
ResponseEntity
<
ApolloConfigNotification
>
NOT_MODIFIED_RESPONSE
=
new
ResponseEntity
<>(
HttpStatus
.
NOT_MODIFIED
);
private
static
final
Joiner
STRING_JOINER
=
Joiner
.
on
(
ConfigConsts
.
CLUSTER_NAMESPACE_SEPARATOR
);
private
static
final
Splitter
STRING_SPLITTER
=
Splitter
.
on
(
ConfigConsts
.
CLUSTER_NAMESPACE_SEPARATOR
).
omitEmptyStrings
();
@Autowired
private
AppNamespaceService
appNamespaceService
;
private
WatchKeysUtil
watchKeysUtil
;
@Autowired
private
ReleaseMessageService
releaseMessageService
;
...
...
@@ -75,12 +70,7 @@ public class NotificationController implements ReleaseMessageListener {
//strip out .properties suffix
namespace
=
namespaceUtil
.
filterNamespaceName
(
namespace
);
Set
<
String
>
watchedKeys
=
assembleWatchKeys
(
appId
,
cluster
,
namespace
,
dataCenter
);
//Listen on more namespaces if it's a public namespace
if
(!
namespaceBelongsToAppId
(
appId
,
namespace
))
{
watchedKeys
.
addAll
(
this
.
findPublicConfigWatchKey
(
appId
,
cluster
,
namespace
,
dataCenter
));
}
Set
<
String
>
watchedKeys
=
watchKeysUtil
.
assembleAllWatchKeys
(
appId
,
cluster
,
namespace
,
dataCenter
);
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
deferredResult
=
new
DeferredResult
<>(
TIMEOUT
,
NOT_MODIFIED_RESPONSE
);
...
...
@@ -117,52 +107,13 @@ public class NotificationController implements ReleaseMessageListener {
});
logWatchedKeysToCat
(
watchedKeys
,
"Apollo.LongPoll.RegisteredKeys"
);
logger
.
info
(
"Listening {} from appId: {}, cluster: {}, namespace: {}, datacenter: {}"
,
logger
.
debug
(
"Listening {} from appId: {}, cluster: {}, namespace: {}, datacenter: {}"
,
watchedKeys
,
appId
,
cluster
,
namespace
,
dataCenter
);
}
return
deferredResult
;
}
private
String
assembleKey
(
String
appId
,
String
cluster
,
String
namespace
)
{
return
STRING_JOINER
.
join
(
appId
,
cluster
,
namespace
);
}
private
Set
<
String
>
findPublicConfigWatchKey
(
String
applicationId
,
String
clusterName
,
String
namespace
,
String
dataCenter
)
{
AppNamespace
appNamespace
=
appNamespaceService
.
findPublicNamespaceByName
(
namespace
);
//check whether the namespace's appId equals to current one
if
(
Objects
.
isNull
(
appNamespace
)
||
Objects
.
equals
(
applicationId
,
appNamespace
.
getAppId
()))
{
return
Sets
.
newHashSet
();
}
String
publicConfigAppId
=
appNamespace
.
getAppId
();
return
assembleWatchKeys
(
publicConfigAppId
,
clusterName
,
namespace
,
dataCenter
);
}
private
Set
<
String
>
assembleWatchKeys
(
String
appId
,
String
clusterName
,
String
namespace
,
String
dataCenter
)
{
Set
<
String
>
watchedKeys
=
Sets
.
newHashSet
();
//watch specified cluster config change
if
(!
Objects
.
equals
(
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
clusterName
))
{
watchedKeys
.
add
(
assembleKey
(
appId
,
clusterName
,
namespace
));
}
//watch data center config change
if
(!
Strings
.
isNullOrEmpty
(
dataCenter
)
&&
!
Objects
.
equals
(
dataCenter
,
clusterName
))
{
watchedKeys
.
add
(
assembleKey
(
appId
,
dataCenter
,
namespace
));
}
//watch default cluster config change
watchedKeys
.
add
(
assembleKey
(
appId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
namespace
));
return
watchedKeys
;
}
@Override
public
void
handleMessage
(
ReleaseMessage
message
,
String
channel
)
{
logger
.
info
(
"message received - channel: {}, message: {}"
,
channel
,
message
);
...
...
@@ -183,26 +134,18 @@ public class NotificationController implements ReleaseMessageListener {
new
ResponseEntity
<>(
new
ApolloConfigNotification
(
keys
.
get
(
2
),
message
.
getId
()),
HttpStatus
.
OK
);
if
(!
deferredResults
.
containsKey
(
content
))
{
return
;
}
//create a new list to avoid ConcurrentModificationException
List
<
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>>
results
=
Lists
.
newArrayList
(
deferredResults
.
get
(
content
));
logger
.
info
(
"Notify {} clients for key {}"
,
results
.
size
(),
content
);
logger
.
debug
(
"Notify {} clients for key {}"
,
results
.
size
(),
content
);
for
(
DeferredResult
<
ResponseEntity
<
ApolloConfigNotification
>>
result
:
results
)
{
result
.
setResult
(
notification
);
}
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
;
logger
.
debug
(
"Notification completed"
);
}
private
void
logWatchedKeysToCat
(
Set
<
String
>
watchedKeys
,
String
eventName
)
{
...
...
apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/util/WatchKeysUtil.java
0 → 100644
浏览文件 @
f435f27d
package
com.ctrip.framework.apollo.configservice.util
;
import
com.google.common.base.Joiner
;
import
com.google.common.base.Strings
;
import
com.google.common.collect.Sets
;
import
com.ctrip.framework.apollo.biz.service.AppNamespaceService
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
java.util.Objects
;
import
java.util.Set
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Component
public
class
WatchKeysUtil
{
private
static
final
Joiner
STRING_JOINER
=
Joiner
.
on
(
ConfigConsts
.
CLUSTER_NAMESPACE_SEPARATOR
);
@Autowired
private
AppNamespaceService
appNamespaceService
;
public
Set
<
String
>
assembleAllWatchKeys
(
String
appId
,
String
clusterName
,
String
namespace
,
String
dataCenter
)
{
Set
<
String
>
watchedKeys
=
assembleWatchKeys
(
appId
,
clusterName
,
namespace
,
dataCenter
);
//Listen on more namespaces if it's a public namespace
if
(!
namespaceBelongsToAppId
(
appId
,
namespace
))
{
watchedKeys
.
addAll
(
this
.
findPublicConfigWatchKey
(
appId
,
clusterName
,
namespace
,
dataCenter
));
}
return
watchedKeys
;
}
private
Set
<
String
>
findPublicConfigWatchKey
(
String
applicationId
,
String
clusterName
,
String
namespace
,
String
dataCenter
)
{
AppNamespace
appNamespace
=
appNamespaceService
.
findPublicNamespaceByName
(
namespace
);
//check whether the namespace's appId equals to current one
if
(
Objects
.
isNull
(
appNamespace
)
||
Objects
.
equals
(
applicationId
,
appNamespace
.
getAppId
()))
{
return
Sets
.
newHashSet
();
}
String
publicConfigAppId
=
appNamespace
.
getAppId
();
return
assembleWatchKeys
(
publicConfigAppId
,
clusterName
,
namespace
,
dataCenter
);
}
private
String
assembleKey
(
String
appId
,
String
cluster
,
String
namespace
)
{
return
STRING_JOINER
.
join
(
appId
,
cluster
,
namespace
);
}
private
Set
<
String
>
assembleWatchKeys
(
String
appId
,
String
clusterName
,
String
namespace
,
String
dataCenter
)
{
Set
<
String
>
watchedKeys
=
Sets
.
newHashSet
();
//watch specified cluster config change
if
(!
Objects
.
equals
(
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
clusterName
))
{
watchedKeys
.
add
(
assembleKey
(
appId
,
clusterName
,
namespace
));
}
//watch data center config change
if
(!
Strings
.
isNullOrEmpty
(
dataCenter
)
&&
!
Objects
.
equals
(
dataCenter
,
clusterName
))
{
watchedKeys
.
add
(
assembleKey
(
appId
,
dataCenter
,
namespace
));
}
//watch default cluster config change
watchedKeys
.
add
(
assembleKey
(
appId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
namespace
));
return
watchedKeys
;
}
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
;
}
}
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/AllTests.java
浏览文件 @
f435f27d
package
com.ctrip.framework.apollo.configservice
;
import
com.ctrip.framework.apollo.configservice.controller.ConfigControllerTest
;
import
com.ctrip.framework.apollo.configservice.controller.ConfigFileControllerTest
;
import
com.ctrip.framework.apollo.configservice.controller.NotificationControllerTest
;
import
com.ctrip.framework.apollo.configservice.integration.ConfigControllerIntegrationTest
;
import
com.ctrip.framework.apollo.configservice.integration.ConfigFileControllerIntegrationTest
;
import
com.ctrip.framework.apollo.configservice.integration.NotificationControllerIntegrationTest
;
import
com.ctrip.framework.apollo.configservice.util.NamespaceUtilTest
;
...
...
@@ -13,7 +15,8 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith
(
Suite
.
class
)
@SuiteClasses
({
ConfigControllerTest
.
class
,
NotificationControllerTest
.
class
,
ConfigControllerIntegrationTest
.
class
,
NotificationControllerIntegrationTest
.
class
,
NamespaceUtilTest
.
class
})
NamespaceUtilTest
.
class
,
ConfigFileControllerTest
.
class
,
ConfigFileControllerIntegrationTest
.
class
})
public
class
AllTests
{
}
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/ConfigFileControllerTest.java
0 → 100644
浏览文件 @
f435f27d
package
com.ctrip.framework.apollo.configservice.controller
;
import
com.google.common.cache.Cache
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Multimap
;
import
com.google.common.collect.Sets
;
import
com.ctrip.framework.apollo.biz.entity.ReleaseMessage
;
import
com.ctrip.framework.apollo.biz.message.Topics
;
import
com.ctrip.framework.apollo.configservice.util.NamespaceUtil
;
import
com.ctrip.framework.apollo.configservice.util.WatchKeysUtil
;
import
com.ctrip.framework.apollo.core.dto.ApolloConfig
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.Mock
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
javax.servlet.http.HttpServletResponse
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
ConfigFileControllerTest
{
@Mock
private
ConfigController
configController
;
@Mock
private
WatchKeysUtil
watchKeysUtil
;
@Mock
private
NamespaceUtil
namespaceUtil
;
private
ConfigFileController
configFileController
;
private
String
someAppId
;
private
String
someClusterName
;
private
String
someNamespace
;
private
String
someDataCenter
;
private
String
someClientIp
;
@Mock
private
HttpServletResponse
someResponse
;
Multimap
<
String
,
String
>
watchedKeys2CacheKey
;
Multimap
<
String
,
String
>
cacheKey2WatchedKeys
;
@Before
public
void
setUp
()
throws
Exception
{
configFileController
=
new
ConfigFileController
();
ReflectionTestUtils
.
setField
(
configFileController
,
"configController"
,
configController
);
ReflectionTestUtils
.
setField
(
configFileController
,
"watchKeysUtil"
,
watchKeysUtil
);
ReflectionTestUtils
.
setField
(
configFileController
,
"namespaceUtil"
,
namespaceUtil
);
someAppId
=
"someAppId"
;
someClusterName
=
"someClusterName"
;
someNamespace
=
"someNamespace"
;
someDataCenter
=
"someDataCenter"
;
someClientIp
=
"10.1.1.1"
;
when
(
namespaceUtil
.
filterNamespaceName
(
someNamespace
)).
thenReturn
(
someNamespace
);
watchedKeys2CacheKey
=
(
Multimap
<
String
,
String
>)
ReflectionTestUtils
.
getField
(
configFileController
,
"watchedKeys2CacheKey"
);
cacheKey2WatchedKeys
=
(
Multimap
<
String
,
String
>)
ReflectionTestUtils
.
getField
(
configFileController
,
"cacheKey2WatchedKeys"
);
}
@Test
public
void
testQueryConfigAsFile
()
throws
Exception
{
String
someKey
=
"someKey"
;
String
someValue
=
"someValue"
;
String
anotherKey
=
"anotherKey"
;
String
anotherValue
=
"anotherValue"
;
String
someWatchKey
=
"someWatchKey"
;
String
anotherWatchKey
=
"anotherWatchKey"
;
Set
<
String
>
watchKeys
=
Sets
.
newHashSet
(
someWatchKey
,
anotherWatchKey
);
String
cacheKey
=
configFileController
.
assembleCacheKey
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
);
Map
<
String
,
String
>
configurations
=
ImmutableMap
.
of
(
someKey
,
someValue
,
anotherKey
,
anotherValue
);
ApolloConfig
someApolloConfig
=
mock
(
ApolloConfig
.
class
);
when
(
someApolloConfig
.
getConfigurations
()).
thenReturn
(
configurations
);
when
(
configController
.
queryConfig
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
,
"-1"
,
someClientIp
,
someResponse
)).
thenReturn
(
someApolloConfig
);
when
(
watchKeysUtil
.
assembleAllWatchKeys
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
))
.
thenReturn
(
watchKeys
);
ResponseEntity
<
String
>
response
=
configFileController
.
queryConfigAsFile
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
,
someClientIp
,
someResponse
);
assertEquals
(
2
,
watchedKeys2CacheKey
.
size
());
assertEquals
(
2
,
cacheKey2WatchedKeys
.
size
());
assertTrue
(
watchedKeys2CacheKey
.
containsEntry
(
someWatchKey
,
cacheKey
));
assertTrue
(
watchedKeys2CacheKey
.
containsEntry
(
anotherWatchKey
,
cacheKey
));
assertTrue
(
cacheKey2WatchedKeys
.
containsEntry
(
cacheKey
,
someWatchKey
));
assertTrue
(
cacheKey2WatchedKeys
.
containsEntry
(
cacheKey
,
anotherWatchKey
));
assertEquals
(
HttpStatus
.
OK
,
response
.
getStatusCode
());
assertTrue
(
response
.
getBody
().
contains
(
String
.
format
(
"%s=%s"
,
someKey
,
someValue
)));
assertTrue
(
response
.
getBody
().
contains
(
String
.
format
(
"%s=%s"
,
anotherKey
,
anotherValue
)));
ResponseEntity
<
String
>
anotherResponse
=
configFileController
.
queryConfigAsFile
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
,
someClientIp
,
someResponse
);
assertEquals
(
response
,
anotherResponse
);
verify
(
configController
,
times
(
1
))
.
queryConfig
(
someAppId
,
someClusterName
,
someNamespace
,
someDataCenter
,
"-1"
,
someClientIp
,
someResponse
);
}
@Test
public
void
testHandleMessage
()
throws
Exception
{
String
someWatchKey
=
"someWatchKey"
;
String
anotherWatchKey
=
"anotherWatchKey"
;
String
someCacheKey
=
"someCacheKey"
;
String
anotherCacheKey
=
"anotherCacheKey"
;
String
someValue
=
"someValue"
;
ReleaseMessage
someReleaseMessage
=
mock
(
ReleaseMessage
.
class
);
when
(
someReleaseMessage
.
getMessage
()).
thenReturn
(
someWatchKey
);
Cache
<
String
,
String
>
cache
=
(
Cache
<
String
,
String
>)
ReflectionTestUtils
.
getField
(
configFileController
,
"localCache"
);
cache
.
put
(
someCacheKey
,
someValue
);
cache
.
put
(
anotherCacheKey
,
someValue
);
watchedKeys2CacheKey
.
putAll
(
someWatchKey
,
Lists
.
newArrayList
(
someCacheKey
,
anotherCacheKey
));
watchedKeys2CacheKey
.
putAll
(
anotherWatchKey
,
Lists
.
newArrayList
(
someCacheKey
,
anotherCacheKey
));
cacheKey2WatchedKeys
.
putAll
(
someCacheKey
,
Lists
.
newArrayList
(
someWatchKey
,
anotherWatchKey
));
cacheKey2WatchedKeys
.
putAll
(
anotherCacheKey
,
Lists
.
newArrayList
(
someWatchKey
,
anotherWatchKey
));
configFileController
.
handleMessage
(
someReleaseMessage
,
Topics
.
APOLLO_RELEASE_TOPIC
);
assertTrue
(
watchedKeys2CacheKey
.
isEmpty
());
assertTrue
(
cacheKey2WatchedKeys
.
isEmpty
());
}
}
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/NotificationControllerTest.java
浏览文件 @
f435f27d
...
...
@@ -11,6 +11,7 @@ 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.configservice.util.WatchKeysUtil
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.dto.ApolloConfigNotification
;
...
...
@@ -61,10 +62,13 @@ public class NotificationControllerTest {
@Before
public
void
setUp
()
throws
Exception
{
controller
=
new
NotificationController
();
ReflectionTestUtils
.
setField
(
controller
,
"appNamespaceService"
,
appNamespaceService
);
ReflectionTestUtils
.
setField
(
controller
,
"releaseMessageService"
,
releaseMessageService
);
ReflectionTestUtils
.
setField
(
controller
,
"entityManagerUtil"
,
entityManagerUtil
);
ReflectionTestUtils
.
setField
(
controller
,
"namespaceUtil"
,
namespaceUtil
);
WatchKeysUtil
watchKeysUtil
=
new
WatchKeysUtil
();
ReflectionTestUtils
.
setField
(
watchKeysUtil
,
"appNamespaceService"
,
appNamespaceService
);
ReflectionTestUtils
.
setField
(
controller
,
"watchKeysUtil"
,
watchKeysUtil
);
someAppId
=
"someAppId"
;
someCluster
=
"someCluster"
;
...
...
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/AbstractBaseIntegrationTest.java
浏览文件 @
f435f27d
package
com.ctrip.framework.apollo.configservice.integration
;
import
com.google.gson.Gson
;
import
com.ctrip.framework.apollo.ConfigServiceTestConfiguration
;
import
com.ctrip.framework.apollo.biz.entity.Namespace
;
import
com.ctrip.framework.apollo.biz.entity.Release
;
import
com.ctrip.framework.apollo.biz.entity.ReleaseMessage
;
import
com.ctrip.framework.apollo.biz.repository.ReleaseMessageRepository
;
import
com.ctrip.framework.apollo.biz.repository.ReleaseRepository
;
import
com.ctrip.framework.apollo.biz.utils.ReleaseKeyGenerator
;
import
org.junit.runner.RunWith
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.test.SpringApplicationConfiguration
;
import
org.springframework.boot.test.TestRestTemplate
;
...
...
@@ -13,6 +22,9 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import
org.springframework.web.client.DefaultResponseErrorHandler
;
import
org.springframework.web.client.RestTemplate
;
import
java.util.Date
;
import
java.util.Map
;
import
javax.annotation.PostConstruct
;
/**
...
...
@@ -22,6 +34,12 @@ import javax.annotation.PostConstruct;
@SpringApplicationConfiguration
(
classes
=
AbstractBaseIntegrationTest
.
TestConfiguration
.
class
)
@WebIntegrationTest
(
randomPort
=
true
)
public
abstract
class
AbstractBaseIntegrationTest
{
@Autowired
private
ReleaseMessageRepository
releaseMessageRepository
;
@Autowired
private
ReleaseRepository
releaseRepository
;
private
Gson
gson
=
new
Gson
();
RestTemplate
restTemplate
=
new
TestRestTemplate
(
"user"
,
""
);
...
...
@@ -40,8 +58,29 @@ public abstract class AbstractBaseIntegrationTest {
@Configuration
@Import
(
ConfigServiceTestConfiguration
.
class
)
protected
static
class
TestConfiguration
{
}
protected
void
sendReleaseMessage
(
String
message
)
{
ReleaseMessage
releaseMessage
=
new
ReleaseMessage
(
message
);
releaseMessageRepository
.
save
(
releaseMessage
);
}
public
Release
buildRelease
(
String
name
,
String
comment
,
Namespace
namespace
,
Map
<
String
,
String
>
configurations
,
String
owner
)
{
Release
release
=
new
Release
();
release
.
setReleaseKey
(
ReleaseKeyGenerator
.
generateReleaseKey
(
namespace
));
release
.
setDataChangeCreatedTime
(
new
Date
());
release
.
setDataChangeCreatedBy
(
owner
);
release
.
setDataChangeLastModifiedBy
(
owner
);
release
.
setName
(
name
);
release
.
setComment
(
comment
);
release
.
setAppId
(
namespace
.
getAppId
());
release
.
setClusterName
(
namespace
.
getClusterName
());
release
.
setNamespaceName
(
namespace
.
getNamespaceName
());
release
.
setConfigurations
(
gson
.
toJson
(
configurations
));
release
=
releaseRepository
.
save
(
release
);
return
release
;
}
}
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/ConfigFileControllerIntegrationTest.java
0 → 100644
浏览文件 @
f435f27d
package
com.ctrip.framework.apollo.configservice.integration
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.collect.Lists
;
import
com.ctrip.framework.apollo.biz.entity.Namespace
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.netflix.servo.util.Strings
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.test.context.jdbc.Sql
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
ConfigFileControllerIntegrationTest
extends
AbstractBaseIntegrationTest
{
private
String
someAppId
;
private
String
someCluster
;
private
String
someNamespace
;
private
String
somePublicNamespace
;
private
String
someDC
;
private
String
someDefaultCluster
;
@Before
public
void
setUp
()
throws
Exception
{
someDefaultCluster
=
ConfigConsts
.
CLUSTER_NAME_DEFAULT
;
someAppId
=
"someAppId"
;
someCluster
=
"someCluster"
;
someNamespace
=
"someNamespace"
;
somePublicNamespace
=
"somePublicNamespace"
;
someDC
=
"someDC"
;
}
@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
testQueryConfigAsFile
()
throws
Exception
{
ResponseEntity
<
String
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configfiles/{appId}/{clusterName}/{namespace}"
,
String
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
someNamespace
);
String
result
=
response
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
response
.
getStatusCode
());
assertTrue
(
result
.
contains
(
"k2=v2"
));
}
@Test
@Sql
(
scripts
=
"/integration-test/test-release.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/test-release-public-dc-override.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
BEFORE_TEST_METHOD
)
@Sql
(
scripts
=
"/integration-test/cleanup.sql"
,
executionPhase
=
Sql
.
ExecutionPhase
.
AFTER_TEST_METHOD
)
public
void
testQueryPublicConfigAsFile
()
throws
Exception
{
ResponseEntity
<
String
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configfiles/{appId}/{clusterName}/{namespace}?dataCenter={dateCenter}"
,
String
.
class
,
getHostUrl
(),
someAppId
,
someDefaultCluster
,
somePublicNamespace
,
someDC
);
String
result
=
response
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
response
.
getStatusCode
());
assertTrue
(
result
.
contains
(
"k1=override-someDC-v1"
));
assertTrue
(
result
.
contains
(
"k2=someDC-v2"
));
}
@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
testConfigChanged
()
throws
Exception
{
ResponseEntity
<
String
>
response
=
restTemplate
.
getForEntity
(
"{baseurl}/configfiles/{appId}/{clusterName}/{namespace}"
,
String
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
someNamespace
);
String
result
=
response
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
response
.
getStatusCode
());
assertTrue
(
result
.
contains
(
"k2=v2"
));
String
someReleaseName
=
"someReleaseName"
;
String
someReleaseComment
=
"someReleaseComment"
;
Namespace
namespace
=
new
Namespace
();
namespace
.
setAppId
(
someAppId
);
namespace
.
setClusterName
(
someCluster
);
namespace
.
setNamespaceName
(
someNamespace
);
String
someOwner
=
"someOwner"
;
Map
<
String
,
String
>
newConfigurations
=
ImmutableMap
.
of
(
"k1"
,
"v1-changed"
,
"k2"
,
"v2-changed"
);
buildRelease
(
someReleaseName
,
someReleaseComment
,
namespace
,
newConfigurations
,
someOwner
);
ResponseEntity
<
String
>
anotherResponse
=
restTemplate
.
getForEntity
(
"{baseurl}/configfiles/{appId}/{clusterName}/{namespace}"
,
String
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
someNamespace
);
assertEquals
(
response
.
getBody
(),
anotherResponse
.
getBody
());
List
<
String
>
keys
=
Lists
.
newArrayList
(
someAppId
,
someCluster
,
someNamespace
);
String
message
=
Strings
.
join
(
ConfigConsts
.
CLUSTER_NAMESPACE_SEPARATOR
,
keys
.
iterator
());
sendReleaseMessage
(
message
);
TimeUnit
.
MILLISECONDS
.
sleep
(
500
);
ResponseEntity
<
String
>
newResponse
=
restTemplate
.
getForEntity
(
"{baseurl}/configfiles/{appId}/{clusterName}/{namespace}"
,
String
.
class
,
getHostUrl
(),
someAppId
,
someCluster
,
someNamespace
);
result
=
newResponse
.
getBody
();
assertEquals
(
HttpStatus
.
OK
,
response
.
getStatusCode
());
assertTrue
(
result
.
contains
(
"k1=v1-changed"
));
assertTrue
(
result
.
contains
(
"k2=v2-changed"
));
}
}
apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/integration/NotificationControllerIntegrationTest.java
浏览文件 @
f435f27d
...
...
@@ -29,8 +29,7 @@ import static org.junit.Assert.assertNotEquals;
public
class
NotificationControllerIntegrationTest
extends
AbstractBaseIntegrationTest
{
@Autowired
private
NotificationController
notificationController
;
@Autowired
private
ReleaseMessageRepository
releaseMessageRepository
;
private
String
someAppId
;
private
String
someCluster
;
private
String
defaultNamespace
;
...
...
@@ -244,8 +243,7 @@ public class NotificationControllerIntegrationTest extends AbstractBaseIntegrati
break
;
}
ReleaseMessage
releaseMessage
=
new
ReleaseMessage
(
message
);
releaseMessageRepository
.
save
(
releaseMessage
);
sendReleaseMessage
(
message
);
}
});
}
...
...
apollo-core/pom.xml
浏览文件 @
f435f27d
...
...
@@ -4,7 +4,7 @@
<parent>
<groupId>
com.ctrip.framework.apollo
</groupId>
<artifactId>
apollo
</artifactId>
<version>
0.0.
5
</version>
<version>
0.0.
6-SNAPSHOT
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<modelVersion>
4.0.0
</modelVersion>
...
...
apollo-core/src/main/java/com/ctrip/framework/apollo/core/utils/PropertiesUtil.java
0 → 100644
浏览文件 @
f435f27d
package
com.ctrip.framework.apollo.core.utils
;
import
java.io.IOException
;
import
java.io.StringWriter
;
import
java.util.Properties
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
PropertiesUtil
{
/**
* Transform the properties to string format
* @param properties the properties object
* @return the string containing the properties
* @throws IOException
*/
public
static
String
toString
(
Properties
properties
)
throws
IOException
{
StringWriter
writer
=
new
StringWriter
();
properties
.
store
(
writer
,
null
);
StringBuffer
stringBuffer
=
writer
.
getBuffer
();
filterPropertiesComment
(
stringBuffer
);
return
stringBuffer
.
toString
();
}
/**
* filter out the first comment line
* @param stringBuffer the string buffer
* @return true if filtered successfully, false otherwise
*/
static
boolean
filterPropertiesComment
(
StringBuffer
stringBuffer
)
{
//check whether has comment in the first line
if
(
stringBuffer
.
charAt
(
0
)
!=
'#'
)
{
return
false
;
}
int
commentLineIndex
=
stringBuffer
.
indexOf
(
"\n"
);
if
(
commentLineIndex
==
-
1
)
{
return
false
;
}
stringBuffer
.
delete
(
0
,
commentLineIndex
+
1
);
return
true
;
}
}
apollo-demo/pom.xml
浏览文件 @
f435f27d
...
...
@@ -4,7 +4,7 @@
<parent>
<artifactId>
apollo
</artifactId>
<groupId>
com.ctrip.framework.apollo
</groupId>
<version>
0.0.
5
</version>
<version>
0.0.
6-SNAPSHOT
</version>
</parent>
<modelVersion>
4.0.0
</modelVersion>
<artifactId>
apollo-demo
</artifactId>
...
...
apollo-demo/src/main/java/ApolloConfigFileDemo.java
浏览文件 @
f435f27d
...
...
@@ -8,6 +8,8 @@ import org.slf4j.LoggerFactory;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.io.StringReader
;
import
java.util.Properties
;
/**
* @author Jason Song(song_s@ctrip.com)
...
...
@@ -18,7 +20,7 @@ public class ApolloConfigFileDemo {
private
String
namespace
=
"application"
;
public
ApolloConfigFileDemo
()
{
configFile
=
ConfigService
.
getConfigFile
(
namespace
,
ConfigFileFormat
.
XML
);
configFile
=
ConfigService
.
getConfigFile
(
namespace
,
ConfigFileFormat
.
Properties
);
}
private
void
print
()
{
...
...
apollo-portal/pom.xml
浏览文件 @
f435f27d
...
...
@@ -4,7 +4,7 @@
<parent>
<groupId>
com.ctrip.framework.apollo
</groupId>
<artifactId>
apollo
</artifactId>
<version>
0.0.
5
</version>
<version>
0.0.
6-SNAPSHOT
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<modelVersion>
4.0.0
</modelVersion>
...
...
pom.xml
浏览文件 @
f435f27d
...
...
@@ -4,7 +4,7 @@
<modelVersion>
4.0.0
</modelVersion>
<groupId>
com.ctrip.framework.apollo
</groupId>
<artifactId>
apollo
</artifactId>
<version>
0.0.
5
</version>
<version>
0.0.
6-SNAPSHOT
</version>
<name>
Apollo
</name>
<packaging>
pom
</packaging>
<description>
Ctrip Configuration Center
</description>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录