Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
apollo
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
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
openSource
apollo
Commits
47478b47
Commit
47478b47
authored
Mar 22, 2016
by
Jason Song
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #22 from yiming187/dev_branch
Merge MetaServer into ConfigServer
parents
b0f5f4ae
dfc172a1
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
92 additions
and
270 deletions
+92
-270
pom.xml
apollo-assembly/pom.xml
+0
-13
pom.xml
apollo-biz/pom.xml
+1
-1
application.properties
apollo-biz/src/main/resources/application.properties
+2
-0
RemoteConfigLoader.java
...m/ctrip/apollo/client/loader/impl/RemoteConfigLoader.java
+16
-11
pom.xml
apollo-configadmin/pom.xml
+40
-4
AdminServiceApplication.java
...com/ctrip/apollo/configadmin/AdminServiceApplication.java
+6
-8
application.yml
apollo-configadmin/src/main/resources/application.yml
+6
-6
bootstrap.yml
apollo-configadmin/src/main/resources/bootstrap.yml
+2
-4
pom.xml
apollo-configserver/pom.xml
+1
-23
ServerApplication.java
...ver/src/main/java/com/ctrip/apollo/ServerApplication.java
+6
-4
WebConfig.java
.../java/com/ctrip/apollo/configserver/config/WebConfig.java
+0
-47
ConfigController.java
...trip/apollo/configserver/controller/ConfigController.java
+1
-0
DiscoveryService.java
...m/ctrip/apollo/configserver/service/DiscoveryService.java
+0
-29
ServiceController.java
...ctrip/apollo/metaserver/controller/ServiceController.java
+0
-0
DiscoveryService.java
...com/ctrip/apollo/metaserver/service/DiscoveryService.java
+0
-0
application.yml
apollo-configserver/src/main/resources/application.yml
+5
-1
bootstrap.yml
apollo-configserver/src/main/resources/bootstrap.yml
+4
-4
welcome.jsp
...lo-configserver/src/main/webapp/WEB-INF/views/welcome.jsp
+0
-10
DiscoveryServiceTest.java
...rip/apollo/configserver/service/DiscoveryServiceTest.java
+0
-21
AbstractMetaServerTest.java
...a/com/ctrip/apollo/metaserver/AbstractMetaServerTest.java
+0
-11
AllTests.java
...r/src/test/java/com/ctrip/apollo/metaserver/AllTests.java
+0
-13
DiscoveryControllerTest.java
...apollo/metaserver/controller/DiscoveryControllerTest.java
+0
-37
application.yml
apollo-metaserver/src/test/resources/application.yml
+0
-5
bootstrap.yml
apollo-metaserver/src/test/resources/bootstrap.yml
+0
-15
pom.xml
pom.xml
+2
-3
No files found.
apollo-assembly/pom.xml
deleted
100644 → 0
View file @
b0f5f4ae
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
>
<parent>
<groupId>
com.ctrip.apollo
</groupId>
<artifactId>
apollo
</artifactId>
<version>
0.0.1-SNAPSHOT
</version>
<relativePath>
../pom.xml
</relativePath>
</parent>
<modelVersion>
4.0.0
</modelVersion>
<artifactId>
apollo-assembly
</artifactId>
<name>
Apollo Assembly
</name>
</project>
apollo-biz/pom.xml
View file @
47478b47
...
...
@@ -9,7 +9,7 @@
</parent>
<modelVersion>
4.0.0
</modelVersion>
<artifactId>
apollo-biz
</artifactId>
<name>
Apollo Biz
Logic
</name>
<name>
Apollo Biz
</name>
<packaging>
jar
</packaging>
<dependencies>
...
...
apollo-biz/src/main/resources/application.properties
View file @
47478b47
...
...
@@ -2,3 +2,4 @@ spring.datasource.url = jdbc:h2:file:~/fxapolloconfigdb;mode=mysql
spring.datasource.username
=
sa
spring.datasource.password
=
spring.jpa.hibernate.naming_strategy
=
org.hibernate.cfg.EJB3NamingStrategy
spring.h2.console.enabled
=
true
\ No newline at end of file
apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/RemoteConfigLoader.java
View file @
47478b47
package
com
.
ctrip
.
apollo
.
client
.
loader
.
impl
;
import
com.ctrip.apollo.client.loader.ConfigLoader
;
import
com.ctrip.apollo.client.model.ApolloRegistry
;
import
com.ctrip.apollo.client.util.ConfigUtil
;
import
com.ctrip.apollo.core.model.ApolloConfig
;
import
com.google.common.collect.Lists
;
import
java.io.IOException
;
import
java.util.List
;
import
java.util.concurrent.Callable
;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.ThreadFactory
;
import
java.util.concurrent.atomic.AtomicLong
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.core.env.CompositePropertySource
;
...
...
@@ -16,11 +21,11 @@ import org.springframework.http.ResponseEntity;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.client.RestTemplate
;
import
java.io.IOException
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.*
;
import
java.util.concurrent.atomic.AtomicLong
;
import
com.ctrip.apollo.client.loader.ConfigLoader
;
import
com.ctrip.apollo.client.model.ApolloRegistry
;
import
com.ctrip.apollo.client.util.ConfigUtil
;
import
com.ctrip.apollo.core.model.ApolloConfig
;
import
com.google.common.collect.Lists
;
/**
* Load config from remote config server
...
...
@@ -116,7 +121,7 @@ public class RemoteConfigLoader implements ConfigLoader {
ApolloConfig
getRemoteConfig
(
RestTemplate
restTemplate
,
String
uri
,
long
appId
,
String
cluster
,
String
version
)
{
logger
.
info
(
"Loading config from {}, appId={}, cluster={}, version={}"
,
uri
,
appId
,
cluster
,
version
);
String
path
=
"/{appId}/{cluster}"
;
String
path
=
"
config
/{appId}/{cluster}"
;
Object
[]
args
=
new
String
[]
{
String
.
valueOf
(
appId
),
cluster
};
if
(
StringUtils
.
hasText
(
version
))
{
args
=
new
String
[]
{
String
.
valueOf
(
appId
),
cluster
,
version
};
...
...
apollo-
metaserver
/pom.xml
→
apollo-
configadmin
/pom.xml
View file @
47478b47
...
...
@@ -8,17 +8,53 @@
<relativePath>
../pom.xml
</relativePath>
</parent>
<modelVersion>
4.0.0
</modelVersion>
<artifactId>
apollo-
metaserver
</artifactId>
<name>
Apollo
MetaServer
</name>
<artifactId>
apollo-
configadmin
</artifactId>
<name>
Apollo
ConfigAdmin
</name>
<dependencies>
<!-- apollo -->
<dependency>
<groupId>
com.ctrip.apollo
</groupId>
<artifactId>
apollo-
core
</artifactId>
<artifactId>
apollo-
biz
</artifactId>
</dependency>
<!-- end of apollo -->
<!-- web -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-tomcat
</artifactId>
<scope>
provided
</scope>
</dependency>
<!-- end of web -->
<!-- redis -->
<dependency>
<groupId>
org.springframework.data
</groupId>
<artifactId>
spring-data-redis
</artifactId>
</dependency>
<dependency>
<groupId>
redis.clients
</groupId>
<artifactId>
jedis
</artifactId>
</dependency>
<!-- end of redis -->
<!-- eureka -->
<dependency>
<groupId>
org.springframework.cloud
</groupId>
<artifactId>
spring-cloud-starter-eureka
-server
</artifactId>
<artifactId>
spring-cloud-starter-eureka
</artifactId>
</dependency>
<!-- end of eureka -->
<!-- jsp -->
<dependency>
<groupId>
javax.servlet
</groupId>
<artifactId>
jstl
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.tomcat.embed
</groupId>
<artifactId>
tomcat-embed-jasper
</artifactId>
<scope>
provided
</scope>
</dependency>
<!-- end of jsp -->
</dependencies>
<build>
<plugins>
...
...
apollo-
metaserver/src/main/java/com/ctrip/apollo/metaserver/MetaServer
Application.java
→
apollo-
configadmin/src/main/java/com/ctrip/apollo/configadmin/AdminService
Application.java
View file @
47478b47
package
com
.
ctrip
.
apollo
.
metaserver
;
package
com
.
ctrip
.
apollo
.
configadmin
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.builder.SpringApplicationBuilder
;
import
org.springframework.cloud.netflix.eureka.EnableEurekaClient
;
import
org.springframework.cloud.netflix.eureka.server.EnableEurekaServer
;
@SpringBootApplication
@EnableEurekaServer
@EnableEurekaClient
public
class
MetaServerApplication
{
public
static
void
main
(
String
[]
args
)
{
new
SpringApplicationBuilder
(
MetaServerApplication
.
class
).
web
(
true
).
run
(
args
);
}
public
class
AdminServiceApplication
{
public
static
void
main
(
String
[]
args
)
{
new
SpringApplicationBuilder
(
AdminServiceApplication
.
class
).
web
(
true
).
run
(
args
);
}
}
apollo-
metaserver
/src/main/resources/application.yml
→
apollo-
configadmin
/src/main/resources/application.yml
View file @
47478b47
spring
:
application
:
name
:
apollo-metaserver
profiles
:
active
:
native
name
:
apollo-configadmin
server
:
port
:
9080
logging
:
level
:
org.springframework.cloud
:
'
DEBUG'
file
:
/opt/logs/apollo-configadmin.log
\ No newline at end of file
apollo-
metaserver
/src/main/resources/bootstrap.yml
→
apollo-
configadmin
/src/main/resources/bootstrap.yml
View file @
47478b47
server
:
port
:
8761
eureka
:
instance
:
hostname
:
localhost
...
...
@@ -8,4 +5,4 @@ eureka:
serviceUrl
:
defaultZone
:
http://${eureka.instance.hostname}:${server.port}/eureka/
healthcheck
:
enabled
:
true
enabled
:
true
\ No newline at end of file
apollo-configserver/pom.xml
View file @
47478b47
...
...
@@ -18,17 +18,6 @@
<artifactId>
apollo-biz
</artifactId>
</dependency>
<!-- end of apollo -->
<!-- web -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-tomcat
</artifactId>
<scope>
provided
</scope>
</dependency>
<!-- end of web -->
<!-- redis -->
<dependency>
<groupId>
org.springframework.data
</groupId>
...
...
@@ -42,20 +31,9 @@
<!-- eureka -->
<dependency>
<groupId>
org.springframework.cloud
</groupId>
<artifactId>
spring-cloud-starter-eureka
</artifactId>
<artifactId>
spring-cloud-starter-eureka
-server
</artifactId>
</dependency>
<!-- end of eureka -->
<!-- jsp -->
<dependency>
<groupId>
javax.servlet
</groupId>
<artifactId>
jstl
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.tomcat.embed
</groupId>
<artifactId>
tomcat-embed-jasper
</artifactId>
<scope>
provided
</scope>
</dependency>
<!-- end of jsp -->
</dependencies>
<build>
<plugins>
...
...
apollo-configserver/src/main/java/com/ctrip/apollo/ServerApplication.java
View file @
47478b47
package
com
.
ctrip
.
apollo
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.cloud.client.discovery.EnableDiscoveryClient
;
import
org.springframework.boot.builder.SpringApplicationBuilder
;
import
org.springframework.cloud.netflix.eureka.EnableEurekaClient
;
import
org.springframework.cloud.netflix.eureka.server.EnableEurekaServer
;
/**
* Spring boot application entry point
* @author Jason Song(song_s@ctrip.com)
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableEurekaServer
@EnableEurekaClient
public
class
ServerApplication
{
public
static
void
main
(
String
[]
args
)
{
SpringApplication
.
run
(
ServerApplication
.
class
,
args
);
new
SpringApplicationBuilder
(
ServerApplication
.
class
).
web
(
true
).
run
(
args
);
}
}
apollo-configserver/src/main/java/com/ctrip/apollo/configserver/config/WebConfig.java
deleted
100644 → 0
View file @
b0f5f4ae
package
com
.
ctrip
.
apollo
.
configserver
.
config
;
import
org.h2.server.web.WebServlet
;
import
org.springframework.boot.context.embedded.ServletRegistrationBean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.web.servlet.config.annotation.EnableWebMvc
;
import
org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
;
import
org.springframework.web.servlet.config.annotation.ViewControllerRegistry
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
;
import
org.springframework.web.servlet.view.InternalResourceViewResolver
;
import
org.springframework.web.servlet.view.JstlView
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Configuration
@EnableWebMvc
public
class
WebConfig
extends
WebMvcConfigurerAdapter
{
@Override
public
void
addViewControllers
(
ViewControllerRegistry
registry
)
{
registry
.
addViewController
(
"/"
).
setViewName
(
"welcome"
);
registry
.
addViewController
(
"/index"
).
setViewName
(
"welcome"
);
}
@Bean
public
InternalResourceViewResolver
viewResolver
()
{
InternalResourceViewResolver
viewResolver
=
new
InternalResourceViewResolver
();
viewResolver
.
setViewClass
(
JstlView
.
class
);
viewResolver
.
setPrefix
(
"/WEB-INF/views/"
);
viewResolver
.
setSuffix
(
".jsp"
);
return
viewResolver
;
}
@Override
public
void
addResourceHandlers
(
ResourceHandlerRegistry
registry
)
{
registry
.
addResourceHandler
(
"/**"
).
addResourceLocations
(
"/"
);
}
@Bean
ServletRegistrationBean
h2servletRegistration
(){
ServletRegistrationBean
registrationBean
=
new
ServletRegistrationBean
(
new
WebServlet
());
registrationBean
.
addUrlMappings
(
"/console/*"
);
return
registrationBean
;
}
}
apollo-configserver/src/main/java/com/ctrip/apollo/configserver/controller/ConfigController.java
View file @
47478b47
...
...
@@ -16,6 +16,7 @@ import java.io.IOException;
* @author Jason Song(song_s@ctrip.com)
*/
@RestController
@RequestMapping
(
"/config"
)
public
class
ConfigController
{
@Resource
(
name
=
"configService"
)
private
ConfigService
configService
;
...
...
apollo-configserver/src/main/java/com/ctrip/apollo/configserver/service/DiscoveryService.java
deleted
100644 → 0
View file @
b0f5f4ae
package
com
.
ctrip
.
apollo
.
configserver
.
service
;
import
java.util.List
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.cloud.client.ServiceInstance
;
import
org.springframework.cloud.client.discovery.DiscoveryClient
;
import
org.springframework.stereotype.Service
;
import
com.ctrip.apollo.core.ServiceIdConsts
;
@Service
public
class
DiscoveryService
{
@Autowired
private
DiscoveryClient
discoveryClient
;
public
List
<
ServiceInstance
>
getConfigServerServiceInstances
()
{
List
<
ServiceInstance
>
instances
=
discoveryClient
.
getInstances
(
ServiceIdConsts
.
APOLLO_CONFIGSERVER
);
return
instances
;
}
public
List
<
ServiceInstance
>
getMetaServerServiceInstances
()
{
List
<
ServiceInstance
>
instances
=
discoveryClient
.
getInstances
(
ServiceIdConsts
.
APOLLO_METASERVER
);
return
instances
;
}
}
apollo-
meta
server/src/main/java/com/ctrip/apollo/metaserver/controller/ServiceController.java
→
apollo-
config
server/src/main/java/com/ctrip/apollo/metaserver/controller/ServiceController.java
View file @
47478b47
File moved
apollo-
meta
server/src/main/java/com/ctrip/apollo/metaserver/service/DiscoveryService.java
→
apollo-
config
server/src/main/java/com/ctrip/apollo/metaserver/service/DiscoveryService.java
View file @
47478b47
File moved
apollo-configserver/src/main/resources/application.yml
View file @
47478b47
spring
:
application
:
name
:
apollo-configserver
server
:
port
:
8
888
port
:
8
0
logging
:
level
:
...
...
apollo-configserver/src/main/resources/bootstrap.yml
View file @
47478b47
spring
:
application
:
name
:
apollo-configserver
eureka
:
instance
:
hostname
:
localhost
client
:
serviceUrl
:
defaultZone
:
http://${eureka.instance.hostname}:8761/eureka/
defaultZone
:
http://${eureka.instance.hostname}:${server.port}/eureka/
healthcheck
:
enabled
:
true
\ No newline at end of file
apollo-configserver/src/main/webapp/WEB-INF/views/welcome.jsp
deleted
100644 → 0
View file @
b0f5f4ae
<!DOCTYPE html>
<
%@
page
contentType=
"text/html"
pageEncoding=
"UTF-8"
%
>
<html>
<meta
http-equiv=
Content-Type
content=
"text/html;charset=utf-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
>
<title>
Apollo Config Server
</title>
<body>
<h2>
Welcome to Apollo Config Server!
</h2>
</body>
</html>
apollo-configserver/src/test/java/com/ctrip/apollo/configserver/service/DiscoveryServiceTest.java
deleted
100644 → 0
View file @
b0f5f4ae
package
com
.
ctrip
.
apollo
.
configserver
.
service
;
import
java.util.List
;
import
org.junit.Test
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.cloud.client.ServiceInstance
;
import
com.ctrip.apollo.configserver.AbstractConfigServerTest
;
public
class
DiscoveryServiceTest
extends
AbstractConfigServerTest
{
@Autowired
private
DiscoveryService
discoveryService
;
@Test
public
void
testGetLocalMetaServerServices
()
{
List
<
ServiceInstance
>
instances
=
discoveryService
.
getMetaServerServiceInstances
();
System
.
out
.
println
(
instances
);
}
}
apollo-metaserver/src/test/java/com/ctrip/apollo/metaserver/AbstractMetaServerTest.java
deleted
100644 → 0
View file @
b0f5f4ae
package
com
.
ctrip
.
apollo
.
metaserver
;
import
org.junit.runner.RunWith
;
import
org.springframework.boot.test.SpringApplicationConfiguration
;
import
org.springframework.test.context.junit4.SpringJUnit4ClassRunner
;
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@SpringApplicationConfiguration
(
classes
=
MetaServerApplication
.
class
)
public
abstract
class
AbstractMetaServerTest
{
}
apollo-metaserver/src/test/java/com/ctrip/apollo/metaserver/AllTests.java
deleted
100644 → 0
View file @
b0f5f4ae
package
com
.
ctrip
.
apollo
.
metaserver
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.Suite
;
import
org.junit.runners.Suite.SuiteClasses
;
@RunWith
(
Suite
.
class
)
@SuiteClasses
({
})
public
class
AllTests
{
}
apollo-metaserver/src/test/java/com/ctrip/apollo/metaserver/controller/DiscoveryControllerTest.java
deleted
100644 → 0
View file @
b0f5f4ae
package
com
.
ctrip
.
apollo
.
metaserver
.
controller
;
import
java.net.URI
;
import
java.net.URISyntaxException
;
import
org.junit.Assert
;
import
org.junit.Test
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.test.TestRestTemplate
;
import
org.springframework.boot.test.WebIntegrationTest
;
import
org.springframework.web.client.RestTemplate
;
import
com.ctrip.apollo.core.ServiceIdConsts
;
import
com.ctrip.apollo.metaserver.AbstractMetaServerTest
;
import
com.netflix.appinfo.InstanceInfo
;
@WebIntegrationTest
public
class
DiscoveryControllerTest
extends
AbstractMetaServerTest
{
RestTemplate
restTemplate
=
new
TestRestTemplate
();
@Value
(
"${local.server.port}"
)
String
serverPort
;
@Test
public
void
testGetMetaServerServices
()
throws
InterruptedException
,
URISyntaxException
{
// Wait Eureka Client to fresh meta
Thread
.
sleep
(
5000
);
URI
uri
=
new
URI
(
"http://localhost:"
+
serverPort
+
"/services/meta"
);
InstanceInfo
[]
serviceInstances
=
restTemplate
.
getForObject
(
uri
,
InstanceInfo
[].
class
);
Assert
.
assertEquals
(
1
,
serviceInstances
.
length
);
Assert
.
assertEquals
(
ServiceIdConsts
.
APOLLO_METASERVER
,
serviceInstances
[
0
].
getAppName
().
toLowerCase
());
}
}
apollo-metaserver/src/test/resources/application.yml
deleted
100644 → 0
View file @
b0f5f4ae
spring
:
application
:
name
:
apollo-metaserver
profiles
:
active
:
native
apollo-metaserver/src/test/resources/bootstrap.yml
deleted
100644 → 0
View file @
b0f5f4ae
server
:
port
:
8761
eureka
:
instance
:
hostname
:
localhost
leaseRenewalIntervalInSeconds
:
1
client
:
# initialInstanceInfoReplicationIntervalSeconds: 1
registryFetchIntervalSeconds
:
2
serviceUrl
:
defaultZone
:
http://${eureka.instance.hostname}:${server.port:8761}/eureka/
healthcheck
:
enabled
:
true
\ No newline at end of file
pom.xml
View file @
47478b47
...
...
@@ -65,13 +65,12 @@
</properties>
<modules>
<module>
apollo-core
</module>
<module>
apollo-metaserver
</module>
<module>
apollo-client
</module>
<module>
apollo-biz
</module>
<module>
apollo-configserver
</module>
<module>
apollo-configadmin
</module>
<module>
apollo-portal
</module>
<module>
apollo-assembly
</module>
<module>
apollo-demo
</module>
<module>
apollo-biz
</module>
</modules>
<dependencyManagement>
<dependencies>
...
...
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