├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── beekeeper ├── pom.xml └── src │ ├── main │ ├── java │ │ └── io │ │ │ └── servicecomb │ │ │ └── company │ │ │ └── beekeeper │ │ │ ├── Ancestor.java │ │ │ ├── BeekeeperApplication.java │ │ │ ├── BeekeeperConfig.java │ │ │ ├── BeekeeperController.java │ │ │ ├── BeekeeperService.java │ │ │ ├── BeekeeperServiceImpl.java │ │ │ └── FibonacciCalculator.java │ └── resources │ │ ├── application.yml │ │ ├── log4j2.xml │ │ └── microservice.yaml │ └── test │ └── java │ └── io │ └── servicecomb │ └── company │ └── beekeeper │ ├── BeekeeperControllerTest.java │ └── BeekeeperServiceImplTest.java ├── coverage-aggregate └── pom.xml ├── docker-build-config ├── assembly │ └── assembly.xml └── pom.xml ├── docker-compose.yml ├── docker-run-config └── pom.xml ├── docs ├── how-to-auto-deploy-on-huawei-cloud-cn.md ├── how-to-auto-deploy-on-huawei-cloud.md ├── how-to-auto-publish-images-to-huawei-cloud-cn.md ├── how-to-auto-publish-images-to-huawei-cloud.md ├── how-to-install-docker-cn.md ├── how-to-install-docker.md └── images │ ├── cluster_info.png │ ├── copy_image_address.png │ ├── copy_image_address_cn.png │ ├── get_host_address.png │ ├── get_host_address_cn.png │ ├── import_template.png │ ├── import_template_cn.png │ ├── save_and_deploy.png │ ├── save_and_deploy_cn.png │ ├── update_cluster_name.png │ ├── update_cluster_name_cn.png │ ├── update_image_address.png │ ├── update_image_address_cn.png │ ├── variables_information.png │ ├── variables_information_cn.png │ ├── view_manager_details.png │ └── view_manager_details_cn.png ├── doorman ├── pom.xml └── src │ ├── main │ ├── java │ │ └── io │ │ │ └── servicecomb │ │ │ └── company │ │ │ ├── DoormanApplication.java │ │ │ └── auth │ │ │ ├── AuthenticationConfig.java │ │ │ ├── AuthenticationService.java │ │ │ ├── AuthenticationServiceImpl.java │ │ │ ├── JwtTokenStore.java │ │ │ ├── TokenException.java │ │ │ ├── TokenStore.java │ │ │ ├── UnauthorizedAccessException.java │ │ │ ├── domain │ │ │ ├── User.java │ │ │ └── UserRepository.java │ │ │ └── endpoint │ │ │ └── rest │ │ │ ├── AuthenticationController.java │ │ │ ├── AuthenticationExceptionHandler.java │ │ │ ├── AuthorizationHeaderGenerator.java │ │ │ └── Token.java │ └── resources │ │ ├── application.yml │ │ ├── log4j2.xml │ │ ├── microservice.yaml │ │ └── schema-mysql.sql │ └── test │ ├── java │ └── io │ │ └── servicecomb │ │ └── company │ │ └── auth │ │ ├── AuthenticationServiceImplTest.java │ │ ├── JwtTokenStoreTest.java │ │ └── endpoint │ │ └── rest │ │ ├── AuthenticationContractTest.java │ │ ├── AuthenticationControllerTest.java │ │ └── AuthenticationIntegrationTest.java │ └── resources │ └── data.sql ├── etc ├── log │ └── log4j2.xml └── microservice │ ├── beekeeper.yaml │ ├── doorman.yaml │ ├── manager.yaml │ └── worker.yaml ├── integration-tests ├── beekeeper-tests │ ├── pom.xml │ └── src │ │ └── test │ │ └── java │ │ └── io │ │ └── servicecomb │ │ └── company │ │ └── beekeeper │ │ └── BeekeeperApplicationIT.java ├── manager-tests │ ├── pom.xml │ └── src │ │ └── test │ │ └── java │ │ └── io │ │ └── servicecomb │ │ └── company │ │ └── manager │ │ └── ManagerApplicationIT.java ├── pom.xml └── worker-tests │ ├── pom.xml │ └── src │ └── test │ ├── java │ └── io │ │ └── servicecomb │ │ └── company │ │ └── worker │ │ ├── FibonacciProvider.java │ │ └── WorkerApplicationIT.java │ └── resources │ ├── application.yaml │ └── microservice.yaml ├── kubernetes ├── README.md ├── cleanup-autoscale.sh ├── cleanup.sh ├── company-beekeeper-deployment.yaml ├── company-bulletin-board-deployment.yaml ├── company-bulletin-board-service.yaml ├── company-doorman-deployment.yaml ├── company-manager-deployment.yaml ├── company-manager-service.yaml ├── company-worker-deployment.yaml ├── mysql-deployment.yaml ├── mysql-service.yaml ├── start-autoscale.sh ├── start.sh ├── zipkin-deployment.yaml └── zipkin-service.yaml ├── manager ├── pom.xml └── src │ ├── main │ ├── java │ │ └── io │ │ │ └── servicecomb │ │ │ └── company │ │ │ └── manager │ │ │ ├── AuthenticationService.java │ │ │ ├── ManagerApplication.java │ │ │ ├── RestTemplateConfig.java │ │ │ ├── Token.java │ │ │ ├── archive │ │ │ ├── Archive.java │ │ │ ├── HitArchive.java │ │ │ ├── MissArchive.java │ │ │ ├── ProjectArchive.java │ │ │ └── ProjectArchiveConfig.java │ │ │ └── filters │ │ │ ├── AuthenticationAwareFilter.java │ │ │ ├── BeekeeperCacheFetchFilter.java │ │ │ ├── BeekeeperCacheUpdateFilter.java │ │ │ ├── CacheFetchFilter.java │ │ │ ├── CacheUpdateFilter.java │ │ │ ├── FilterConstants.java │ │ │ ├── PathExtractor.java │ │ │ ├── WorkerCacheFetchFilter.java │ │ │ └── WorkerCacheUpdateFilter.java │ └── resources │ │ ├── application.yaml │ │ ├── log4j2.xml │ │ └── microservice.yaml │ └── test │ └── java │ └── io │ └── servicecomb │ └── company │ └── manager │ ├── AuthenticationServiceFailedTest.java │ ├── AuthenticationServiceHappyTest.java │ ├── AuthenticationServiceTest.java │ ├── FixedUrlRestTemplate.java │ ├── FixedUrlRestTemplateConfig.java │ ├── ManagerApplicationTest.java │ ├── ProjectArchiveTest.java │ ├── archive │ ├── HitArchiveTest.java │ └── MissArchiveTest.java │ └── filters │ └── PathExtractorTest.java ├── pom.xml ├── scripts ├── blueprint.yaml ├── make_docker_image │ └── Dockerfile └── publish_images_to_huaweicloud.sh ├── settings.xml ├── stress-tests ├── README.md ├── hosts.csv └── workshop.jmx └── worker ├── pom.xml └── src ├── main ├── java │ └── io │ │ └── servicecomb │ │ └── company │ │ └── worker │ │ ├── FibonacciEndpoint.java │ │ ├── FibonacciRestEndpoint.java │ │ ├── FibonacciRpcEndpoint.java │ │ ├── FibonacciService.java │ │ ├── FibonacciServiceImpl.java │ │ └── WorkerApplication.java └── resources │ ├── application.yml │ ├── log4j2.xml │ └── microservice.yaml └── test └── java └── io └── servicecomb └── company └── worker ├── FibonacciRestEndpointTest.java ├── FibonacciRpcEndpointTest.java └── FibonacciServiceTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | *.log -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | language: java 4 | 5 | cache: 6 | directories: 7 | - "$HOME/.m2" 8 | 9 | services: 10 | - docker 11 | 12 | script: 13 | - mvn clean install -Ddocker.useColor=false -Ddocker.showLogs -Pdocker -Pjacoco coveralls:report 14 | -------------------------------------------------------------------------------- /beekeeper/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | company 23 | io.servicecomb.workshop.demo 24 | 0.3.0-SNAPSHOT 25 | 26 | 4.0.0 27 | 28 | beekeeper 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-logging 38 | 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-log4j2 44 | 45 | 46 | org.apache.logging.log4j 47 | log4j-web 48 | 49 | 50 | com.lmax 51 | disruptor 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-starter-web 56 | 57 | 58 | io.servicecomb 59 | spring-boot-starter-provider 60 | 61 | 62 | io.servicecomb 63 | handler-tracing-zipkin 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-starter-test 69 | test 70 | 71 | 72 | com.github.seanyinx 73 | unit-scaffolding 74 | test 75 | 76 | 77 | 78 | 79 | 80 | 81 | com.github.odavid.maven.plugins 82 | mixin-maven-plugin 83 | 84 | 85 | 86 | io.servicecomb.workshop.demo 87 | docker-build-config 88 | 0.3.0-SNAPSHOT 89 | 90 | 91 | 92 | 93 | 94 | org.springframework.boot 95 | spring-boot-maven-plugin 96 | 97 | 98 | 99 | 100 | 101 | 102 | docker 103 | 104 | 105 | 106 | io.fabric8 107 | docker-maven-plugin 108 | 109 | 110 | org.commonjava.maven.plugins 111 | directory-maven-plugin 112 | 113 | 114 | 115 | 116 | 117 | HuaweiCloud 118 | 119 | 120 | 121 | maven-antrun-plugin 122 | 1.8 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /beekeeper/src/main/java/io/servicecomb/company/beekeeper/Ancestor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.beekeeper; 18 | 19 | class Ancestor { 20 | private long ancestors; 21 | 22 | /** 23 | * Default constructor for Json deserialization 24 | */ 25 | Ancestor() { 26 | } 27 | 28 | Ancestor(long ancestors) { 29 | this.ancestors = ancestors; 30 | } 31 | 32 | public long getAncestors() { 33 | return ancestors; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /beekeeper/src/main/java/io/servicecomb/company/beekeeper/BeekeeperApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.beekeeper; 18 | 19 | import io.servicecomb.springboot.starter.provider.EnableServiceComb; 20 | import org.springframework.boot.SpringApplication; 21 | import org.springframework.boot.autoconfigure.SpringBootApplication; 22 | import org.springframework.context.annotation.Configuration; 23 | import org.springframework.context.annotation.Profile; 24 | 25 | @SpringBootApplication 26 | public class BeekeeperApplication { 27 | 28 | public static void main(String[] args) { 29 | SpringApplication.run(BeekeeperApplication.class, args); 30 | } 31 | 32 | // do not enable service registration/discovery and schema generation/registration 33 | // unless the active profile is not dev 34 | @EnableServiceComb 35 | @Profile("!dev") 36 | @Configuration 37 | static class ServiceCombConfig { 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /beekeeper/src/main/java/io/servicecomb/company/beekeeper/BeekeeperConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.beekeeper; 18 | 19 | import io.servicecomb.provider.pojo.RpcReference; 20 | import org.springframework.context.annotation.Bean; 21 | import org.springframework.context.annotation.Configuration; 22 | 23 | @Configuration 24 | class BeekeeperConfig { 25 | 26 | @RpcReference(microserviceName = "worker", schemaId = "fibonacciRpcEndpoint") 27 | private FibonacciCalculator fibonacciCalculator; 28 | 29 | @Bean 30 | BeekeeperService beekeeperService() { 31 | return new BeekeeperServiceImpl(fibonacciCalculator); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /beekeeper/src/main/java/io/servicecomb/company/beekeeper/BeekeeperController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.beekeeper; 18 | 19 | import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; 20 | import static org.springframework.web.bind.annotation.RequestMethod.GET; 21 | 22 | import io.servicecomb.provider.rest.common.RestSchema; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.stereotype.Controller; 27 | import org.springframework.web.bind.annotation.PathVariable; 28 | import org.springframework.web.bind.annotation.RequestMapping; 29 | import org.springframework.web.bind.annotation.ResponseBody; 30 | 31 | /** 32 | * Rest endpoint of bee ancestor counting service. Endpoints annotated with {@link RestSchema} and 33 | * their rest resources must be public or schema generation will fail. 34 | */ 35 | @RestSchema(schemaId = "beekeeperRestEndpoint") 36 | @RequestMapping("/rest") 37 | @Controller 38 | public class BeekeeperController { 39 | 40 | private static final Logger logger = LoggerFactory.getLogger(BeekeeperController.class); 41 | 42 | private final BeekeeperService beekeeperService; 43 | 44 | @Autowired 45 | BeekeeperController(BeekeeperService beekeeperService) { 46 | this.beekeeperService = beekeeperService; 47 | } 48 | 49 | /** 50 | * calculates the number of ancestors of a drone (male bee) at specified generation. 51 | * 52 | * @param generation the generation of bee ancestors at query 53 | * @return the number of ancestors 54 | */ 55 | @RequestMapping(value = "/drone/ancestors/{generation}", method = GET, produces = APPLICATION_JSON_VALUE) 56 | @ResponseBody 57 | public Ancestor ancestorsOfDrone(@PathVariable int generation) { 58 | logger.info( 59 | "Received request to find the number of ancestors of drone at generation {}", 60 | generation); 61 | 62 | return new Ancestor(beekeeperService.ancestorsOfDroneAt(generation)); 63 | } 64 | 65 | /** 66 | * calculates the number of ancestors of a queen (female bee) at specified generation. 67 | * 68 | * @param generation the generation of bee ancestors at query 69 | * @return the number of ancestors 70 | */ 71 | @RequestMapping(value = "/queen/ancestors/{generation}", method = GET, produces = APPLICATION_JSON_VALUE) 72 | @ResponseBody 73 | public Ancestor ancestorsOfQueen(@PathVariable int generation) { 74 | logger.info( 75 | "Received request to find the number of ancestors of queen at generation {}", 76 | generation); 77 | 78 | return new Ancestor(beekeeperService.ancestorsOfQueenAt(generation)); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /beekeeper/src/main/java/io/servicecomb/company/beekeeper/BeekeeperService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.beekeeper; 18 | 19 | interface BeekeeperService { 20 | 21 | /** 22 | * calculates the number of ancestors of a drone (male bee) at specified generation. 23 | * 24 | * @param generation the generation of bee ancestors at query 25 | * @return the number of ancestors 26 | * @see Drone Parent Numbers 27 | */ 28 | long ancestorsOfDroneAt(int generation); 29 | 30 | /** 31 | * calculates the number of ancestors of a queen (female bee) at specified generation. 32 | * 33 | * @param generation the generation of bee ancestors at query 34 | * @return the number of ancestors 35 | * @see Drone Parent Numbers 36 | */ 37 | long ancestorsOfQueenAt(int generation); 38 | } 39 | -------------------------------------------------------------------------------- /beekeeper/src/main/java/io/servicecomb/company/beekeeper/BeekeeperServiceImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.beekeeper; 18 | 19 | /** 20 | * Implements {@link BeekeeperService} to get fibonacci term from remote worker. 21 | */ 22 | class BeekeeperServiceImpl implements BeekeeperService { 23 | 24 | private final FibonacciCalculator fibonacciCalculator; 25 | 26 | BeekeeperServiceImpl(FibonacciCalculator fibonacciCalculator) { 27 | this.fibonacciCalculator = fibonacciCalculator; 28 | } 29 | 30 | /** 31 | * {@inheritDoc} 32 | */ 33 | @Override 34 | public long ancestorsOfDroneAt(int generation) { 35 | if (generation <= 0) { 36 | return 0; 37 | } 38 | return fibonacciCalculator.term(generation + 1); 39 | } 40 | 41 | /** 42 | * {@inheritDoc} 43 | */ 44 | @Override 45 | public long ancestorsOfQueenAt(int generation) { 46 | if (generation <= 0) { 47 | return 0; 48 | } 49 | // please refer to the link in javadoc for the reason of + 2 50 | return fibonacciCalculator.term(generation + 2); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /beekeeper/src/main/java/io/servicecomb/company/beekeeper/FibonacciCalculator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.beekeeper; 18 | 19 | public interface FibonacciCalculator { 20 | 21 | long term(int n); 22 | } 23 | -------------------------------------------------------------------------------- /beekeeper/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 0 3 | -------------------------------------------------------------------------------- /beekeeper/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /beekeeper/src/main/resources/microservice.yaml: -------------------------------------------------------------------------------- 1 | # all interconnected microservices must belong to an application wth the same ID 2 | APPLICATION_ID: company 3 | service_description: 4 | # name of the declaring microservice 5 | name: beekeeper 6 | version: 0.0.1 7 | cse: 8 | service: 9 | registry: 10 | address: http://sc.servicecomb.io:30100 11 | rest: 12 | address: 0.0.0.0:8090 13 | handler: 14 | chain: 15 | Consumer: 16 | default: tracing-consumer,bizkeeper-consumer,loadbalance 17 | Provider: 18 | default: tracing-provider,bizkeeper-provider 19 | 20 | servicecomb: 21 | tracing: 22 | collector: 23 | address: http://zipkin.io:9411 24 | 25 | references: 26 | # this one below must refer to the microservice name it communicates with 27 | worker: 28 | version-rule: 0.0.1 29 | -------------------------------------------------------------------------------- /beekeeper/src/test/java/io/servicecomb/company/beekeeper/BeekeeperControllerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.beekeeper; 18 | 19 | import static com.seanyinx.github.unit.scaffolding.Randomness.nextInt; 20 | import static com.seanyinx.github.unit.scaffolding.Randomness.nextLong; 21 | import static org.hamcrest.core.Is.is; 22 | import static org.mockito.Mockito.when; 23 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 24 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; 25 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 26 | 27 | import org.junit.Test; 28 | import org.junit.runner.RunWith; 29 | import org.springframework.beans.factory.annotation.Autowired; 30 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 31 | import org.springframework.boot.test.mock.mockito.MockBean; 32 | import org.springframework.test.context.ActiveProfiles; 33 | import org.springframework.test.context.junit4.SpringRunner; 34 | import org.springframework.test.web.servlet.MockMvc; 35 | 36 | @RunWith(SpringRunner.class) 37 | @WebMvcTest(BeekeeperController.class) 38 | @ActiveProfiles("dev") 39 | public class BeekeeperControllerTest { 40 | 41 | private final int generation = nextInt(90); 42 | private final long fibonacciValue = nextLong(); 43 | 44 | @Autowired 45 | private MockMvc mockMvc; 46 | @MockBean 47 | private BeekeeperService beekeeperService; 48 | 49 | @Test 50 | public void getsAncestorsOfDroneUsingUnderlyingService() throws Exception { 51 | when(beekeeperService.ancestorsOfDroneAt(generation)).thenReturn(fibonacciValue); 52 | 53 | mockMvc.perform(get("/rest/drone/ancestors/{generation}", generation)) 54 | .andExpect(status().isOk()) 55 | .andExpect(jsonPath("$.ancestors", is(fibonacciValue))); 56 | } 57 | 58 | @Test 59 | public void getsAncestorsOfQueenUsingUnderlyingService() throws Exception { 60 | when(beekeeperService.ancestorsOfQueenAt(generation)).thenReturn(fibonacciValue); 61 | 62 | mockMvc.perform(get("/rest/queen/ancestors/{generation}", generation)) 63 | .andExpect(status().isOk()) 64 | .andExpect(jsonPath("$.ancestors", is(fibonacciValue))); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /beekeeper/src/test/java/io/servicecomb/company/beekeeper/BeekeeperServiceImplTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.beekeeper; 18 | 19 | import static com.seanyinx.github.unit.scaffolding.Randomness.nextInt; 20 | import static com.seanyinx.github.unit.scaffolding.Randomness.nextLong; 21 | import static org.assertj.core.api.Assertions.assertThat; 22 | import static org.mockito.Matchers.anyInt; 23 | import static org.mockito.Mockito.mock; 24 | import static org.mockito.Mockito.when; 25 | 26 | import org.junit.Test; 27 | 28 | public class BeekeeperServiceImplTest { 29 | 30 | private final int generation = nextInt(90) + 1; 31 | private final long fibonacciValue = nextLong(); 32 | 33 | private final FibonacciCalculator fibonacciCalculator = mock(FibonacciCalculator.class); 34 | private final BeekeeperService beekeeperService = new BeekeeperServiceImpl(fibonacciCalculator); 35 | 36 | @Test 37 | public void calculatesAncestorsOfDroneAtGenerationN() { 38 | when(fibonacciCalculator.term(generation + 1)).thenReturn(fibonacciValue); 39 | 40 | long ancestors = beekeeperService.ancestorsOfDroneAt(generation); 41 | 42 | assertThat(ancestors).isEqualTo(fibonacciValue); 43 | } 44 | 45 | @Test 46 | public void calculatesAncestorsOfQueenAtGenerationN() { 47 | when(fibonacciCalculator.term(generation + 2)).thenReturn(fibonacciValue); 48 | 49 | long ancestors = beekeeperService.ancestorsOfQueenAt(generation); 50 | 51 | assertThat(ancestors).isEqualTo(fibonacciValue); 52 | } 53 | 54 | @Test 55 | public void ancestorsAtGeneration0Is0() { 56 | when(fibonacciCalculator.term(anyInt())).thenReturn(1L); 57 | 58 | assertThat(beekeeperService.ancestorsOfDroneAt(0)).isZero(); 59 | assertThat(beekeeperService.ancestorsOfQueenAt(0)).isZero(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /coverage-aggregate/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | company 23 | io.servicecomb.workshop.demo 24 | 0.3.0-SNAPSHOT 25 | 26 | 4.0.0 27 | 28 | coverage-aggregate 29 | 30 | 31 | 32 | io.servicecomb.workshop.demo 33 | doorman 34 | 35 | 36 | io.servicecomb.workshop.demo 37 | worker 38 | 39 | 40 | io.servicecomb.workshop.demo 41 | beekeeper 42 | 43 | 44 | io.servicecomb.workshop.demo 45 | manager 46 | 47 | 48 | io.servicecomb.workshop.demo 49 | worker-tests 50 | 0.3.0-SNAPSHOT 51 | 52 | 53 | io.servicecomb.workshop.demo 54 | beekeeper-tests 55 | 0.3.0-SNAPSHOT 56 | 57 | 58 | io.servicecomb.workshop.demo 59 | manager-tests 60 | 0.3.0-SNAPSHOT 61 | 62 | 63 | 64 | 65 | jacoco 66 | 67 | 68 | 69 | org.jacoco 70 | jacoco-maven-plugin 71 | 72 | 73 | post-integration-test 74 | 75 | report-aggregate 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /docker-build-config/assembly/assembly.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | installer 4 | 5 | tar.gz 6 | 7 | 8 | 9 | ${project.build.directory}/company 10 | company 11 | 0644 12 | 0755 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docker-build-config/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | company 23 | io.servicecomb.workshop.demo 24 | 0.3.0-SNAPSHOT 25 | 26 | 4.0.0 27 | 28 | docker-build-config 29 | pom 30 | 31 | 32 | 33 | 34 | 35 | io.fabric8 36 | docker-maven-plugin 37 | 38 | 39 | 40 | ${project.artifactId}:${project.version} 41 | ${project.artifactId} 42 | 43 | openjdk:8-jre-alpine 44 | 45 | 7070 46 | 8080 47 | 9090 48 | 49 | 50 | tar 51 | ${root.basedir}/docker-build-config/assembly/assembly.xml 52 | 53 | 54 | 55 | java $JAVA_OPTS -jar /maven/company/$ARTIFACT_ID-${project.version}-exec.jar 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | build 64 | package 65 | 66 | build 67 | 68 | 69 | 70 | 71 | 72 | org.commonjava.maven.plugins 73 | directory-maven-plugin 74 | 75 | 76 | directories 77 | 78 | highest-basedir 79 | 80 | initialize 81 | 82 | root.basedir 83 | 84 | 85 | 86 | 87 | 88 | org.springframework.boot 89 | spring-boot-maven-plugin 90 | 91 | 92 | 93 | repackage 94 | 95 | 96 | ${project.build.directory}/company 97 | exec 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | 3 | services: 4 | zipkin: 5 | image: "openzipkin/zipkin" 6 | hostname: zipkin 7 | ports: 8 | - "9411:9411" 9 | company-bulletin-board: 10 | image: "servicecomb/service-center" 11 | hostname: service-center 12 | ports: 13 | - "30100:30100" 14 | 15 | mysql: 16 | image: "mysql/mysql-server:5.7" 17 | hostname: mysql 18 | environment: 19 | - MYSQL_ROOT_PASSWORD=password 20 | - MYSQL_DATABASE=company 21 | - MYSQL_USER=company 22 | - MYSQL_PASSWORD=password 23 | ports: 24 | - "3306:3306" 25 | healthcheck: 26 | test: ["CMD-SHELL", "nc -z localhost 3306 &> /dev/null; echo $$?"] 27 | interval: 30s 28 | timeout: 10s 29 | retries: 5 30 | 31 | company-worker: 32 | image: "worker:0.3.0-SNAPSHOT" 33 | hostname: worker 34 | links: 35 | - "company-bulletin-board:sc.servicecomb.io" 36 | - "zipkin:zipkin.io" 37 | environment: 38 | - ARTIFACT_ID=worker 39 | ports: 40 | - "7070:7070" 41 | - "8080:8080" 42 | 43 | company-doorman: 44 | image: "doorman:0.3.0-SNAPSHOT" 45 | hostname: doorman 46 | links: 47 | - "company-bulletin-board:sc.servicecomb.io" 48 | - "mysql:mysql.servicecomb.io" 49 | - "zipkin:zipkin.io" 50 | environment: 51 | - JAVA_OPTS=-Dspring.profiles.active=prd 52 | - ARTIFACT_ID=doorman 53 | depends_on: 54 | mysql: 55 | condition: service_healthy 56 | ports: 57 | - "8081:8080" 58 | 59 | company-beekeeper: 60 | image: "beekeeper:0.3.0-SNAPSHOT" 61 | hostname: beekeeper 62 | links: 63 | - "company-bulletin-board:sc.servicecomb.io" 64 | - "zipkin:zipkin.io" 65 | - "company-worker" 66 | environment: 67 | - ARTIFACT_ID=beekeeper 68 | ports: 69 | - "8082:8090" 70 | 71 | company-manager: 72 | image: "manager:0.3.0-SNAPSHOT" 73 | hostname: manager 74 | links: 75 | - "company-bulletin-board:sc.servicecomb.io" 76 | - "zipkin:zipkin.io" 77 | environment: 78 | - JAVA_OPTS=-Dserver.port=8080 #-Dlogging.level.root=DEBUG 79 | - ARTIFACT_ID=manager 80 | ports: 81 | - "8083:8080" 82 | -------------------------------------------------------------------------------- /docs/how-to-auto-deploy-on-huawei-cloud-cn.md: -------------------------------------------------------------------------------- 1 | # 在华为云上自动部署微服务 2 | ## 背景 3 | 这个 company 的例子包含了4个服务(即部门经理、门卫、养蜂人和技工)。此外,我们还使用了 [zipkin](http://zipkin.io/) 来提供自动调用链追踪能力。因此,本指南将阐述在华为公有云上自动部署这5个服务的步骤,最终编排结构如图1所示。 4 | ![图1 编排结构](images/cluster_info.png) 5 | 图1 编排结构 6 | 7 | ## 导入编排模板 8 | 要导入编排模板,需要以下步骤: 9 | 1. 以*zip*或者*tar.gz*的格式对`scripts`目录下的`blueprint.yaml`的文件进行压缩 10 | 2. 访问Service Stage上的 [设计器](https://servicestage.hwclouds.com/servicestage/#/stage/doodle/new/topology) 11 | 3. 点击如图2所示的 *导入* 按钮 12 | 4. 点击如图2所示的 *选择本地模板* 13 | 5. 在弹出的文件框中选择步骤1中生成的压缩文件 14 | 6. 输入模板文件名, 如: company, 然后点击 *导入* 15 | ![图2 导入模板步骤](images/import_template_cn.png) 16 | 图2 导入模板步骤 17 | 现在在网页上应该能看到类似于图1所示的编排结构图了。 18 | 19 | ## 自动部署 20 | 在部署集群之前,可能需要对一些属性进行更改。部署的步骤为: 21 | 1. 更新集群名. 如果你的集群名称已经是 company 了,则可以跳过这一步。 22 | 如图3所示,首先你需要双击 *cluster-resource* 按钮,然后选取你的集群名。 23 | ![图3 选取集群](images/update_cluster_name_cn.png) 24 | 图3 选取集群 25 | 2. 更新镜像地址。如果你没有构建并发布镜像到镜像仓库,则可以跳过这一步,直接使用我们提供的公共镜像。 26 | (1) 访问 [华为镜像仓库](https://servicestage.hwclouds.com/servicestage/#/stage/softRepository/mirrorCenter/myMirrorPack), 然后选择 *company\_manager* 镜像,点击如图4所示 *复制地址* 按钮。 27 | ![图4 复制镜像地址](images/copy_image_address_cn.png) 28 | 图4 复制镜像地址 29 | (2) 如图5所示,首先你需要点击*输入输出*按钮,然后在输入参数名称一栏中找到*manager_image*并在该栏中点击*编辑*按钮,然后在默认值所在列粘贴步骤(1)中复制的镜像地址,并点击保存按钮。 30 | ![图5 更新镜像地址](images/update_image_address_cn.png) 31 | 图5 更新镜像地址 32 | 对*doorman\_image*, *beekeeper\_image*, *worker\_image*和*zipkin\_image*重复步骤(1)和步骤(2)来更新镜像地址。 33 | 3. 部署。如图6所示,点击*保存模板*和*部署*按钮。然后点击*创建*按钮。 34 | ![图6 保存并部署](images/save_and_deploy_cn.png) 35 | 图6 保存并部署 36 | 4. 访问 [堆栈](https://servicestage.hwclouds.com/servicestage/#/stage/stack/stacklist) 界面,检查堆栈运行状态。当集群颜色由蓝色变为绿色时,就说明集群已成功部署。然后就按图7所示进入经理服务详情页面,获取图8所示位置的服务地址,并通过项目首页中的[验证服务](https://github.com/ServiceComb/ServiceComb-Company-WorkShop#verify-services)一栏提供的方式去验证服务是否正常,同时也可以访问调用链跟踪服务,其运行于30411端口。 37 | ![图7 查看经理服务详情](images/view_manager_details_cn.png) 38 | 图7 查看经理服务详情 39 | ![图8 获取服务地址](images/get_host_address_cn.png) 40 | 图8 获取服务地址 41 | -------------------------------------------------------------------------------- /docs/how-to-auto-deploy-on-huawei-cloud.md: -------------------------------------------------------------------------------- 1 | # Auto deploy microservices on Huawei Cloud 2 | ## Background 3 | In this company demo, we have 4 services(manager, doorman, beekeeper, worker) and we use [zipkin](http://zipkin.io/) service to trace our handler chain. Hence, there should be 5 applications in this cluster as shown in the following figure(fig.1). 4 | ![fig.1 orchestration architecture](images/cluster_info.png) 5 | fig.1 orchestration architecture 6 | 7 | ## Import orchestration template 8 | To import the orchestration template, you need the following steps: 9 | 1. Compress the file `blueprint.yaml` under the `scripts` folder in either *zip* or *tar.gz* format. 10 | 2. Visit [Service Stage's doodle page](https://servicestage.hwclouds.com/servicestage/#/stage/doodle/new/topology). 11 | 3. Click the *Import* button shown in fig.2. 12 | 4. Click *Select a local template* shown in fig.2. 13 | 5. Select the compressed file in step 1. 14 | 6. Enter the template name, e.g. company, then click *Import*. 15 | ![fig.2 import template](images/import_template.png) 16 | fig.2 steps to import template 17 | Now you should be able to see the orchestration architecture similar to the architecture in fig.1. 18 | 19 | ## Auto Deploy 20 | Before you deploy your cluster, you may need to update some properties. 21 | 1. Update cluster name. You can skip this step if your cluster name is company. 22 | As shown in fig.3, first you need to double click the *cluster-resource* button, then choose the name 23 | of your cluster. 24 | ![fig.3 update cluster name](images/update_cluster_name.png) 25 | fig.3 update cluster name 26 | 2. Update images' url. If you did not build and publish your images to the image warehouse, you can skip this step and use the public images we provide in the image warehouse. 27 | (1) Visit [Huawei's Image Warehouse](https://servicestage.hwclouds.com/servicestage/#/stage/softRepository/mirrorCenter/myMirrorPack), then choose the *company\_manager* image. Click on the *copy address* button as shown in fig.4. 28 | ![fig.4 copy image address](images/copy_image_address.png) 29 | fig.4 copy image address 30 | (2) As shown in fig.5, first you need to click the *Input & Output* button, then click *Edit* on the line which name is *manager\_image*, then paste what we copy in step (1) and click the *Save* button. 31 | ![fig.5 update image address](images/update_image_address.png) 32 | fig.5 update image address 33 | Repeat step (1) and step (2) for the *doorman\_image*, *beekeeper\_image*, *worker\_image* and *zipkin\_image* options. 34 | 3. Deploy. As shown in fig.6, save the template and then click deploy. After that, enter the stack name and click *Create* button. 35 | ![fig.6 save and deploy](images/save_and_deploy.png) 36 | fig.6 save and deploy 37 | 4. Check the stack status by visiting the [Stack](https://servicestage.hwclouds.com/servicestage/#/stage/stack/stacklist) page. When your cluster turns green, it means that it's ready and you can click your cluster. After that, click as fig.7 shown, then get the host address from fig.8. Then you can [verify services](https://github.com/ServiceComb/ServiceComb-Company-WorkShop#verify-services) with that hosts and replace port with 30411 to visit the zipkin service. 38 | ![fig.7 view manager details](images/view_manager_details.png) 39 | fig.7 view manager details 40 | ![fig.8 get host address](images/get_host_address.png) 41 | fig.8 get host address 42 | -------------------------------------------------------------------------------- /docs/how-to-auto-publish-images-to-huawei-cloud-cn.md: -------------------------------------------------------------------------------- 1 | # 自动编译构建并发布镜像到华为镜像仓库 2 | 3 | ## 环境准备 4 | 1. Linux(推荐使用Ubuntu) 5 | 2. [Docker 1.11.2][docker_install_guide] 6 | 3. [Maven 3.x][maven] 7 | 4. [Oracle JDK 1.8+][jdk] 8 | 9 | ## 自动构建并发布镜像 10 | 1. 获取 workshop demo 的代码 11 | ```bash 12 | git clone https://github.com/ServiceComb/LinuxCon-Beijing-WorkShop.git 13 | ``` 14 | 2. 配置脚本 `scripts/publish_images_to_huaweicloud.sh` 中的环境变量 15 | 16 | 在你使用脚本前,你需要对以下变量进行更改: 17 | 18 | | 变量名称 | 描述 | 19 | | --------------- | ---------------- | 20 | | TENANT\_NAME | 在图1中的租户名 | 21 | | REPO\_ADDRESS | 在图1中的镜像仓库地址 | 22 | | USERNAME | 在图1中的用户名 | 23 | | PASSWORD | 在图1中的密码 | 24 | | PROJECT\_PATH | (可选) maven项目路径,默认为脚本执行路径的父目录 | 25 | | THIRD\_PARTY\_IMAGES | (可选) 可在[Docker Hub][docker_hub]上访问的第三方镜像,以空格分隔 | 26 | 27 | 图1可以通过以下步骤来获取: 28 | 29 | (1) 访问 [华为镜像仓库][image_warehouse] 30 | 31 | (2) 点击 *Pull/Push指南* 32 | 33 | (3) 点击 *生成docker login指令* 34 | 35 | ![图1. 变量信息][variables_information] 36 | 37 | 图1. 变量信息 38 | 39 | [variables_information]: images/variables_information_cn.png 40 | 3. 通过执行以下命令来运行脚本 41 | ```bash 42 | bash scripts/publish_images_to_huaweicloud.sh 43 | ``` 44 | 稍等片刻直至屏幕输出*Done*的信息,然后就可以在 [华为镜像仓库][image_warehouse] 中看到刚才上传的镜像了。 45 | 46 | [docker_install_guide]: how-to-install-docker-cn.md 47 | [maven]: https://maven.apache.org/install.html 48 | [jdk]: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 49 | [image_warehouse]: https://servicestage.hwclouds.com/servicestage/#/stage/softRepository/mirrorCenter/myMirrorPack 50 | [docker_hub]: https://hub.docker.com 51 | -------------------------------------------------------------------------------- /docs/how-to-auto-publish-images-to-huawei-cloud.md: -------------------------------------------------------------------------------- 1 | # Auto build and publish images to Huawei Image Warehouse 2 | 3 | ## Prerequisites 4 | 1. Linux(Ubuntu is recommended) 5 | 2. [Docker 1.11.2][docker_install_guide] 6 | 3. [Maven 3.x][maven] 7 | 4. [Oracle JDK 1.8+][jdk] 8 | 9 | ## Auto build and publish images 10 | 1. Get the workshop demo's code 11 | ```bash 12 | git clone https://github.com/ServiceComb/LinuxCon-Beijing-WorkShop.git 13 | ``` 14 | 2. Set up environment variables of `scripts/publish_images_to_huaweicloud.sh`. 15 | 16 | Before you use the script, there are several variables you need to set up first. 17 | 18 | | Name | Description | 19 | |-----------------|-----------------------------------------------------| 20 | | TENANT\_NAME | tenant name shown in fig.1 | 21 | | REPO\_ADDRESS | the image repository address shown in fig.1 | 22 | | USERNAME | username shown in fig.1 | 23 | | PASSWORD | password shown in fig.1 | 24 | | PROJECT\_PATH | (Optional) maven project path, default to script's parent path | 25 | | THIRD\_PARTY\_IMAGES | (Optional) third party images that published on [Docker Hub][docker_hub], separated by space | 26 | 27 | The following figure(fig.1) can be retrieved by visiting [Huawei Image Warehouse][image_warehouse], and then click the *Pull/Push Guide* -> *generate docker login instruction*. 28 | 29 | ![fig.1 variables information][variables_information] 30 | 31 | [variables_information]: images/variables_information.png 32 | 3. run the script by executing 33 | ```bash 34 | bash scripts/publish_images_to_huaweicloud.sh 35 | ``` 36 | Wait for a while and then you can check your images in the [Huawei Image Warehouse][image_warehouse]. 37 | 38 | [docker_install_guide]: how-to-install-docker.md 39 | [maven]: https://maven.apache.org/install.html 40 | [jdk]: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 41 | [image_warehouse]: https://servicestage.hwclouds.com/servicestage/#/stage/softRepository/mirrorCenter/myMirrorPack 42 | [docker_hub]: https://hub.docker.com 43 | -------------------------------------------------------------------------------- /docs/how-to-install-docker-cn.md: -------------------------------------------------------------------------------- 1 | # Docker 1.11.2 安装指南 2 | 3 | ## 环境准备 4 | * 64位Linux操作系统(推荐使用Ubuntu 14.04或以上版本) 5 | * Linux 内核 >= 3.10 6 | 7 | ## 安装指南 8 | ### Ubuntu 9 | 1. 卸载系统中已安装的docker 10 | ```bash 11 | sudo apt-get remove docker docker-engine docker.io docker-ce 12 | sudo mv /var/lib/docker /var/lib/docker-old 13 | ``` 14 | 2. 安装docker依赖的软件 15 | ```bash 16 | sudo apt-get update 17 | sudo apt-get install apt-transport-https ca-certificates 18 | ``` 19 | 3. 添加docker官方的GPG密钥 20 | ```bash 21 | sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D 22 | ``` 23 | 4. 添加docker官方的镜像源 24 | ```bash 25 | echo "deb https://apt.dockerproject.org/repo ubuntu-$(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/docker.list 26 | sudo apt-get update 27 | ``` 28 | 5. 安装docker 29 | ```bash 30 | sudo apt-get install docker-engine=1.11.2-0~$(lsb_release -cs) 31 | ``` 32 | 6. 将用户添加至docker用户组 33 | ```bash 34 | sudo usermod -aG docker $USER 35 | ``` 36 | 7. 添加华为镜像仓库配置 37 | ```bash 38 | echo DOCKER_OPTS="--insecure-registry registry.cn-north-1.hwclouds.com" | sudo tee -a /etc/default/docker 39 | ``` 40 | 8. 重启docker 41 | * Ubuntu 16.04或以上 42 | ``` 43 | sudo systemctl restart docker 44 | ``` 45 | * Ubuntu 14.04或以下 46 | ``` 47 | sudo service docker restart 48 | ``` 49 | 50 | ### 其它Linux发行版 51 | 1. 确保你没有安装docker,如果系统中安装了docker,请先卸载。 52 | 2. 下载并解压docker压缩包。 53 | ```bash 54 | wget https://get.docker.com/builds/Linux/x86_64/docker-1.11.2.tgz /tmp 55 | cd /tmp; tar xvf docker-1.11.2.tgz 56 | ``` 57 | 3. 将docker可执行文件移至系统可执行文件目录 58 | ```bash 59 | sudo mv docker/* /usr/bin 60 | ``` 61 | 4. 创建docker运行目录 62 | ```bash 63 | sudo mkdir /var/lib/docker 64 | ``` 65 | 5. 运行docker后台进程 66 | ```bash 67 | sudo docker daemon --insecure-registry=registry.cn-north-1.hwclouds.com 68 | ``` 69 | 70 | docker的安装已完成,现在可以使用docker了。 -------------------------------------------------------------------------------- /docs/how-to-install-docker.md: -------------------------------------------------------------------------------- 1 | # Docker 1.11.2 Installation Guide 2 | 3 | ## Prerequisites 4 | * 64 bit Linux OS(Ubuntu 14.04 or above is recommended) 5 | * Linux kernel >= 3.10 6 | 7 | ## Installation Guide 8 | ### Ubuntu 9 | 1. Uninstall docker 10 | ```bash 11 | sudo apt-get remove docker docker-engine docker.io docker-ce 12 | sudo mv /var/lib/docker /var/lib/docker-old 13 | ``` 14 | 2. Update package information and install necessary packages 15 | ```bash 16 | sudo apt-get update 17 | sudo apt-get install apt-transport-https ca-certificates 18 | ``` 19 | 3. Add docker's official GPG key 20 | ```bash 21 | sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D 22 | ``` 23 | 4. Add docker's mirror source 24 | ```bash 25 | echo "deb https://apt.dockerproject.org/repo ubuntu-$(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/docker.list 26 | sudo apt-get update 27 | ``` 28 | 5. Install docker 29 | ```bash 30 | sudo apt-get install docker-engine=1.11.2-0~$(lsb_release -cs) 31 | ``` 32 | 6. Add user to docker group 33 | ```bash 34 | sudo usermod -aG docker $USER 35 | ``` 36 | 7. Add Huawei's image repository 37 | ```bash 38 | echo DOCKER_OPTS="--insecure-registry registry.cn-north-1.hwclouds.com" | sudo tee -a /etc/default/docker 39 | ``` 40 | 8. Restart docker 41 | * Ubuntu 16.04 or above 42 | ``` 43 | sudo systemctl restart docker 44 | ``` 45 | * Ubuntu 14.04 or below 46 | ``` 47 | sudo service docker restart 48 | ``` 49 | 50 | ### Other Linux distribution 51 | 1. Make sure you don't have docker installed. If you do, remove it first. 52 | 2. Download and extract docker archive files 53 | ```bash 54 | wget https://get.docker.com/builds/Linux/x86_64/docker-1.11.2.tgz /tmp 55 | cd /tmp; tar xvf docker-1.11.2.tgz 56 | ``` 57 | 3. Move docker executable files to system executable path 58 | ```bash 59 | sudo mv docker/* /usr/bin 60 | ``` 61 | 4. Create docker directory 62 | ```bash 63 | sudo mkdir /var/lib/docker 64 | ``` 65 | 5. Run the docker daemon 66 | ```bash 67 | sudo docker daemon --insecure-registry=registry.cn-north-1.hwclouds.com 68 | ``` 69 | 70 | The installation of docker has finished. You are free to use `docker` now. 71 | -------------------------------------------------------------------------------- /docs/images/cluster_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/cluster_info.png -------------------------------------------------------------------------------- /docs/images/copy_image_address.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/copy_image_address.png -------------------------------------------------------------------------------- /docs/images/copy_image_address_cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/copy_image_address_cn.png -------------------------------------------------------------------------------- /docs/images/get_host_address.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/get_host_address.png -------------------------------------------------------------------------------- /docs/images/get_host_address_cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/get_host_address_cn.png -------------------------------------------------------------------------------- /docs/images/import_template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/import_template.png -------------------------------------------------------------------------------- /docs/images/import_template_cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/import_template_cn.png -------------------------------------------------------------------------------- /docs/images/save_and_deploy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/save_and_deploy.png -------------------------------------------------------------------------------- /docs/images/save_and_deploy_cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/save_and_deploy_cn.png -------------------------------------------------------------------------------- /docs/images/update_cluster_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/update_cluster_name.png -------------------------------------------------------------------------------- /docs/images/update_cluster_name_cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/update_cluster_name_cn.png -------------------------------------------------------------------------------- /docs/images/update_image_address.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/update_image_address.png -------------------------------------------------------------------------------- /docs/images/update_image_address_cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/update_image_address_cn.png -------------------------------------------------------------------------------- /docs/images/variables_information.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/variables_information.png -------------------------------------------------------------------------------- /docs/images/variables_information_cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/variables_information_cn.png -------------------------------------------------------------------------------- /docs/images/view_manager_details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/view_manager_details.png -------------------------------------------------------------------------------- /docs/images/view_manager_details_cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huaweicse/ServiceComb-Company-WorkShop/7bbf74a40b59fb0c2c63ae74e99a860357aa5d2a/docs/images/view_manager_details_cn.png -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/DoormanApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company; 17 | 18 | import io.servicecomb.springboot.starter.provider.EnableServiceComb; 19 | import org.springframework.boot.SpringApplication; 20 | import org.springframework.boot.autoconfigure.SpringBootApplication; 21 | import org.springframework.context.annotation.Configuration; 22 | import org.springframework.context.annotation.Profile; 23 | 24 | @SpringBootApplication 25 | public class DoormanApplication { 26 | 27 | public static void main(String[] args) { 28 | SpringApplication.run(DoormanApplication.class, args); 29 | } 30 | 31 | // do not enable service registration/discovery and schema generation/registration 32 | // unless the active profile is not dev 33 | @EnableServiceComb 34 | @Profile("!dev") 35 | @Configuration 36 | static class ServiceCombConfig { 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/AuthenticationConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.auth; 17 | 18 | import io.servicecomb.company.auth.domain.UserRepository; 19 | import org.springframework.beans.factory.annotation.Value; 20 | import org.springframework.context.annotation.Bean; 21 | import org.springframework.context.annotation.Configuration; 22 | 23 | @Configuration 24 | class AuthenticationConfig { 25 | 26 | private static final int SECONDS_OF_A_DAY = 24 * 60 * 60; 27 | 28 | @Bean 29 | AuthenticationService authenticationService( 30 | TokenStore tokenStore, 31 | UserRepository repository) { 32 | 33 | return new AuthenticationServiceImpl(tokenStore, repository); 34 | } 35 | 36 | @Bean 37 | TokenStore tokenStore(@Value("${company.auth.secret:someSecretKey}") String secretKey) { 38 | return new JwtTokenStore(secretKey, SECONDS_OF_A_DAY); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/AuthenticationService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.auth; 17 | 18 | public interface AuthenticationService { 19 | String authenticate(String username, String password); 20 | 21 | String validate(String token); 22 | } 23 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/AuthenticationServiceImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.auth; 17 | 18 | import io.servicecomb.company.auth.domain.User; 19 | import io.servicecomb.company.auth.domain.UserRepository; 20 | 21 | class AuthenticationServiceImpl implements AuthenticationService { 22 | 23 | private final TokenStore tokenStore; 24 | private final UserRepository userRepository; 25 | 26 | AuthenticationServiceImpl( 27 | TokenStore tokenStore, 28 | UserRepository userRepository) { 29 | this.tokenStore = tokenStore; 30 | this.userRepository = userRepository; 31 | } 32 | 33 | @Override 34 | public String authenticate(String username, String password) { 35 | User user = userRepository.findByUsernameAndPassword(username, password); 36 | 37 | if (user == null) { 38 | throw new UnauthorizedAccessException("No user matches username " + username + " and password"); 39 | } 40 | 41 | return tokenStore.generate(username); 42 | } 43 | 44 | @Override 45 | public String validate(String token) { 46 | try { 47 | return tokenStore.parse(token); 48 | } catch (TokenException e) { 49 | throw new UnauthorizedAccessException("No user matches such a token " + token, e); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/JwtTokenStore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.auth; 17 | 18 | import static io.jsonwebtoken.SignatureAlgorithm.HS512; 19 | 20 | import io.jsonwebtoken.JwtException; 21 | import io.jsonwebtoken.Jwts; 22 | import java.time.ZonedDateTime; 23 | import java.util.Date; 24 | 25 | /** 26 | * {@link JwtTokenStore} implements {@link TokenStore} with JWT token specifications. 27 | */ 28 | class JwtTokenStore implements TokenStore { 29 | 30 | private final String secretKey; 31 | private final int secondsToExpire; 32 | 33 | /** 34 | * Constructor 35 | * @param secretKey the signing key to encrypt the token. 36 | * @param secondsToExpire the expire time in seconds. 37 | */ 38 | JwtTokenStore(String secretKey, int secondsToExpire) { 39 | this.secretKey = secretKey; 40 | this.secondsToExpire = secondsToExpire; 41 | } 42 | 43 | @Override 44 | public String generate(String username) { 45 | return Jwts.builder() 46 | .setSubject(username) 47 | .setExpiration(Date.from(ZonedDateTime.now().plusSeconds(secondsToExpire).toInstant())) 48 | .signWith(HS512, secretKey) 49 | .compact(); 50 | } 51 | 52 | @Override 53 | public String parse(String token) { 54 | try { 55 | return Jwts.parser() 56 | .setSigningKey(secretKey) 57 | .parseClaimsJws(token) 58 | .getBody() 59 | .getSubject(); 60 | } catch (JwtException | IllegalArgumentException e) { 61 | throw new TokenException(e); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/TokenException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.auth; 17 | 18 | public class TokenException extends RuntimeException { 19 | 20 | public TokenException(Throwable throwable) { 21 | super(throwable); 22 | } 23 | 24 | public TokenException() { 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/TokenStore.java: -------------------------------------------------------------------------------- 1 | package io.servicecomb.company.auth;/* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * {@link TokenStore} is a general interface responsible for token generation and parsing. 19 | */ 20 | public interface TokenStore { 21 | 22 | /** 23 | * Generates a token embedded with the username provided. 24 | * @param username the username of requested user. 25 | * @return the generated token. 26 | */ 27 | String generate(String username); 28 | 29 | /** 30 | * Parses a token if valid. 31 | * Throws {@link TokenException} if the provided is not genuine. 32 | * @param token the token. 33 | * @return the username embedded in the token. 34 | */ 35 | String parse(String token); 36 | } 37 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/UnauthorizedAccessException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.auth; 17 | 18 | public class UnauthorizedAccessException extends RuntimeException { 19 | 20 | public UnauthorizedAccessException(String message) { 21 | super(message); 22 | } 23 | 24 | public UnauthorizedAccessException(String message, Throwable e) { 25 | super(message, e); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/domain/User.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.auth.domain; 18 | 19 | import java.util.Date; 20 | import javax.persistence.Entity; 21 | import javax.persistence.Id; 22 | 23 | @Entity(name = "user_entity") 24 | public class User { 25 | 26 | @Id 27 | private long id; 28 | private String username; 29 | private String password; 30 | private Date lastAccessedTime; 31 | 32 | User() { 33 | } 34 | 35 | public User(String username) { 36 | this.username = username; 37 | this.lastAccessedTime = new Date(); 38 | } 39 | 40 | public String getUsername() { 41 | return username; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/domain/UserRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.auth.domain; 18 | 19 | import org.springframework.data.repository.CrudRepository; 20 | 21 | public interface UserRepository extends CrudRepository { 22 | User findByUsernameAndPassword(String username, String password); 23 | } 24 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/endpoint/rest/AuthenticationController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.auth.endpoint.rest; 17 | 18 | import static org.springframework.http.HttpStatus.OK; 19 | import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE; 20 | import static org.springframework.http.MediaType.TEXT_PLAIN_VALUE; 21 | import static org.springframework.web.bind.annotation.RequestMethod.POST; 22 | 23 | import io.servicecomb.company.auth.AuthenticationService; 24 | import io.servicecomb.provider.rest.common.RestSchema; 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | import org.springframework.http.HttpHeaders; 29 | import org.springframework.http.ResponseEntity; 30 | import org.springframework.stereotype.Controller; 31 | import org.springframework.web.bind.annotation.RequestBody; 32 | import org.springframework.web.bind.annotation.RequestMapping; 33 | import org.springframework.web.bind.annotation.RequestParam; 34 | import org.springframework.web.bind.annotation.ResponseBody; 35 | 36 | @RestSchema(schemaId = "authenticationRestEndpoint") 37 | @Controller 38 | @RequestMapping("/rest") 39 | public class AuthenticationController { 40 | 41 | private static final Logger logger = LoggerFactory.getLogger(AuthenticationController.class); 42 | 43 | static final String USERNAME = "username"; 44 | static final String PASSWORD = "password"; 45 | 46 | private final AuthenticationService authenticationService; 47 | private final AuthorizationHeaderGenerator authorizationHeaderGenerator; 48 | 49 | @Autowired 50 | AuthenticationController( 51 | AuthenticationService authenticationService, 52 | AuthorizationHeaderGenerator authorizationHeaderGenerator) { 53 | this.authenticationService = authenticationService; 54 | this.authorizationHeaderGenerator = authorizationHeaderGenerator; 55 | } 56 | 57 | @RequestMapping(value = "/login", method = POST, produces = TEXT_PLAIN_VALUE) 58 | public ResponseEntity login( 59 | @RequestParam(USERNAME) String username, 60 | @RequestParam(PASSWORD) String password) { 61 | 62 | logger.info("Received login request from user {}", username); 63 | String token = authenticationService.authenticate(username, password); 64 | HttpHeaders headers = authorizationHeaderGenerator.generate(token); 65 | 66 | logger.info("Authenticated user {} successfully", username); 67 | return new ResponseEntity<>("Welcome, " + username, headers, OK); 68 | } 69 | 70 | @RequestMapping(value = "/validate", method = POST, consumes = APPLICATION_JSON_UTF8_VALUE, produces = TEXT_PLAIN_VALUE) 71 | @ResponseBody 72 | public String validate(@RequestBody Token token) { 73 | logger.info("Received validation request of token {}", token); 74 | return authenticationService.validate(token.getToken()); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/endpoint/rest/AuthenticationExceptionHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.auth.endpoint.rest; 17 | 18 | import static org.springframework.http.HttpStatus.FORBIDDEN; 19 | 20 | import io.servicecomb.company.auth.UnauthorizedAccessException; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.springframework.http.ResponseEntity; 24 | import org.springframework.web.bind.annotation.ControllerAdvice; 25 | import org.springframework.web.bind.annotation.ExceptionHandler; 26 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 27 | 28 | /** 29 | * {@link AuthenticationExceptionHandler} intercepts response with {@link 30 | * UnauthorizedAccessException} and wraps the exception message in a forbidden response. 31 | */ 32 | @ControllerAdvice 33 | class AuthenticationExceptionHandler extends ResponseEntityExceptionHandler { 34 | 35 | private static final Logger logger = LoggerFactory.getLogger(AuthenticationExceptionHandler.class); 36 | 37 | @ExceptionHandler(UnauthorizedAccessException.class) 38 | ResponseEntity handleException(UnauthorizedAccessException e) { 39 | logger.warn("Authentication failure", e); 40 | return new ResponseEntity<>(e.getMessage(), FORBIDDEN); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/endpoint/rest/AuthorizationHeaderGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.auth.endpoint.rest; 18 | 19 | import static org.springframework.http.HttpHeaders.AUTHORIZATION; 20 | 21 | import org.springframework.http.HttpHeaders; 22 | import org.springframework.stereotype.Component; 23 | 24 | @Component 25 | class AuthorizationHeaderGenerator { 26 | 27 | static final String TOKEN_PREFIX = "Bearer "; 28 | 29 | HttpHeaders generate(String token) { 30 | HttpHeaders headers = new HttpHeaders(); 31 | headers.add(AUTHORIZATION, TOKEN_PREFIX + token); 32 | return headers; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /doorman/src/main/java/io/servicecomb/company/auth/endpoint/rest/Token.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.auth.endpoint.rest; 18 | 19 | class Token { 20 | private String token; 21 | 22 | Token() { 23 | } 24 | 25 | Token(String token) { 26 | this.token = token; 27 | } 28 | 29 | public String getToken() { 30 | return token; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "Token{" + 36 | "token='" + token + '\'' + 37 | '}'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /doorman/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 0 3 | 4 | spring: 5 | profiles: prd 6 | datasource: 7 | username: company 8 | password: password 9 | driver-class-name: com.mysql.jdbc.Driver 10 | url: jdbc:mysql://mysql.servicecomb.io:3306/company?useSSL=false 11 | platform: mysql 12 | continue-on-error: true 13 | jpa: 14 | properties: 15 | hibernate: 16 | dialect: org.hibernate.dialect.MySQL5Dialect 17 | hibernate: 18 | ddl-auto: none 19 | -------------------------------------------------------------------------------- /doorman/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /doorman/src/main/resources/microservice.yaml: -------------------------------------------------------------------------------- 1 | # all interconnected microservices must belong to an application wth the same ID 2 | APPLICATION_ID: company 3 | service_description: 4 | # name of the declaring microservice 5 | name: doorman 6 | version: 0.0.1 7 | cse: 8 | service: 9 | registry: 10 | address: http://sc.servicecomb.io:30100 11 | rest: 12 | address: 0.0.0.0:8080 13 | handler: 14 | chain: 15 | Provider: 16 | default: tracing-provider,bizkeeper-provider 17 | 18 | servicecomb: 19 | tracing: 20 | collector: 21 | address: http://zipkin.io:9411 22 | -------------------------------------------------------------------------------- /doorman/src/main/resources/schema-mysql.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS user_entity ( 2 | id BIGINT NOT NULL AUTO_INCREMENT, 3 | username VARCHAR(8) NOT NULL UNIQUE, 4 | password VARCHAR(16) NOT NULL, 5 | last_accessed_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, 6 | PRIMARY KEY (`id`) 7 | ); 8 | 9 | insert ignore into user_entity(username, password) values('jordan', 'password'); 10 | -------------------------------------------------------------------------------- /doorman/src/test/java/io/servicecomb/company/auth/AuthenticationServiceImplTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.auth; 17 | 18 | import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing; 19 | import static com.seanyinx.github.unit.scaffolding.Randomness.uniquify; 20 | import static org.assertj.core.api.Assertions.assertThat; 21 | import static org.mockito.Mockito.mock; 22 | import static org.mockito.Mockito.when; 23 | 24 | import io.servicecomb.company.auth.domain.User; 25 | import io.servicecomb.company.auth.domain.UserRepository; 26 | import org.junit.Test; 27 | 28 | public class AuthenticationServiceImplTest { 29 | 30 | private final String username = uniquify("username"); 31 | private final String password = uniquify("password"); 32 | private final User user = new User(username); 33 | 34 | private final TokenStore tokenStore = mock(TokenStore.class); 35 | private final UserRepository userRepository = mock(UserRepository.class); 36 | 37 | private final AuthenticationService authenticationService = new AuthenticationServiceImpl( 38 | tokenStore, userRepository); 39 | private String token = uniquify("token"); 40 | 41 | @Test 42 | public void authenticateUserWithUsernameAndPassword() { 43 | when(userRepository.findByUsernameAndPassword(username, password)).thenReturn(user); 44 | when(tokenStore.generate(username)).thenReturn(token); 45 | 46 | String token = authenticationService.authenticate(username, password); 47 | 48 | assertThat(token).isEqualTo(this.token); 49 | } 50 | 51 | @Test 52 | public void blowsUpWhenUserIsInvalid() { 53 | try { 54 | authenticationService.authenticate(username, password); 55 | expectFailing(UnauthorizedAccessException.class); 56 | } catch (UnauthorizedAccessException e) { 57 | assertThat(e.getMessage()).isEqualTo("No user matches username " + username + " and password"); 58 | } 59 | } 60 | 61 | @Test 62 | public void validatesUserToken() { 63 | when(tokenStore.parse(token)).thenReturn(username); 64 | 65 | String user = authenticationService.validate(token); 66 | 67 | assertThat(user).isEqualTo(username); 68 | } 69 | 70 | @Test 71 | public void blowsUpWhenTokenMatchesNoUser() { 72 | when(tokenStore.parse(token)).thenThrow(new TokenException()); 73 | 74 | try { 75 | authenticationService.validate(token); 76 | expectFailing(UnauthorizedAccessException.class); 77 | } catch (UnauthorizedAccessException e) { 78 | assertThat(e.getMessage()).isEqualTo("No user matches such a token " + token); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /doorman/src/test/java/io/servicecomb/company/auth/JwtTokenStoreTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.auth; 17 | 18 | import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing; 19 | import static com.seanyinx.github.unit.scaffolding.Randomness.uniquify; 20 | import static org.assertj.core.api.Assertions.assertThat; 21 | 22 | import java.util.concurrent.TimeUnit; 23 | import org.junit.Test; 24 | 25 | public class JwtTokenStoreTest { 26 | 27 | private final String secretKey = uniquify("SecretKey"); 28 | private final String someUser = uniquify("User"); 29 | private TokenStore tokenStore; 30 | 31 | @Test 32 | public void generatesTokenOfSomeUser() { 33 | tokenStore = new JwtTokenStore(secretKey, 10); 34 | 35 | String token = tokenStore.generate(someUser); 36 | assertThat(token).isNotEmpty(); 37 | 38 | String user = tokenStore.parse(token); 39 | assertThat(user).isEqualTo(someUser); 40 | } 41 | 42 | @Test 43 | public void blowsUpWhenTokenExpired() throws InterruptedException { 44 | tokenStore = new JwtTokenStore(secretKey, 1); 45 | 46 | String token = tokenStore.generate(someUser); 47 | TimeUnit.MILLISECONDS.sleep(1002); 48 | 49 | try { 50 | tokenStore.parse(token); 51 | expectFailing(TokenException.class); 52 | } catch (TokenException ignored) { 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /doorman/src/test/java/io/servicecomb/company/auth/endpoint/rest/AuthenticationContractTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.auth.endpoint.rest; 17 | 18 | import static org.mockito.Mockito.mock; 19 | import static org.mockito.Mockito.when; 20 | 21 | import au.com.dius.pact.provider.junit.PactRunner; 22 | import au.com.dius.pact.provider.junit.Provider; 23 | import au.com.dius.pact.provider.junit.State; 24 | import au.com.dius.pact.provider.junit.loader.PactFolder; 25 | import au.com.dius.pact.provider.junit.target.HttpTarget; 26 | import au.com.dius.pact.provider.junit.target.Target; 27 | import au.com.dius.pact.provider.junit.target.TestTarget; 28 | import io.servicecomb.company.auth.AuthenticationService; 29 | import io.servicecomb.company.auth.UnauthorizedAccessException; 30 | import org.junit.AfterClass; 31 | import org.junit.BeforeClass; 32 | import org.junit.runner.RunWith; 33 | import org.springframework.boot.SpringApplication; 34 | import org.springframework.boot.autoconfigure.SpringBootApplication; 35 | import org.springframework.context.ConfigurableApplicationContext; 36 | import org.springframework.context.annotation.Bean; 37 | 38 | @RunWith(PactRunner.class) 39 | @PactFolder("../target/pacts") 40 | @Provider("Doorman") 41 | public class AuthenticationContractTest { 42 | 43 | private static ConfigurableApplicationContext doormanContext; 44 | private static AuthenticationService authenticationService; 45 | 46 | @TestTarget 47 | public final Target target = new HttpTarget(8081); 48 | 49 | @BeforeClass 50 | public static void startCustomerService() { 51 | doormanContext = SpringApplication 52 | .run(DoormanRestApplication.class, "--server.port=8081", "--spring.profiles.active=dev", "--spring.main.web-environment=true"); 53 | 54 | authenticationService = doormanContext.getBean(AuthenticationService.class); 55 | } 56 | 57 | @AfterClass 58 | public static void tearDown() throws Exception { 59 | doormanContext.close(); 60 | } 61 | 62 | @State("User Sean is authorized") 63 | public void acceptAuthenticatedUser() { 64 | when(authenticationService.validate("sean-token")).thenReturn("Sean"); 65 | } 66 | 67 | @State("User Jack is unauthorized") 68 | public void rejectUnknownUser() { 69 | when(authenticationService.validate("unknown-token")) 70 | .thenThrow(new UnauthorizedAccessException("No user matches such a token unknown-token")); 71 | } 72 | 73 | @SpringBootApplication 74 | static class DoormanRestApplication { 75 | 76 | public static void main(String[] args) { 77 | SpringApplication.run(DoormanRestApplication.class, args); 78 | } 79 | 80 | @Bean 81 | AuthenticationService authenticationService() { 82 | return mock(AuthenticationService.class); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /doorman/src/test/java/io/servicecomb/company/auth/endpoint/rest/AuthenticationControllerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.auth.endpoint.rest; 17 | 18 | import static com.seanyinx.github.unit.scaffolding.Randomness.uniquify; 19 | import static io.servicecomb.company.auth.endpoint.rest.AuthenticationController.PASSWORD; 20 | import static io.servicecomb.company.auth.endpoint.rest.AuthenticationController.USERNAME; 21 | import static org.mockito.Mockito.when; 22 | import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED; 23 | import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE; 24 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 25 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 26 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 27 | 28 | import com.fasterxml.jackson.databind.ObjectMapper; 29 | import io.servicecomb.company.auth.AuthenticationService; 30 | import org.junit.Before; 31 | import org.junit.Test; 32 | import org.junit.runner.RunWith; 33 | import org.springframework.beans.factory.annotation.Autowired; 34 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 35 | import org.springframework.boot.test.mock.mockito.MockBean; 36 | import org.springframework.http.HttpHeaders; 37 | import org.springframework.test.context.junit4.SpringRunner; 38 | import org.springframework.test.web.servlet.MockMvc; 39 | 40 | @RunWith(SpringRunner.class) 41 | @WebMvcTest(AuthenticationController.class) 42 | public class AuthenticationControllerTest { 43 | 44 | @Autowired 45 | private MockMvc mockMvc; 46 | 47 | @MockBean 48 | private AuthenticationService authenticationService; 49 | 50 | @MockBean 51 | private AuthorizationHeaderGenerator headerGenerator; 52 | 53 | private final String password = uniquify("password"); 54 | private final String username = uniquify("username"); 55 | private final String token = uniquify("token"); 56 | private final ObjectMapper objectMapper = new ObjectMapper(); 57 | 58 | @Before 59 | public void setUp() throws Exception { 60 | when(headerGenerator.generate(token)).thenReturn(new HttpHeaders()); 61 | } 62 | 63 | @Test 64 | public void returnsTokenOfAuthenticatedUser() throws Exception { 65 | when(authenticationService.authenticate(username, password)).thenReturn(token); 66 | 67 | mockMvc.perform( 68 | post("/rest/login") 69 | .contentType(APPLICATION_FORM_URLENCODED) 70 | .param(USERNAME, username) 71 | .param(PASSWORD, password)) 72 | .andExpect(status().isOk()) 73 | .andExpect(content().string("Welcome, " + username)); 74 | } 75 | 76 | @Test 77 | public void validatesTokenAgainstStoredUserSessions() throws Exception { 78 | when(authenticationService.validate(token)).thenReturn(username); 79 | 80 | mockMvc.perform( 81 | post("/rest/validate") 82 | .contentType(APPLICATION_JSON_UTF8_VALUE) 83 | .content(objectMapper.writeValueAsBytes(new Token(token)))) 84 | .andExpect(status().isOk()) 85 | .andExpect(content().string(username)); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /doorman/src/test/resources/data.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS user_entity; 2 | 3 | CREATE TABLE user_entity ( 4 | id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1, INCREMENT BY 1) PRIMARY KEY, 5 | username VARCHAR(8) NOT NULL UNIQUE, 6 | password VARCHAR(16) NOT NULL, 7 | last_accessed_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, 8 | ); 9 | 10 | insert into user_entity(username, password) values('jordan', 'password'); 11 | -------------------------------------------------------------------------------- /etc/log/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | ../logs 21 | server.log 22 | /var/paas/cse/trace/company 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 39 | 40 | 41 | 42 | 43 | 44 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 60 | 61 | 62 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /etc/microservice/beekeeper.yaml: -------------------------------------------------------------------------------- 1 | # all interconnected microservices must belong to an application wth the same ID 2 | APPLICATION_ID: company 3 | service_description: 4 | # name of the declaring microservice 5 | name: beekeeper 6 | version: 0.0.1 7 | cse: 8 | service: 9 | registry: 10 | address: https://100.125.1.34:30100 11 | rest: 12 | address: 0.0.0.0:8002 13 | monitor: 14 | client: 15 | serverUri: https://100.125.1.34:30109 16 | handler: 17 | chain: 18 | Provider: 19 | default: tracing-provider-apm,kpi-provider-apm,bizkeeper-provider,perf-stats 20 | Consumer: 21 | default: loadbalance,tracing-consumer-apm,kpi-consumer-apm,bizkeeper-consumer,perf-stats 22 | config: 23 | client: 24 | serverUri: https://100.125.1.34:30103 25 | 26 | servicecomb: 27 | tracing: 28 | collector: 29 | address: http://zipkin:30411 30 | 31 | references: 32 | # this one below must refer to the microservice name it communicates with 33 | worker: 34 | version-rule: 0.0.1 35 | -------------------------------------------------------------------------------- /etc/microservice/doorman.yaml: -------------------------------------------------------------------------------- 1 | # all interconnected microservices must belong to an application wth the same ID 2 | APPLICATION_ID: company 3 | service_description: 4 | # name of the declaring microservice 5 | name: doorman 6 | version: 0.0.1 7 | cse: 8 | service: 9 | registry: 10 | address: https://100.125.1.34:30100 11 | rest: 12 | address: 0.0.0.0:8003 13 | monitor: 14 | client: 15 | serverUri: https://100.125.1.34:30109 16 | handler: 17 | chain: 18 | Provider: 19 | default: tracing-provider-apm,kpi-provider-apm,bizkeeper-provider,perf-stats,qps-flowcontrol-provider 20 | Consumer: 21 | default: loadbalance,tracing-consumer-apm,kpi-consumer-apm,bizkeeper-consumer,perf-stats,qps-flowcontrol-consumer 22 | config: 23 | client: 24 | serverUri: https://100.125.1.34:30103 25 | servicecomb: 26 | tracing: 27 | collector: 28 | address: http://zipkin:30411 -------------------------------------------------------------------------------- /etc/microservice/manager.yaml: -------------------------------------------------------------------------------- 1 | # all interconnected microservices must belong to an application wth the same ID 2 | APPLICATION_ID: company 3 | service_description: 4 | # name of the declaring microservice 5 | name: manager 6 | version: 0.0.1 7 | cse: 8 | service: 9 | registry: 10 | address: https://100.125.1.34:30100 11 | isolation: 12 | doorman: 13 | timeoutInMilliseconds: 30000 14 | beekeeper: 15 | timeoutInMilliseconds: 30000 16 | worker: 17 | timeoutInMilliseconds: 30000 18 | monitor: 19 | client: 20 | serverUri: https://100.125.1.34:30109 21 | handler: 22 | chain: 23 | Provider: 24 | default: bizkeeper-provider,perf-stats,qps-flowcontrol-provider 25 | Consumer: 26 | default: loadbalance,bizkeeper-consumer,perf-stats,qps-flowcontrol-consumer 27 | config: 28 | client: 29 | serverUri: https://100.125.1.34:30103 30 | servicecomb: 31 | tracing: 32 | collector: 33 | address: http://zipkin:30411 34 | 35 | -------------------------------------------------------------------------------- /etc/microservice/worker.yaml: -------------------------------------------------------------------------------- 1 | # all interconnected microservices must belong to an application wth the same ID 2 | APPLICATION_ID: company 3 | service_description: 4 | # name of the declaring microservice 5 | name: worker 6 | version: 0.0.1 7 | cse: 8 | service: 9 | registry: 10 | address: https://100.125.1.34:30100 11 | highway: 12 | address: 0.0.0.0:6001?sslEnable=false 13 | rest: 14 | address: 0.0.0.0:7001?sslEnable=false 15 | monitor: 16 | client: 17 | serverUri: https://100.125.1.34:30109 18 | handler: 19 | chain: 20 | Provider: 21 | default: tracing-provider-apm,kpi-provider-apm,bizkeeper-provider,perf-stats 22 | Consumer: 23 | default: loadbalance,tracing-consumer-apm,kpi-consumer-apm,bizkeeper-consumer,perf-stats 24 | config: 25 | client: 26 | serverUri: https://100.125.1.34:30103 27 | servicecomb: 28 | tracing: 29 | collector: 30 | address: http://zipkin:30411 -------------------------------------------------------------------------------- /integration-tests/beekeeper-tests/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | integration-tests 23 | io.servicecomb.workshop.demo 24 | 0.3.0-SNAPSHOT 25 | 26 | 4.0.0 27 | 28 | beekeeper-tests 29 | 30 | 31 | 32 | io.servicecomb.workshop.demo 33 | beekeeper 34 | 35 | 36 | io.servicecomb 37 | spring-boot-starter-provider 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter 42 | 43 | 44 | commons-logging 45 | commongs-logging 46 | 47 | 48 | ch.qos.logback 49 | logback-classic 50 | 51 | 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-starter-web 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-test 61 | test 62 | 63 | 64 | com.github.seanyinx 65 | unit-scaffolding 66 | test 67 | 68 | 69 | 70 | 71 | 72 | 74 | 75 | com.github.odavid.maven.plugins 76 | mixin-maven-plugin 77 | 78 | 79 | 80 | io.servicecomb.workshop.demo 81 | docker-run-config 82 | 0.3.0-SNAPSHOT 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | docker 93 | 94 | worker 95 | 96 | 97 | 98 | 99 | 100 | io.fabric8 101 | docker-maven-plugin 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /integration-tests/beekeeper-tests/src/test/java/io/servicecomb/company/beekeeper/BeekeeperApplicationIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.beekeeper; 18 | 19 | import static org.assertj.core.api.Assertions.assertThat; 20 | import static org.springframework.http.HttpStatus.OK; 21 | 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.springframework.boot.test.context.SpringBootTest; 25 | import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; 26 | import org.springframework.http.ResponseEntity; 27 | import org.springframework.test.context.junit4.SpringRunner; 28 | import org.springframework.web.client.RestTemplate; 29 | 30 | @RunWith(SpringRunner.class) 31 | @SpringBootTest( 32 | classes = BeekeeperApplication.class, 33 | webEnvironment = WebEnvironment.RANDOM_PORT, 34 | properties = { 35 | }) 36 | public class BeekeeperApplicationIT { 37 | 38 | private final RestTemplate restTemplate = new RestTemplate(); 39 | 40 | private final String serviceAddress = "http://localhost:8090"; 41 | 42 | @Test 43 | public void getsAncestorsOfDroneAtGenerationN() { 44 | ResponseEntity responseEntity = restTemplate.getForEntity( 45 | serviceAddress + "/rest/drone/ancestors/{generation}", 46 | Ancestor.class, 47 | 2); 48 | 49 | assertThat(responseEntity.getStatusCode()).isEqualTo(OK); 50 | assertThat(responseEntity.getBody().getAncestors()).isEqualTo(2L); 51 | } 52 | 53 | @Test 54 | public void getsAncestorsOfQueenAtGenerationN() { 55 | ResponseEntity responseEntity = restTemplate.getForEntity( 56 | serviceAddress + "/rest/queen/ancestors/{generation}", 57 | Ancestor.class, 58 | 2); 59 | 60 | assertThat(responseEntity.getStatusCode()).isEqualTo(OK); 61 | assertThat(responseEntity.getBody().getAncestors()).isEqualTo(3L); 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /integration-tests/manager-tests/src/test/java/io/servicecomb/company/manager/ManagerApplicationIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.manager; 18 | 19 | import static org.assertj.core.api.Assertions.assertThat; 20 | import static org.springframework.http.HttpHeaders.AUTHORIZATION; 21 | import static org.springframework.http.HttpStatus.NOT_FOUND; 22 | import static org.springframework.http.HttpStatus.OK; 23 | 24 | import org.junit.Test; 25 | import org.junit.runner.RunWith; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.boot.test.context.SpringBootTest; 28 | import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; 29 | import org.springframework.boot.test.web.client.TestRestTemplate; 30 | import org.springframework.http.HttpEntity; 31 | import org.springframework.http.HttpHeaders; 32 | import org.springframework.http.HttpMethod; 33 | import org.springframework.http.MediaType; 34 | import org.springframework.http.ResponseEntity; 35 | import org.springframework.test.context.ActiveProfiles; 36 | import org.springframework.test.context.junit4.SpringRunner; 37 | import org.springframework.util.LinkedMultiValueMap; 38 | import org.springframework.util.MultiValueMap; 39 | 40 | @RunWith(SpringRunner.class) 41 | @SpringBootTest( 42 | classes = ManagerApplication.class, 43 | webEnvironment = WebEnvironment.RANDOM_PORT, 44 | properties = { 45 | }) 46 | @ActiveProfiles("sit") 47 | public class ManagerApplicationIT { 48 | 49 | @Autowired 50 | private TestRestTemplate restTemplate; 51 | 52 | @Test 53 | public void loginAndValidateWithRemoteDoorman() { 54 | ResponseEntity responseEntity = restTemplate.exchange( 55 | "/doorman/rest/login", 56 | HttpMethod.POST, 57 | loginRequest(), 58 | String.class); 59 | 60 | assertThat(responseEntity.getStatusCode()).isEqualTo(OK); 61 | assertThat(responseEntity.getBody()).isEqualTo("Welcome, jordan"); 62 | 63 | responseEntity = restTemplate.exchange( 64 | "/doorman/path/not/exist", 65 | HttpMethod.GET, 66 | validationRequest(authorization(responseEntity)), 67 | String.class); 68 | 69 | assertThat(responseEntity.getStatusCode()).isEqualTo(NOT_FOUND); 70 | } 71 | 72 | private String authorization(ResponseEntity responseEntity) { 73 | return responseEntity.getHeaders().get(AUTHORIZATION).get(0); 74 | } 75 | 76 | private HttpEntity> loginRequest() { 77 | HttpHeaders headers = new HttpHeaders(); 78 | headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); 79 | 80 | MultiValueMap map = new LinkedMultiValueMap<>(); 81 | map.add("username", "jordan"); 82 | map.add("password", "password"); 83 | 84 | return new HttpEntity<>(map, headers); 85 | } 86 | 87 | private HttpEntity validationRequest(String authorization) { 88 | HttpHeaders headers = new HttpHeaders(); 89 | headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); 90 | headers.add(AUTHORIZATION, authorization); 91 | 92 | return new HttpEntity<>(headers); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /integration-tests/worker-tests/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | integration-tests 23 | io.servicecomb.workshop.demo 24 | 0.3.0-SNAPSHOT 25 | 26 | 4.0.0 27 | 28 | worker-tests 29 | 30 | 31 | 32 | io.servicecomb 33 | spring-boot-starter-provider 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter 38 | 39 | 40 | commons-logging 41 | commongs-logging 42 | 43 | 44 | ch.qos.logback 45 | logback-classic 46 | 47 | 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-starter-web 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-starter-test 57 | test 58 | 59 | 60 | com.github.seanyinx 61 | unit-scaffolding 62 | test 63 | 64 | 65 | 66 | 67 | 68 | 70 | 71 | com.github.odavid.maven.plugins 72 | mixin-maven-plugin 73 | 74 | 75 | 76 | io.servicecomb.workshop.demo 77 | docker-run-config 78 | 0.3.0-SNAPSHOT 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | docker 89 | 90 | worker 91 | 92 | 93 | 94 | 95 | 96 | io.fabric8 97 | docker-maven-plugin 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /integration-tests/worker-tests/src/test/java/io/servicecomb/company/worker/FibonacciProvider.java: -------------------------------------------------------------------------------- 1 | package io.servicecomb.company.worker;/* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | public interface FibonacciProvider { 18 | 19 | long term(int n); 20 | } 21 | -------------------------------------------------------------------------------- /integration-tests/worker-tests/src/test/java/io/servicecomb/company/worker/WorkerApplicationIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.worker; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import io.servicecomb.provider.pojo.RpcReference; 21 | import io.servicecomb.springboot.starter.provider.EnableServiceComb; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.beans.factory.annotation.Value; 26 | import org.springframework.boot.SpringApplication; 27 | import org.springframework.boot.autoconfigure.SpringBootApplication; 28 | import org.springframework.boot.test.context.SpringBootTest; 29 | import org.springframework.context.annotation.Bean; 30 | import org.springframework.http.HttpStatus; 31 | import org.springframework.http.ResponseEntity; 32 | import org.springframework.test.context.junit4.SpringRunner; 33 | import org.springframework.web.client.RestTemplate; 34 | 35 | @RunWith(SpringRunner.class) 36 | @SpringBootTest 37 | public class WorkerApplicationIT { 38 | 39 | @Autowired 40 | private FibonacciProvider fibonacciProvider; 41 | 42 | @Value("${service.address}") 43 | private String serviceAddress; 44 | 45 | private final long fibonacciValue = 12586269025L; 46 | private final RestTemplate restTemplate = new RestTemplate(); 47 | 48 | @Test 49 | public void getsNthTermOfFibonacci() { 50 | long fibo = fibonacciProvider.term(50); 51 | 52 | assertThat(fibo).isEqualTo(fibonacciValue); 53 | } 54 | 55 | @Test 56 | public void getsNthTermOfFibonacciByRest() { 57 | ResponseEntity responseEntity = restTemplate.getForEntity( 58 | serviceAddress + "/fibonacci/term?n=50", 59 | long.class); 60 | 61 | assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); 62 | assertThat(responseEntity.getBody()).isEqualTo(fibonacciValue); 63 | } 64 | 65 | @SpringBootApplication 66 | @EnableServiceComb 67 | static class WorkerTestApplication { 68 | // this annotation does not take effect in spring test 69 | @RpcReference(microserviceName = "worker", schemaId = "fibonacciRpcEndpoint") 70 | private FibonacciProvider fibonacciProvider; 71 | 72 | public static void main(String[] args) { 73 | SpringApplication.run(WorkerTestApplication.class, args); 74 | } 75 | 76 | @Bean 77 | FibonacciProvider fibonacciProvider() { 78 | return fibonacciProvider; 79 | } 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /integration-tests/worker-tests/src/test/resources/application.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 0 3 | -------------------------------------------------------------------------------- /integration-tests/worker-tests/src/test/resources/microservice.yaml: -------------------------------------------------------------------------------- 1 | # all interconnected microservices must belong to an application wth the same ID 2 | APPLICATION_ID: company 3 | service_description: 4 | # name of the declaring microservice 5 | name: fibonacciClient 6 | version: 0.0.1 7 | cse: 8 | service: 9 | registry: 10 | address: http://sc.servicecomb.io:30100 11 | handler: 12 | chain: 13 | Consumer: 14 | default: bizkeeper-consumer,loadbalance 15 | references: 16 | # this one below must refer to the microservice name it communicates with 17 | worker: 18 | version-rule: 0.0.1 19 | -------------------------------------------------------------------------------- /kubernetes/README.md: -------------------------------------------------------------------------------- 1 | # Run Company on Kubernetes Cluster 2 | These scripts show you how to run Company on kubernetes cluster. 3 | 4 | ## Before you begin 5 | 6 | Scripts are tested with kubernetes 1.7+ and docker 17.06.0-ce 7 | 8 | ## Start up 9 | ``` 10 | git clone https://github.com/ServiceComb/ServiceComb-Company-WorkShop.git 11 | cd ServiceComb-Company-WorkShop/kubernetes/ 12 | bash start.sh 13 | ``` 14 | ## Visit company service 15 | 16 | * **Visit Inside the cluster** 17 | ``` 18 | # get CLUSTER-IP and TARGET-PORT with api gateway 19 | kubectl get svc |grep company-manager 20 | 21 | # export HOST variable 22 | export HOST=":" 23 | 24 | # verify login and retrive token from Authorization section 25 | curl -v -H "Content-Type: application/x-www-form-urlencoded" -d "username=jordan&password=password" -XPOST "http://$HOST/doorman/rest/login" 26 | ``` 27 | ***Reference to [Verify services](../README.md) to get more to visit company service*** 28 | 29 | * **Visit outside the cluster** 30 | 31 | Modified the HOST variable to use EXTERNAL-IP and NODE-PORT 32 | ``` 33 | # get EXTERNAL-IP and NODE-PORT with api gateway 34 | kubectl get svc company-manager -o yaml | grep ExternalIP -C 1 35 | kubectl get svc company-manager -o yaml | grep nodePort -C 1 36 | 37 | # export HOST variable 38 | export HOST=":" 39 | ``` 40 | ***Notes:*** 41 | *If no free external-ip can be reserved by kubernetes, try to use the public-ip with the node.* 42 | ``` 43 | # get NODE-NAME of the node which api gateway is runing on 44 | kubectl get po -owide |grep company-manager 45 | # get PUBLIC-IP which of the node 46 | kubectl describe node |grep public-ip 47 | # set HOST variable 48 | export HOST=":" 49 | ``` 50 | 51 | ## Clean up 52 | ``` 53 | bash cleanup.sh 54 | ``` 55 | -------------------------------------------------------------------------------- /kubernetes/cleanup-autoscale.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2017 Huawei Technologies Co., Ltd 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | kubectl delete hpa zipkin 17 | kubectl delete hpa company-bulletin-board 18 | kubectl delete hpa company-worker 19 | kubectl delete hpa company-doorman 20 | kubectl delete hpa company-beekeeper 21 | kubectl delete hpa company-manager 22 | 23 | CLEANUP_SCRIPT=$(cd $(dirname $0); pwd)/cleanup.sh 24 | bash $CLEANUP_SCRIPT 25 | -------------------------------------------------------------------------------- /kubernetes/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2017 Huawei Technologies Co., Ltd 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | kubectl delete -f zipkin-service.yaml 17 | kubectl delete -f zipkin-deployment.yaml 18 | 19 | kubectl delete -f mysql-service.yaml 20 | kubectl delete -f mysql-deployment.yaml 21 | 22 | kubectl delete -f company-bulletin-board-service.yaml 23 | kubectl delete -f company-bulletin-board-deployment.yaml 24 | 25 | #kubectl delete -f company-worker-service.yaml 26 | kubectl delete -f company-worker-deployment.yaml 27 | #kubectl delete -f company-doorman-service.yaml 28 | kubectl delete -f company-doorman-deployment.yaml 29 | #kubectl delete -f company-beekeeper-service.yaml 30 | kubectl delete -f company-beekeeper-deployment.yaml 31 | 32 | kubectl delete -f company-manager-service.yaml 33 | kubectl delete -f company-manager-deployment.yaml 34 | -------------------------------------------------------------------------------- /kubernetes/company-beekeeper-deployment.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Huawei Technologies Co., Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: extensions/v1beta1 16 | kind: Deployment 17 | metadata: 18 | creationTimestamp: null 19 | labels: 20 | io.kompose.service: company-beekeeper 21 | name: company-beekeeper 22 | spec: 23 | replicas: 1 24 | strategy: {} 25 | template: 26 | metadata: 27 | creationTimestamp: null 28 | labels: 29 | io.kompose.service: company-beekeeper 30 | spec: 31 | containers: 32 | - env: 33 | - name: ARTIFACT_ID 34 | value: beekeeper 35 | - name: JAVA_OPTS 36 | value: -Dcse.service.registry.address=http://company-bulletin-board:30100 -Dservicecomb.tracing.collector.adress=http://zipkin:9411 37 | image: servicecomb/beekeeper:0.0.1-SNAPSHOT 38 | name: company-beekeeper 39 | ports: 40 | - containerPort: 8090 41 | resources: 42 | requests: 43 | cpu: 200m 44 | restartPolicy: Always 45 | status: {} 46 | -------------------------------------------------------------------------------- /kubernetes/company-bulletin-board-deployment.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Huawei Technologies Co., Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: extensions/v1beta1 16 | kind: Deployment 17 | metadata: 18 | creationTimestamp: null 19 | labels: 20 | io.kompose.service: company-bulletin-board 21 | name: company-bulletin-board 22 | spec: 23 | replicas: 1 24 | strategy: {} 25 | template: 26 | metadata: 27 | creationTimestamp: null 28 | labels: 29 | io.kompose.service: company-bulletin-board 30 | spec: 31 | containers: 32 | - image: servicecomb/service-center 33 | name: company-bulletin-board 34 | ports: 35 | - containerPort: 30100 36 | resources: 37 | requests: 38 | cpu: 200m 39 | restartPolicy: Always 40 | status: {} 41 | -------------------------------------------------------------------------------- /kubernetes/company-bulletin-board-service.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Huawei Technologies Co., Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: v1 16 | kind: Service 17 | metadata: 18 | creationTimestamp: null 19 | labels: 20 | io.kompose.service: company-bulletin-board 21 | name: company-bulletin-board 22 | spec: 23 | ports: 24 | - name: "30100" 25 | port: 30100 26 | targetPort: 30100 27 | selector: 28 | io.kompose.service: company-bulletin-board 29 | status: 30 | loadBalancer: {} 31 | -------------------------------------------------------------------------------- /kubernetes/company-doorman-deployment.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Huawei Technologies Co., Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: extensions/v1beta1 16 | kind: Deployment 17 | metadata: 18 | creationTimestamp: null 19 | labels: 20 | io.kompose.service: company-doorman 21 | name: company-doorman 22 | spec: 23 | replicas: 1 24 | strategy: {} 25 | template: 26 | metadata: 27 | creationTimestamp: null 28 | labels: 29 | io.kompose.service: company-doorman 30 | spec: 31 | containers: 32 | - env: 33 | - name: ARTIFACT_ID 34 | value: doorman 35 | - name: JAVA_OPTS 36 | value: -Dcse.service.registry.address=http://company-bulletin-board:30100 -Dservicecomb.tracing.collector.adress=http://zipkin:9411 -Dspring.profiles.active=prd -Dspring.datasource.url=jdbc:mysql://company-mysql:3306/company 37 | image: servicecomb/doorman:0.0.1-SNAPSHOT 38 | name: company-doorman 39 | ports: 40 | - containerPort: 8080 41 | resources: 42 | requests: 43 | cpu: 200m 44 | restartPolicy: Always 45 | status: {} 46 | -------------------------------------------------------------------------------- /kubernetes/company-manager-deployment.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Huawei Technologies Co., Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: extensions/v1beta1 16 | kind: Deployment 17 | metadata: 18 | creationTimestamp: null 19 | labels: 20 | io.kompose.service: company-manager 21 | name: company-manager 22 | spec: 23 | replicas: 1 24 | strategy: {} 25 | template: 26 | metadata: 27 | creationTimestamp: null 28 | labels: 29 | io.kompose.service: company-manager 30 | spec: 31 | containers: 32 | - env: 33 | - name: ARTIFACT_ID 34 | value: manager 35 | - name: JAVA_OPTS 36 | value: -Dserver.port=8080 -Dcse.service.registry.address=http://company-bulletin-board:30100 -Dservicecomb.tracing.collector.adress=http://zipkin:9411 37 | image: servicecomb/manager:0.0.1-SNAPSHOT 38 | name: company-manager 39 | ports: 40 | - containerPort: 8080 41 | resources: 42 | requests: 43 | cpu: 200m 44 | restartPolicy: Always 45 | status: {} 46 | -------------------------------------------------------------------------------- /kubernetes/company-manager-service.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Huawei Technologies Co., Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: v1 16 | kind: Service 17 | metadata: 18 | creationTimestamp: null 19 | labels: 20 | io.kompose.service: company-manager 21 | name: company-manager 22 | spec: 23 | ports: 24 | - name: "8083" 25 | port: 8083 26 | targetPort: 8080 27 | nodePort: 30301 28 | protocol: TCP 29 | type: NodePort 30 | selector: 31 | io.kompose.service: company-manager 32 | status: 33 | loadBalancer: {} 34 | -------------------------------------------------------------------------------- /kubernetes/company-worker-deployment.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Huawei Technologies Co., Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: extensions/v1beta1 16 | kind: Deployment 17 | metadata: 18 | creationTimestamp: null 19 | labels: 20 | io.kompose.service: company-worker 21 | name: company-worker 22 | spec: 23 | replicas: 1 24 | strategy: {} 25 | template: 26 | metadata: 27 | creationTimestamp: null 28 | labels: 29 | io.kompose.service: company-worker 30 | spec: 31 | containers: 32 | - env: 33 | - name: ARTIFACT_ID 34 | value: worker 35 | - name: JAVA_OPTS 36 | value: -Dcse.service.registry.address=http://company-bulletin-board:30100 -Dservicecomb.tracing.collector.adress=http://zipkin:9411 37 | image: servicecomb/worker:0.0.1-SNAPSHOT 38 | name: company-worker 39 | ports: 40 | - containerPort: 7070 41 | - containerPort: 8080 42 | resources: 43 | requests: 44 | cpu: 200m 45 | restartPolicy: Always 46 | status: {} 47 | -------------------------------------------------------------------------------- /kubernetes/mysql-deployment.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Huawei Technologies Co., Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: extensions/v1beta1 16 | kind: Deployment 17 | metadata: 18 | creationTimestamp: null 19 | labels: 20 | io.kompose.service: company-mysql 21 | name: company-mysql 22 | spec: 23 | replicas: 1 24 | strategy: {} 25 | template: 26 | metadata: 27 | creationTimestamp: null 28 | labels: 29 | io.kompose.service: company-mysql 30 | spec: 31 | containers: 32 | - image: mysql/mysql-server:5.7 33 | name: company-mysql 34 | env: 35 | - name: MYSQL_ROOT_PASSWORD 36 | value: "password" 37 | - name: MYSQL_DATABASE 38 | value: "company" 39 | - name: MYSQL_USER 40 | value: "company" 41 | - name: MYSQL_PASSWORD 42 | value: "password" 43 | ports: 44 | - containerPort: 3306 45 | resources: 46 | requests: 47 | cpu: 200m 48 | restartPolicy: Always 49 | status: {} 50 | -------------------------------------------------------------------------------- /kubernetes/mysql-service.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Huawei Technologies Co., Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: v1 16 | kind: Service 17 | metadata: 18 | creationTimestamp: null 19 | labels: 20 | io.kompose.service: company-mysql 21 | name: company-mysql 22 | spec: 23 | ports: 24 | - name: "3306" 25 | port: 3306 26 | targetPort: 3306 27 | selector: 28 | io.kompose.service: company-mysql 29 | status: 30 | loadBalancer: {} 31 | -------------------------------------------------------------------------------- /kubernetes/start-autoscale.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2017 Huawei Technologies Co., Ltd 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | START_SCRIPT=$(cd $(dirname $0); pwd)/start.sh 18 | bash $START_SCRIPT 19 | 20 | #Create Horizontal Pod Autoscaler 21 | kubectl autoscale deployment zipkin --cpu-percent=50 --min=1 --max=10 22 | kubectl autoscale deployment company-bulletin-board --cpu-percent=50 --min=1 --max=10 23 | kubectl autoscale deployment company-worker --cpu-percent=50 --min=1 --max=10 24 | kubectl autoscale deployment company-doorman --cpu-percent=50 --min=1 --max=10 25 | kubectl autoscale deployment company-manager --cpu-percent=50 --min=1 --max=10 26 | kubectl autoscale deployment company-beekeeper --cpu-percent=50 --min=1 --max=10 27 | -------------------------------------------------------------------------------- /kubernetes/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2017 Huawei Technologies Co., Ltd 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | kubectl expose -f zipkin-service.yaml 17 | kubectl create -f zipkin-deployment.yaml 18 | 19 | kubectl expose -f mysql-service.yaml 20 | kubectl create -f mysql-deployment.yaml 21 | 22 | kubectl expose -f company-bulletin-board-service.yaml 23 | kubectl create -f company-bulletin-board-deployment.yaml 24 | 25 | #kubectl create -f company-worker-service.yaml 26 | kubectl create -f company-worker-deployment.yaml 27 | #kubectl create -f company-doorman-service.yaml 28 | kubectl create -f company-doorman-deployment.yaml 29 | #kubectl create -f company-beekeeper-service.yaml 30 | kubectl create -f company-beekeeper-deployment.yaml 31 | 32 | kubectl create -f company-manager-service.yaml 33 | kubectl create -f company-manager-deployment.yaml 34 | -------------------------------------------------------------------------------- /kubernetes/zipkin-deployment.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Huawei Technologies Co., Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: extensions/v1beta1 16 | kind: Deployment 17 | metadata: 18 | creationTimestamp: null 19 | labels: 20 | io.kompose.service: zipkin 21 | name: zipkin 22 | spec: 23 | replicas: 1 24 | strategy: {} 25 | template: 26 | metadata: 27 | creationTimestamp: null 28 | labels: 29 | io.kompose.service: zipkin 30 | spec: 31 | containers: 32 | - image: openzipkin/zipkin 33 | name: zipkin 34 | ports: 35 | - containerPort: 9411 36 | resources: 37 | requests: 38 | cpu: 200m 39 | restartPolicy: Always 40 | status: {} 41 | -------------------------------------------------------------------------------- /kubernetes/zipkin-service.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Huawei Technologies Co., Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: v1 16 | kind: Service 17 | metadata: 18 | creationTimestamp: null 19 | labels: 20 | io.kompose.service: zipkin 21 | name: zipkin 22 | spec: 23 | ports: 24 | - name: "9411" 25 | port: 9411 26 | targetPort: 9411 27 | selector: 28 | io.kompose.service: zipkin 29 | status: 30 | loadBalancer: {} 31 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/AuthenticationService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager; 17 | 18 | import static org.springframework.http.HttpStatus.REQUEST_TIMEOUT; 19 | 20 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 21 | import java.io.IOException; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.http.HttpEntity; 26 | import org.springframework.http.HttpHeaders; 27 | import org.springframework.http.MediaType; 28 | import org.springframework.http.ResponseEntity; 29 | import org.springframework.http.client.ClientHttpResponse; 30 | import org.springframework.stereotype.Service; 31 | import org.springframework.web.client.ResponseErrorHandler; 32 | import org.springframework.web.client.RestTemplate; 33 | 34 | /** 35 | * {@link AuthenticationService} validates user requests by sending the token in request header to 36 | * remote doorman for authentication. 37 | */ 38 | @Service 39 | public class AuthenticationService { 40 | 41 | private static final Logger logger = LoggerFactory.getLogger(AuthenticationService.class); 42 | private static final String DOORMAN_ADDRESS = "cse://doorman"; 43 | 44 | private final RestTemplate restTemplate; 45 | 46 | @Autowired 47 | AuthenticationService(RestTemplate restTemplate) { 48 | this.restTemplate = restTemplate; 49 | 50 | this.restTemplate.setErrorHandler(new ResponseErrorHandler() { 51 | @Override 52 | public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException { 53 | return false; 54 | } 55 | 56 | @Override 57 | public void handleError(ClientHttpResponse clientHttpResponse) throws IOException { 58 | } 59 | }); 60 | } 61 | 62 | @HystrixCommand(fallbackMethod = "timeout") 63 | public ResponseEntity validate(String token) { 64 | logger.info("Validating token {}", token); 65 | ResponseEntity responseEntity = restTemplate.postForEntity( 66 | DOORMAN_ADDRESS + "/rest/validate", 67 | validationRequest(token), 68 | String.class 69 | ); 70 | 71 | if (!responseEntity.getStatusCode().is2xxSuccessful()) { 72 | logger.warn("No such user found with token {}", token); 73 | } 74 | logger.info("Validated request of token {} to be user {}", token, responseEntity.getBody()); 75 | return responseEntity; 76 | } 77 | 78 | private ResponseEntity timeout(String token) { 79 | logger.warn("Request to validate token {} timed out", token); 80 | return new ResponseEntity<>(REQUEST_TIMEOUT); 81 | } 82 | 83 | private HttpEntity validationRequest(String token) { 84 | HttpHeaders headers = new HttpHeaders(); 85 | headers.setContentType(MediaType.APPLICATION_JSON_UTF8); 86 | 87 | return new HttpEntity<>(new Token(token), headers); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/ManagerApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager; 17 | 18 | import io.servicecomb.springboot.starter.provider.EnableServiceComb; 19 | import org.springframework.boot.SpringApplication; 20 | import org.springframework.boot.autoconfigure.SpringBootApplication; 21 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 22 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 23 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 24 | import org.springframework.context.annotation.Configuration; 25 | import org.springframework.context.annotation.Profile; 26 | 27 | @SpringBootApplication 28 | @EnableCircuitBreaker 29 | @EnableZuulProxy 30 | public class ManagerApplication { 31 | 32 | public static void main(String[] args) { 33 | SpringApplication.run(ManagerApplication.class, args); 34 | } 35 | 36 | // do not enable service registration/discovery and schema generation/registration 37 | // unless the active profile is not dev 38 | @EnableServiceComb 39 | @EnableDiscoveryClient 40 | @Profile("!dev") 41 | @Configuration 42 | static class ServiceCombConfig { 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/RestTemplateConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.manager; 18 | 19 | import io.servicecomb.provider.springmvc.reference.RestTemplateBuilder; 20 | import org.springframework.context.annotation.Bean; 21 | import org.springframework.context.annotation.Configuration; 22 | import org.springframework.context.annotation.Profile; 23 | import org.springframework.web.client.RestTemplate; 24 | 25 | @Configuration 26 | @Profile("!dev") 27 | class RestTemplateConfig { 28 | @Bean 29 | RestTemplate restTemplate() { 30 | return RestTemplateBuilder.create(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/Token.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.manager; 18 | 19 | class Token { 20 | private String token; 21 | 22 | Token(String token) { 23 | this.token = token; 24 | } 25 | 26 | public String getToken() { 27 | return token; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return "Token{" + 33 | "token='" + token + '\'' + 34 | '}'; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/archive/Archive.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager.archive; 17 | 18 | public interface Archive { 19 | 20 | V get(); 21 | 22 | boolean exists(); 23 | } 24 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/archive/HitArchive.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager.archive; 17 | 18 | /** 19 | * Represents cache hit of a cache entry. 20 | * 21 | * @param the value of the cache entry 22 | */ 23 | class HitArchive implements Archive { 24 | 25 | private final V value; 26 | 27 | HitArchive(V value) { 28 | this.value = value; 29 | } 30 | 31 | @Override 32 | public V get() { 33 | return value; 34 | } 35 | 36 | @Override 37 | public boolean exists() { 38 | return true; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/archive/MissArchive.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager.archive; 17 | 18 | import java.util.NoSuchElementException; 19 | 20 | /** 21 | * Represents cache miss of a cache entry. 22 | * 23 | * @param value of the cache entry 24 | */ 25 | class MissArchive implements Archive { 26 | 27 | private final String term; 28 | 29 | MissArchive(String term) { 30 | this.term = term; 31 | } 32 | 33 | @Override 34 | public V get() { 35 | throw new NoSuchElementException("No result found for search term " + term); 36 | } 37 | 38 | @Override 39 | public boolean exists() { 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/archive/ProjectArchive.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager.archive; 17 | 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | import org.springframework.cache.annotation.CacheConfig; 21 | import org.springframework.cache.annotation.CachePut; 22 | import org.springframework.cache.annotation.Cacheable; 23 | 24 | /** 25 | * A generic project archive to cache user requests. 26 | * 27 | * @param key of cache entry 28 | * @param value of cache entry 29 | */ 30 | @CacheConfig(cacheNames = "projectArchive") 31 | public class ProjectArchive { 32 | private static final Logger logger = LoggerFactory.getLogger(ProjectArchive.class); 33 | 34 | /** 35 | * Search the cache for matching result of provided key. This method will not be executed unless 36 | * there is no such key in the cache. In this case, {@link MissArchive} will always be returned to 37 | * indicate a cache miss. Otherwise, {@link HitArchive} will be retrieved from the cache using 38 | * {@link Cacheable} 39 | * 40 | * @param key the key of the cache entry to be found 41 | * @return {@link Archive} of cache entry 42 | * @see Cacheable 43 | */ 44 | @Cacheable 45 | public Archive search(K key) { 46 | logger.info("Cache miss with key: {}", key); 47 | return new MissArchive<>(key.toString()); 48 | } 49 | 50 | /** 51 | * Update the cache with provided key and value. This method will always be executed. 52 | * 53 | * @param key the key of the cache entry to be updated 54 | * @param value the value of the cache entry to be updated 55 | * @return {@link HitArchive} of the cache entry 56 | * @see CachePut 57 | */ 58 | @CachePut(key = "#key") 59 | public Archive archive(K key, V value) { 60 | logger.info("Updated cache with key {} and value {}", key, value); 61 | return new HitArchive<>(value); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/archive/ProjectArchiveConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager.archive; 17 | 18 | import org.springframework.cache.annotation.EnableCaching; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import org.springframework.context.annotation.Profile; 22 | 23 | @Configuration 24 | @EnableCaching 25 | @Profile("archive") 26 | class ProjectArchiveConfig { 27 | @Bean 28 | ProjectArchive projectArchive() { 29 | return new ProjectArchive<>(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/filters/AuthenticationAwareFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager.filters; 17 | 18 | import static io.servicecomb.company.manager.filters.FilterConstants.TOKEN_PREFIX; 19 | import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; 20 | import static org.springframework.http.HttpHeaders.AUTHORIZATION; 21 | 22 | import com.netflix.zuul.ZuulFilter; 23 | import com.netflix.zuul.context.RequestContext; 24 | import io.servicecomb.company.manager.AuthenticationService; 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | import org.springframework.http.ResponseEntity; 29 | import org.springframework.stereotype.Component; 30 | 31 | /** 32 | * {@link AuthenticationAwareFilter} is a pre-filter for netflix Zuul. It validates all user 33 | * requests except those ending with /login to doorman to verify if the JWT token provided is 34 | * genuine. 35 | */ 36 | @Component 37 | class AuthenticationAwareFilter extends ZuulFilter { 38 | 39 | private static final Logger logger = LoggerFactory.getLogger(AuthenticationAwareFilter.class); 40 | 41 | private static final String LOGIN_PATH = "/login"; 42 | 43 | private final AuthenticationService authenticationService; 44 | private final PathExtractor pathExtractor; 45 | 46 | @Autowired 47 | AuthenticationAwareFilter( 48 | AuthenticationService authenticationService, 49 | PathExtractor pathExtractor) { 50 | 51 | this.authenticationService = authenticationService; 52 | this.pathExtractor = pathExtractor; 53 | } 54 | 55 | @Override 56 | public String filterType() { 57 | return "pre"; 58 | } 59 | 60 | @Override 61 | public int filterOrder() { 62 | return 1; 63 | } 64 | 65 | @Override 66 | public boolean shouldFilter() { 67 | String path = pathExtractor.path(RequestContext.getCurrentContext()); 68 | logger.info("Received request with query path: {}", path); 69 | return !path.endsWith(LOGIN_PATH); 70 | } 71 | 72 | @Override 73 | public Object run() { 74 | filter(); 75 | return null; 76 | } 77 | 78 | private void filter() { 79 | RequestContext context = RequestContext.getCurrentContext(); 80 | 81 | if (doesNotContainToken(context)) { 82 | logger.warn("No token found in request header"); 83 | rejectRequest(context); 84 | } else { 85 | String token = token(context); 86 | ResponseEntity responseEntity = authenticationService.validate(token); 87 | if (!responseEntity.getStatusCode().is2xxSuccessful()) { 88 | logger.warn("Unauthorized token {} and request rejected", token); 89 | rejectRequest(context); 90 | } else { 91 | logger.info("Token {} validated", token); 92 | } 93 | } 94 | } 95 | 96 | private void rejectRequest(RequestContext context) { 97 | context.setResponseStatusCode(SC_FORBIDDEN); 98 | context.setSendZuulResponse(false); 99 | } 100 | 101 | private boolean doesNotContainToken(RequestContext context) { 102 | return authorizationHeader(context) == null 103 | || !authorizationHeader(context).startsWith(TOKEN_PREFIX); 104 | } 105 | 106 | private String token(RequestContext context) { 107 | return authorizationHeader(context).replace(TOKEN_PREFIX, ""); 108 | } 109 | 110 | private String authorizationHeader(RequestContext context) { 111 | return context.getRequest().getHeader(AUTHORIZATION); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/filters/BeekeeperCacheFetchFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.manager.filters; 18 | 19 | import static io.servicecomb.company.manager.filters.FilterConstants.ANCESTORS_PATH; 20 | import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE; 21 | 22 | import io.servicecomb.company.manager.archive.ProjectArchive; 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.context.annotation.Profile; 25 | import org.springframework.stereotype.Component; 26 | 27 | @Component 28 | @Profile("archive") 29 | class BeekeeperCacheFetchFilter extends CacheFetchFilter { 30 | 31 | @Autowired 32 | BeekeeperCacheFetchFilter(ProjectArchive archive, PathExtractor pathExtractor) { 33 | super(archive, pathExtractor); 34 | } 35 | 36 | @Override 37 | protected String requestDescription() { 38 | return "count bee ancestors"; 39 | } 40 | 41 | @Override 42 | protected String responseContentType() { 43 | return APPLICATION_JSON_UTF8_VALUE; 44 | } 45 | 46 | @Override 47 | protected String pathInRequest() { 48 | return ANCESTORS_PATH; 49 | } 50 | 51 | @Override 52 | public int filterOrder() { 53 | return 3; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/filters/BeekeeperCacheUpdateFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.manager.filters; 18 | 19 | import static io.servicecomb.company.manager.filters.FilterConstants.ANCESTORS_PATH; 20 | 21 | import io.servicecomb.company.manager.archive.ProjectArchive; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.context.annotation.Profile; 24 | import org.springframework.stereotype.Component; 25 | 26 | @Component 27 | @Profile("archive") 28 | class BeekeeperCacheUpdateFilter extends CacheUpdateFilter { 29 | 30 | @Autowired 31 | BeekeeperCacheUpdateFilter(ProjectArchive archive, PathExtractor pathExtractor) { 32 | super(archive, pathExtractor); 33 | } 34 | 35 | @Override 36 | protected String pathInRequest() { 37 | return ANCESTORS_PATH; 38 | } 39 | 40 | @Override 41 | public int filterOrder() { 42 | return 1; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/filters/CacheFetchFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.manager.filters; 18 | 19 | import static javax.servlet.http.HttpServletResponse.SC_OK; 20 | import static org.springframework.http.HttpHeaders.CONTENT_TYPE; 21 | 22 | import com.netflix.zuul.ZuulFilter; 23 | import com.netflix.zuul.context.RequestContext; 24 | import io.servicecomb.company.manager.archive.Archive; 25 | import io.servicecomb.company.manager.archive.ProjectArchive; 26 | import org.slf4j.Logger; 27 | import org.slf4j.LoggerFactory; 28 | 29 | /** 30 | * Pre {@link ZuulFilter} to search cache for corresponding entry of provided key. If a 31 | * matching cache entry is found, return the cache value immediately without forwarding requests 32 | * further to remote service. 33 | */ 34 | abstract class CacheFetchFilter extends ZuulFilter { 35 | 36 | private static final Logger logger = LoggerFactory.getLogger(CacheFetchFilter.class); 37 | private final ProjectArchive archive; 38 | private final PathExtractor pathExtractor; 39 | 40 | CacheFetchFilter(ProjectArchive archive, PathExtractor pathExtractor) { 41 | this.archive = archive; 42 | this.pathExtractor = pathExtractor; 43 | } 44 | 45 | @Override 46 | public String filterType() { 47 | return "pre"; 48 | } 49 | 50 | @Override 51 | public boolean shouldFilter() { 52 | RequestContext context = RequestContext.getCurrentContext(); 53 | String path = pathExtractor.path(context); 54 | logger.info("Received request with query path: {}", path); 55 | return isGenuineFibonacciRequest(context, path); 56 | } 57 | 58 | @Override 59 | public Object run() { 60 | RequestContext context = RequestContext.getCurrentContext(); 61 | String path = pathExtractor.path(context); 62 | logger.info("Received request to " + requestDescription() + " at {}", path); 63 | 64 | Archive result = archive.search(path); 65 | 66 | if (result.exists()) { 67 | logger.info("Found existing project archive with key {} and value {}", path, result.get()); 68 | returnResultWithoutForwardingToZuul(context, result.get(), responseContentType()); 69 | } 70 | 71 | return null; 72 | } 73 | 74 | protected abstract String requestDescription(); 75 | 76 | protected abstract String responseContentType(); 77 | 78 | protected abstract String pathInRequest(); 79 | 80 | private boolean isGenuineFibonacciRequest(RequestContext context, String path) { 81 | return path.contains(pathInRequest()) && context.sendZuulResponse(); 82 | } 83 | 84 | private void returnResultWithoutForwardingToZuul( 85 | RequestContext context, 86 | String body, 87 | String contentType) { 88 | context.setResponseStatusCode(SC_OK); 89 | context.getResponse().setHeader(CONTENT_TYPE, contentType); 90 | context.setResponseBody(body); 91 | context.setSendZuulResponse(false); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/filters/CacheUpdateFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.manager.filters; 18 | 19 | import static com.netflix.zuul.constants.ZuulConstants.ZUUL_INITIAL_STREAM_BUFFER_SIZE; 20 | import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; 21 | import static javax.servlet.http.HttpServletResponse.SC_OK; 22 | 23 | import com.netflix.config.DynamicIntProperty; 24 | import com.netflix.config.DynamicPropertyFactory; 25 | import com.netflix.zuul.ZuulFilter; 26 | import com.netflix.zuul.context.RequestContext; 27 | import io.servicecomb.company.manager.archive.ProjectArchive; 28 | import java.io.ByteArrayOutputStream; 29 | import java.io.IOException; 30 | import org.apache.commons.io.IOUtils; 31 | import org.slf4j.Logger; 32 | import org.slf4j.LoggerFactory; 33 | 34 | /** 35 | * Post {@link ZuulFilter} to update cache entry with response body from remote service. 36 | */ 37 | abstract class CacheUpdateFilter extends ZuulFilter { 38 | 39 | private static final Logger logger = LoggerFactory.getLogger(CacheUpdateFilter.class); 40 | private static final DynamicIntProperty STREAM_BUFFER_SIZE = DynamicPropertyFactory 41 | .getInstance() 42 | .getIntProperty(ZUUL_INITIAL_STREAM_BUFFER_SIZE, 8192); 43 | private final ProjectArchive archive; 44 | private final PathExtractor pathExtractor; 45 | 46 | CacheUpdateFilter( 47 | ProjectArchive archive, PathExtractor pathExtractor) { 48 | this.archive = archive; 49 | this.pathExtractor = pathExtractor; 50 | } 51 | 52 | @Override 53 | public String filterType() { 54 | return "post"; 55 | } 56 | 57 | @Override 58 | public boolean shouldFilter() { 59 | RequestContext context = RequestContext.getCurrentContext(); 60 | String path = pathExtractor.path(context); 61 | logger.info("Received request with query path: {}", path); 62 | 63 | return isSuccessfulFibonacciResponse(context, path); 64 | } 65 | 66 | @Override 67 | public Object run() { 68 | RequestContext context = RequestContext.getCurrentContext(); 69 | 70 | archive.archive(pathExtractor.path(context), responseBodyOf(context)); 71 | return null; 72 | } 73 | 74 | private boolean isSuccessfulFibonacciResponse(RequestContext context, String path) { 75 | return path.contains(pathInRequest()) 76 | && context.getResponseStatusCode() == SC_OK 77 | && context.sendZuulResponse() 78 | && (context.getResponseBody() != null || context.getResponseDataStream() != null); 79 | } 80 | 81 | protected abstract String pathInRequest(); 82 | 83 | private String responseBodyOf(RequestContext context) { 84 | try { 85 | if (context.getResponseBody() != null) { 86 | return context.getResponseBody(); 87 | } else { 88 | return responseBody(context); 89 | } 90 | } catch (IOException e) { 91 | logger.error("Failed to read response body", e); 92 | context.setResponseStatusCode(SC_INTERNAL_SERVER_ERROR); 93 | throw new IllegalStateException("Failed to read response body", e); 94 | } 95 | } 96 | 97 | private String responseBody(RequestContext context) throws IOException { 98 | try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(STREAM_BUFFER_SIZE.get())) { 99 | IOUtils.copy(context.getResponseDataStream(), outputStream); 100 | context.setResponseBody(outputStream.toString()); 101 | return outputStream.toString(); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/filters/FilterConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager.filters; 17 | 18 | public interface FilterConstants { 19 | String TOKEN_PREFIX = "Bearer "; 20 | String FIBONACCI_PATH = "/fibonacci/term"; 21 | String ANCESTORS_PATH = "/ancestors"; 22 | } 23 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/filters/PathExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager.filters; 17 | 18 | import com.netflix.zuul.context.RequestContext; 19 | import java.util.LinkedList; 20 | import java.util.List; 21 | import javax.servlet.http.HttpServletRequest; 22 | import org.springframework.stereotype.Component; 23 | 24 | @Component 25 | class PathExtractor { 26 | 27 | String path(RequestContext context) { 28 | HttpServletRequest request = context.getRequest(); 29 | StringBuilder builder = new StringBuilder(); 30 | 31 | builder.append(request.getContextPath()).append(request.getServletPath()); 32 | if (request.getPathInfo() != null) { 33 | builder.append(request.getPathInfo()); 34 | } 35 | 36 | if (context.getRequestQueryParams() != null) { 37 | appendQueryParams(context, builder); 38 | } 39 | 40 | return builder.toString(); 41 | } 42 | 43 | private void appendQueryParams(RequestContext context, StringBuilder builder) { 44 | List queryParams = new LinkedList<>(); 45 | 46 | context.getRequestQueryParams() 47 | .forEach((key, values) -> values 48 | .forEach(value -> queryParams.add(key + "=" + value))); 49 | 50 | builder.append("?").append(String.join("&", queryParams)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/filters/WorkerCacheFetchFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager.filters; 17 | 18 | import static io.servicecomb.company.manager.filters.FilterConstants.FIBONACCI_PATH; 19 | import static org.springframework.http.MediaType.TEXT_PLAIN_VALUE; 20 | 21 | import io.servicecomb.company.manager.archive.ProjectArchive; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.context.annotation.Profile; 24 | import org.springframework.stereotype.Component; 25 | 26 | @Component 27 | @Profile("archive") 28 | class WorkerCacheFetchFilter extends CacheFetchFilter { 29 | 30 | @Autowired 31 | WorkerCacheFetchFilter(ProjectArchive archive, PathExtractor pathExtractor) { 32 | super(archive, pathExtractor); 33 | } 34 | 35 | @Override 36 | protected String requestDescription() { 37 | return "calculate fibonacci term"; 38 | } 39 | 40 | @Override 41 | protected String responseContentType() { 42 | return TEXT_PLAIN_VALUE; 43 | } 44 | 45 | @Override 46 | protected String pathInRequest() { 47 | return FIBONACCI_PATH; 48 | } 49 | 50 | @Override 51 | public int filterOrder() { 52 | return 2; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /manager/src/main/java/io/servicecomb/company/manager/filters/WorkerCacheUpdateFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager.filters; 17 | 18 | import static io.servicecomb.company.manager.filters.FilterConstants.FIBONACCI_PATH; 19 | 20 | import com.netflix.zuul.ZuulFilter; 21 | import io.servicecomb.company.manager.archive.ProjectArchive; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.context.annotation.Profile; 24 | import org.springframework.stereotype.Component; 25 | 26 | /** 27 | * Post {@link ZuulFilter} to update cache entry when a fibonacci term is calculated. 28 | */ 29 | @Component 30 | @Profile("archive") 31 | class WorkerCacheUpdateFilter extends CacheUpdateFilter { 32 | 33 | @Autowired 34 | WorkerCacheUpdateFilter(ProjectArchive archive, PathExtractor pathExtractor) { 35 | super(archive, pathExtractor); 36 | } 37 | 38 | @Override 39 | protected String pathInRequest() { 40 | return FIBONACCI_PATH; 41 | } 42 | 43 | @Override 44 | public int filterOrder() { 45 | return 0; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /manager/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | zuul: 2 | routes: 3 | doorman: 4 | serviceId: doorman 5 | sensitiveHeaders: 6 | worker: 7 | serviceId: worker 8 | beekeeper: 9 | serviceId: beekeeper 10 | 11 | # disable netflix eurkea since it's not used for service discovery 12 | ribbon: 13 | eureka: 14 | enabled: false 15 | 16 | spring: 17 | cloud: 18 | cse: 19 | host: 127.0.0.1 20 | port: 30100 21 | 22 | server: 23 | port: 0 24 | 25 | --- 26 | 27 | spring: 28 | profiles: sit 29 | 30 | --- 31 | 32 | spring: 33 | profiles: dev 34 | 35 | logging: 36 | level: 37 | root: INFO 38 | 39 | zuul: 40 | routes: 41 | doorman: 42 | url: http://localhost:8082 43 | sensitiveHeaders: 44 | worker: 45 | url: http://localhost:8082 46 | beekeeper: 47 | url: http://localhost:8082 48 | -------------------------------------------------------------------------------- /manager/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /manager/src/main/resources/microservice.yaml: -------------------------------------------------------------------------------- 1 | # all interconnected microservices must belong to an application wth the same ID 2 | APPLICATION_ID: company 3 | service_description: 4 | # name of the declaring microservice 5 | name: manager 6 | version: 0.0.1 7 | cse: 8 | service: 9 | registry: 10 | address: http://sc.servicecomb.io:30100 11 | isolation: 12 | doorman: 13 | timeoutInMilliseconds: 30000 14 | beekeeper: 15 | timeoutInMilliseconds: 30000 16 | worker: 17 | timeoutInMilliseconds: 30000 18 | 19 | servicecomb: 20 | tracing: 21 | collector: 22 | address: http://zipkin.io:9411 23 | 24 | -------------------------------------------------------------------------------- /manager/src/test/java/io/servicecomb/company/manager/AuthenticationServiceFailedTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager; 17 | 18 | import static org.apache.http.entity.ContentType.APPLICATION_JSON; 19 | import static org.assertj.core.api.Assertions.assertThat; 20 | import static org.mockito.Mockito.mock; 21 | import static org.mockito.Mockito.when; 22 | 23 | import au.com.dius.pact.consumer.Pact; 24 | import au.com.dius.pact.consumer.PactProviderRule; 25 | import au.com.dius.pact.consumer.PactVerification; 26 | import au.com.dius.pact.consumer.dsl.PactDslWithProvider; 27 | import au.com.dius.pact.model.PactFragment; 28 | import com.fasterxml.jackson.core.JsonProcessingException; 29 | import com.fasterxml.jackson.databind.ObjectMapper; 30 | import java.net.URI; 31 | import java.util.HashMap; 32 | import java.util.Map; 33 | import org.junit.Rule; 34 | import org.junit.Test; 35 | import org.springframework.cloud.client.ServiceInstance; 36 | import org.springframework.http.HttpStatus; 37 | import org.springframework.http.MediaType; 38 | import org.springframework.http.ResponseEntity; 39 | import org.springframework.web.client.RestTemplate; 40 | 41 | public class AuthenticationServiceFailedTest { 42 | @Rule 43 | public final PactProviderRule providerRule = new PactProviderRule("Doorman", this); 44 | 45 | private final String token = "unknown-token"; 46 | 47 | private final ServiceInstance serviceInstance = mock(ServiceInstance.class); 48 | private final RestTemplate restTemplate = new FixedUrlRestTemplate(providerRule.getConfig().url() + "/rest/validate"); 49 | 50 | private final ObjectMapper objectMapper = new ObjectMapper(); 51 | private final AuthenticationService authenticationService = new AuthenticationService(restTemplate); 52 | 53 | @Pact(consumer = "Manager") 54 | public PactFragment createFragment(PactDslWithProvider pactDslWithProvider) throws JsonProcessingException { 55 | Map headers = new HashMap<>(); 56 | headers.put("Content-Type", MediaType.TEXT_PLAIN_VALUE); 57 | 58 | return pactDslWithProvider 59 | .given("User Jack is unauthorized") 60 | .uponReceiving("a request to access from Jack") 61 | .path("/rest/validate") 62 | .body(objectMapper.writeValueAsString(new Token(token)), APPLICATION_JSON) 63 | .method("POST") 64 | .willRespondWith() 65 | .headers(headers) 66 | .status(HttpStatus.FORBIDDEN.value()) 67 | .toFragment(); 68 | } 69 | 70 | @PactVerification 71 | @Test 72 | public void validatesUserToken() { 73 | when(serviceInstance.getUri()).thenReturn(URI.create(providerRule.getConfig().url())); 74 | 75 | ResponseEntity responseEntity = authenticationService.validate(token); 76 | 77 | assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /manager/src/test/java/io/servicecomb/company/manager/AuthenticationServiceHappyTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager; 17 | 18 | import static org.apache.http.entity.ContentType.APPLICATION_JSON; 19 | import static org.assertj.core.api.Assertions.assertThat; 20 | import static org.mockito.Mockito.mock; 21 | import static org.mockito.Mockito.when; 22 | 23 | import au.com.dius.pact.consumer.Pact; 24 | import au.com.dius.pact.consumer.PactProviderRule; 25 | import au.com.dius.pact.consumer.PactVerification; 26 | import au.com.dius.pact.consumer.dsl.PactDslWithProvider; 27 | import au.com.dius.pact.model.PactFragment; 28 | import com.fasterxml.jackson.core.JsonProcessingException; 29 | import com.fasterxml.jackson.databind.ObjectMapper; 30 | import java.net.URI; 31 | import java.util.HashMap; 32 | import java.util.Map; 33 | import org.junit.Rule; 34 | import org.junit.Test; 35 | import org.springframework.cloud.client.ServiceInstance; 36 | import org.springframework.http.HttpStatus; 37 | import org.springframework.http.MediaType; 38 | import org.springframework.http.ResponseEntity; 39 | import org.springframework.web.client.RestTemplate; 40 | 41 | public class AuthenticationServiceHappyTest { 42 | @Rule 43 | public final PactProviderRule providerRule = new PactProviderRule("Doorman", this); 44 | 45 | private final String token = "sean-token"; 46 | private final String username = "Sean"; 47 | 48 | private final ServiceInstance serviceInstance = mock(ServiceInstance.class); 49 | private final RestTemplate restTemplate = new FixedUrlRestTemplate(providerRule.getConfig().url() + "/rest/validate"); 50 | 51 | private final ObjectMapper objectMapper = new ObjectMapper(); 52 | private final AuthenticationService authenticationService = new AuthenticationService(restTemplate); 53 | 54 | @Pact(consumer = "Manager") 55 | public PactFragment createFragment(PactDslWithProvider pactDslWithProvider) throws JsonProcessingException { 56 | Map headers = new HashMap<>(); 57 | headers.put("Content-Type", MediaType.TEXT_PLAIN_VALUE); 58 | 59 | return pactDslWithProvider 60 | .given("User Sean is authorized") 61 | .uponReceiving("a request to access from Sean") 62 | .path("/rest/validate") 63 | .body(objectMapper.writeValueAsString(new Token(token)), APPLICATION_JSON) 64 | .method("POST") 65 | .willRespondWith() 66 | .headers(headers) 67 | .status(HttpStatus.OK.value()) 68 | .body(username) 69 | .toFragment(); 70 | } 71 | 72 | @PactVerification 73 | @Test 74 | public void validatesUserToken() { 75 | when(serviceInstance.getUri()).thenReturn(URI.create(providerRule.getConfig().url())); 76 | 77 | ResponseEntity responseEntity = authenticationService.validate(token); 78 | 79 | assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); 80 | assertThat(responseEntity.getBody()).isEqualTo(username); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /manager/src/test/java/io/servicecomb/company/manager/AuthenticationServiceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager; 17 | 18 | import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; 19 | import static com.github.tomakehurst.wiremock.client.WireMock.post; 20 | import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; 21 | import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; 22 | import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; 23 | import static org.apache.http.HttpStatus.SC_OK; 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | import static org.springframework.http.HttpStatus.REQUEST_TIMEOUT; 26 | 27 | import com.github.tomakehurst.wiremock.junit.WireMockRule; 28 | import com.seanyinx.github.unit.scaffolding.Randomness; 29 | import org.junit.Before; 30 | import org.junit.ClassRule; 31 | import org.junit.Test; 32 | import org.junit.runner.RunWith; 33 | import org.springframework.beans.factory.annotation.Autowired; 34 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 35 | import org.springframework.boot.test.context.SpringBootTest; 36 | import org.springframework.http.ResponseEntity; 37 | import org.springframework.test.context.ActiveProfiles; 38 | import org.springframework.test.context.junit4.SpringRunner; 39 | 40 | @RunWith(SpringRunner.class) 41 | @SpringBootTest(properties = "hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=500") 42 | @AutoConfigureMockMvc 43 | @ActiveProfiles("dev") 44 | public class AuthenticationServiceTest { 45 | @ClassRule 46 | public static final WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort()); 47 | 48 | private final String username = Randomness.uniquify("username"); 49 | private final String token = Randomness.uniquify("token"); 50 | 51 | @Autowired 52 | private FixedUrlRestTemplate restTemplate; 53 | 54 | @Autowired 55 | private AuthenticationService authenticationService; 56 | 57 | @Before 58 | public void setUp() throws Exception { 59 | restTemplate.setUrl("http://localhost:" + wireMockRule.port() + "/rest/validate"); 60 | stubFor(post(urlEqualTo("/rest/validate")) 61 | .willReturn( 62 | aResponse() 63 | .withFixedDelay(2000) 64 | .withStatus(SC_OK) 65 | .withBody(username))); 66 | } 67 | 68 | @Test 69 | public void timesOutWhenDoormanIsUnresponsive() { 70 | ResponseEntity responseEntity = authenticationService.validate(token); 71 | 72 | assertThat(responseEntity.getStatusCode()).isEqualTo(REQUEST_TIMEOUT); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /manager/src/test/java/io/servicecomb/company/manager/FixedUrlRestTemplate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.manager; 18 | 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | import org.springframework.http.ResponseEntity; 22 | import org.springframework.web.client.RestClientException; 23 | import org.springframework.web.client.RestTemplate; 24 | 25 | class FixedUrlRestTemplate extends RestTemplate { 26 | 27 | private static final Logger logger = LoggerFactory.getLogger(FixedUrlRestTemplate.class); 28 | 29 | private String url; 30 | 31 | FixedUrlRestTemplate(String url) { 32 | this.url = url; 33 | } 34 | 35 | void setUrl(String url) { 36 | this.url = url; 37 | } 38 | 39 | @Override 40 | public ResponseEntity postForEntity( 41 | String url, 42 | Object request, 43 | Class responseType, 44 | Object... uriVariables) throws RestClientException { 45 | 46 | logger.info("Received POST request to address {} -> {}", url, this.url); 47 | return super.postForEntity( 48 | this.url, 49 | request, 50 | responseType, 51 | uriVariables); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /manager/src/test/java/io/servicecomb/company/manager/FixedUrlRestTemplateConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.manager; 18 | 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import org.springframework.context.annotation.Primary; 22 | import org.springframework.web.client.RestTemplate; 23 | 24 | @Configuration 25 | class FixedUrlRestTemplateConfig { 26 | 27 | @Primary 28 | @Bean 29 | RestTemplate restTemplate() { 30 | return new FixedUrlRestTemplate("http://localhost:8082/rest/validate"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /manager/src/test/java/io/servicecomb/company/manager/ProjectArchiveTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import io.servicecomb.company.manager.archive.Archive; 21 | import io.servicecomb.company.manager.archive.ProjectArchive; 22 | import org.junit.Test; 23 | 24 | public class ProjectArchiveTest { 25 | 26 | private final ProjectArchive archive = new ProjectArchive<>(); 27 | 28 | @Test 29 | public void alwaysMissOnSearch() { 30 | Archive result = archive.search(1); 31 | 32 | assertThat(result.exists()).isFalse(); 33 | } 34 | 35 | @Test 36 | public void alwaysHitOnArchive() { 37 | Archive result = archive.archive(1, 1L); 38 | 39 | assertThat(result.exists()).isTrue(); 40 | assertThat(result.get()).isEqualTo(1L); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /manager/src/test/java/io/servicecomb/company/manager/archive/HitArchiveTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager.archive; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import com.seanyinx.github.unit.scaffolding.Randomness; 21 | import org.junit.Test; 22 | 23 | public class HitArchiveTest { 24 | private final String value = Randomness.uniquify("value"); 25 | private final HitArchive archive = new HitArchive<>(value); 26 | 27 | @Test 28 | public void getsProvidedValue() { 29 | assertThat(archive.exists()).isTrue(); 30 | assertThat(archive.get()).isEqualTo(value); 31 | } 32 | } -------------------------------------------------------------------------------- /manager/src/test/java/io/servicecomb/company/manager/archive/MissArchiveTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.manager.archive; 17 | 18 | import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing; 19 | import static com.seanyinx.github.unit.scaffolding.Randomness.uniquify; 20 | import static org.assertj.core.api.Assertions.assertThat; 21 | 22 | import java.util.NoSuchElementException; 23 | import org.junit.Test; 24 | 25 | public class MissArchiveTest { 26 | 27 | private final String key = uniquify("key"); 28 | private final Archive archive = new MissArchive<>(key); 29 | 30 | @Test 31 | public void blowsUpWhenGet() { 32 | assertThat(archive.exists()).isFalse(); 33 | 34 | try { 35 | archive.get(); 36 | expectFailing(NoSuchElementException.class); 37 | } catch (NoSuchElementException e) { 38 | assertThat(e.getMessage()).isEqualTo("No result found for search term " + key); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /manager/src/test/java/io/servicecomb/company/manager/filters/PathExtractorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.manager.filters; 18 | 19 | import static java.util.Arrays.asList; 20 | import static org.assertj.core.api.Assertions.assertThat; 21 | import static org.mockito.Mockito.when; 22 | 23 | import com.netflix.zuul.context.RequestContext; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | import java.util.Map; 27 | import javax.servlet.http.HttpServletRequest; 28 | import org.junit.Before; 29 | import org.junit.Test; 30 | import org.mockito.Mockito; 31 | 32 | public class PathExtractorTest { 33 | 34 | private final RequestContext requestContext = Mockito.mock(RequestContext.class); 35 | private final HttpServletRequest servletRequest = Mockito.mock(HttpServletRequest.class); 36 | 37 | private final Map> queryParams = new HashMap<>(); 38 | private final PathExtractor extractor = new PathExtractor(); 39 | 40 | @Before 41 | public void setUp() throws Exception { 42 | when(requestContext.getRequest()).thenReturn(servletRequest); 43 | when(servletRequest.getContextPath()).thenReturn("/root"); 44 | when(servletRequest.getServletPath()).thenReturn("/path/to/resource"); 45 | 46 | queryParams.put("n", asList("3", "5")); 47 | } 48 | 49 | @Test 50 | public void extractsPathWithQueryStringAndPathInfo() { 51 | when(servletRequest.getPathInfo()).thenReturn("/id"); 52 | when(requestContext.getRequestQueryParams()).thenReturn(queryParams); 53 | 54 | String path = extractor.path(requestContext); 55 | 56 | assertThat(path).isEqualTo("/root/path/to/resource/id?n=3&n=5"); 57 | } 58 | } -------------------------------------------------------------------------------- /scripts/make_docker_image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jre-alpine 2 | 3 | EXPOSE 8080 4 | 5 | RUN mkdir -p /maven/company/ 6 | 7 | COPY ./*-exec.jar /maven/company/ 8 | 9 | ENTRYPOINT java $JAVA_OPTS -jar /maven/company/$ARTIFACT_ID-0.2.0-SNAPSHOT-exec.jar 10 | -------------------------------------------------------------------------------- /stress-tests/README.md: -------------------------------------------------------------------------------- 1 | # Steps to stress tests *Company Demo* using JMeter 2 | 3 | 1. make sure the *Company Demo* is up 4 | 2. replace host and port information in `hosts.csv` file with the working *Company Demo*'s. 5 | 3. run JMeter tests 6 | ```bash 7 | jmeter -n -t workshop.jmx -j workshop.log -l workshop.jtl -Jthreads=100 -Jduration=600 8 | ``` 9 | The threads parameter means the simulated concurrency while the duration means the test period. 10 | 11 | After the tests finished, you can check the result in jmeter's user interface by calling `jmeter` directly and import the *workshop.jmx* file. 12 | -------------------------------------------------------------------------------- /stress-tests/hosts.csv: -------------------------------------------------------------------------------- 1 | 127.0.0.1,8083 2 | -------------------------------------------------------------------------------- /worker/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | company 23 | io.servicecomb.workshop.demo 24 | 0.3.0-SNAPSHOT 25 | 26 | 4.0.0 27 | 28 | worker 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-logging 38 | 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-log4j2 44 | 45 | 46 | org.apache.logging.log4j 47 | log4j-web 48 | 49 | 50 | com.lmax 51 | disruptor 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-starter-web 56 | 57 | 58 | io.servicecomb 59 | spring-boot-starter-provider 60 | 61 | 62 | io.servicecomb 63 | handler-tracing-zipkin 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-starter-test 69 | test 70 | 71 | 72 | com.github.seanyinx 73 | unit-scaffolding 74 | test 75 | 76 | 77 | 78 | 79 | 80 | 81 | com.github.odavid.maven.plugins 82 | mixin-maven-plugin 83 | 84 | 85 | 86 | io.servicecomb.workshop.demo 87 | docker-build-config 88 | 0.3.0-SNAPSHOT 89 | 90 | 91 | 92 | 93 | 94 | org.springframework.boot 95 | spring-boot-maven-plugin 96 | 97 | 98 | 99 | 100 | 101 | 102 | docker 103 | 104 | 105 | 106 | io.fabric8 107 | docker-maven-plugin 108 | 109 | 110 | org.commonjava.maven.plugins 111 | directory-maven-plugin 112 | 113 | 114 | 115 | 116 | 117 | HuaweiCloud 118 | 119 | 120 | 121 | maven-antrun-plugin 122 | 1.8 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /worker/src/main/java/io/servicecomb/company/worker/FibonacciEndpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.worker; 17 | 18 | /** 19 | * {@link FibonacciEndpoint} provides the common interface for different endpoint implementations, 20 | * such as {@link FibonacciRestEndpoint} and {@link FibonacciRpcEndpoint}. 21 | * 22 | * It supports sequence up to roughly 90, because the sequence value will exceed the limit of Java 23 | * type long. 24 | * 25 | * The endpoints are supposed to be very thin. They parse requests from different protocols and 26 | * delegate them to the same calculation logic provided by {@link FibonacciService}. 27 | */ 28 | public interface FibonacciEndpoint { 29 | 30 | /** 31 | * Calculates the nth term of fibonacci sequence. 32 | * for example, the following statement outputs fibonacci sequence [0, 1, 1, 2, 3, 5] 33 | *
34 |    *   {@code long[] sequence = {
35 |    *      endpoint.term(0),
36 |    *      endpoint.term(1),
37 |    *      endpoint.term(2),
38 |    *      endpoint.term(3),
39 |    *      endpoint.term(4),
40 |    *      endpoint.term(5)};
41 |    *   System.out.println(Arrays.toString(sequence));
42 |    *   }
43 |    * 
44 | * 45 | * @param n the index of fibonacci sequence 46 | * @return the nth term of fibonacci 47 | */ 48 | long term(int n); 49 | } 50 | -------------------------------------------------------------------------------- /worker/src/main/java/io/servicecomb/company/worker/FibonacciRestEndpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.worker; 17 | 18 | import io.servicecomb.provider.rest.common.RestSchema; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.stereotype.Controller; 21 | import org.springframework.web.bind.annotation.RequestMapping; 22 | import org.springframework.web.bind.annotation.RequestMethod; 23 | import org.springframework.web.bind.annotation.ResponseBody; 24 | 25 | /** 26 | * {@link FibonacciRestEndpoint} provides the rest implementation of {@link FibonacciEndpoint}. 27 | * The rest endpoint is accessed by /fibonacci/term?n={value} with HTTP GET. 28 | */ 29 | @RestSchema(schemaId = "fibonacciRestEndpoint") 30 | @RequestMapping("/fibonacci") 31 | @Controller 32 | public class FibonacciRestEndpoint implements FibonacciEndpoint { 33 | 34 | private final FibonacciService fibonacciService; 35 | 36 | @Autowired 37 | FibonacciRestEndpoint(FibonacciService fibonacciService) { 38 | this.fibonacciService = fibonacciService; 39 | } 40 | 41 | @Override 42 | @RequestMapping(value = "/term", method = RequestMethod.GET) 43 | @ResponseBody 44 | public long term(int n) { 45 | return fibonacciService.term(n); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /worker/src/main/java/io/servicecomb/company/worker/FibonacciRpcEndpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.worker; 17 | 18 | 19 | import io.servicecomb.provider.pojo.RpcSchema; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | 22 | /** 23 | * {@link FibonacciRpcEndpoint} provides the RPC implementation of {@link FibonacciEndpoint}. 24 | */ 25 | @RpcSchema(schemaId = "fibonacciRpcEndpoint") 26 | // class modifier has to be public, or producer invoker will fail to access it 27 | public class FibonacciRpcEndpoint implements FibonacciEndpoint { 28 | 29 | private final FibonacciService fibonacciService; 30 | 31 | @Autowired 32 | public FibonacciRpcEndpoint(FibonacciService fibonacciService) { 33 | this.fibonacciService = fibonacciService; 34 | } 35 | 36 | @Override 37 | public long term(int n) { 38 | return fibonacciService.term(n); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /worker/src/main/java/io/servicecomb/company/worker/FibonacciService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.worker; 17 | 18 | /** 19 | * {@link FibonacciService} provides the interface of actual fibonacci sequence calculation. 20 | */ 21 | interface FibonacciService { 22 | 23 | /** 24 | * @see FibonacciEndpoint#term(int) 25 | * @param n the index of fibonacci sequence 26 | * @return the nth term of fibonacci sequence 27 | */ 28 | long term(int n); 29 | } 30 | -------------------------------------------------------------------------------- /worker/src/main/java/io/servicecomb/company/worker/FibonacciServiceImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.worker; 17 | 18 | import org.springframework.stereotype.Service; 19 | 20 | @Service 21 | class FibonacciServiceImpl implements FibonacciService { 22 | 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | @Override 27 | public long term(int n) { 28 | if (n < 0) { 29 | throw new IllegalArgumentException("Fibonacci term must not be negative: " + n); 30 | } 31 | 32 | return nthTerm(n, new long[]{-1, -1}); 33 | } 34 | 35 | private long nthTerm(int n, long[] lastTwoFibos) { 36 | if (n == 0) { 37 | return 0; 38 | } else if (n == 1) { 39 | return 1; 40 | } 41 | 42 | if (!isCached(lastTwoFibos)) { 43 | cacheCalculatedFibo(nthTerm(n - 2, lastTwoFibos), lastTwoFibos); 44 | cacheCalculatedFibo(nthTerm(n - 1, lastTwoFibos), lastTwoFibos); 45 | } 46 | 47 | return lastTwoFibos[0] + lastTwoFibos[1]; 48 | } 49 | 50 | private boolean isCached(long[] lastTwoFibos) { 51 | return lastTwoFibos[0] >= 0 && lastTwoFibos[1] >= 0; 52 | } 53 | 54 | private void cacheCalculatedFibo(long fibo, long[] lastTwoFibos) { 55 | lastTwoFibos[1] = lastTwoFibos[0]; 56 | lastTwoFibos[0] = fibo; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /worker/src/main/java/io/servicecomb/company/worker/WorkerApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.worker; 17 | 18 | import io.servicecomb.springboot.starter.provider.EnableServiceComb; 19 | import org.springframework.boot.SpringApplication; 20 | import org.springframework.boot.autoconfigure.SpringBootApplication; 21 | import org.springframework.context.annotation.Configuration; 22 | import org.springframework.context.annotation.Profile; 23 | 24 | @SpringBootApplication 25 | public class WorkerApplication { 26 | 27 | public static void main(String[] args) { 28 | SpringApplication.run(WorkerApplication.class, args); 29 | } 30 | 31 | // do not enable service registration/discovery and schema generation/registration 32 | // unless the active profile is not dev 33 | @EnableServiceComb 34 | @Profile("!dev") 35 | @Configuration 36 | static class ServiceCombConfig { 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /worker/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 0 3 | -------------------------------------------------------------------------------- /worker/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /worker/src/main/resources/microservice.yaml: -------------------------------------------------------------------------------- 1 | # all interconnected microservices must belong to an application wth the same ID 2 | APPLICATION_ID: company 3 | service_description: 4 | # name of the declaring microservice 5 | name: worker 6 | version: 0.0.1 7 | cse: 8 | service: 9 | registry: 10 | address: http://sc.servicecomb.io:30100 11 | highway: 12 | address: 0.0.0.0:7070 13 | rest: 14 | address: 0.0.0.0:8080 15 | handler: 16 | chain: 17 | Provider: 18 | default: tracing-provider,bizkeeper-provider 19 | 20 | servicecomb: 21 | tracing: 22 | collector: 23 | address: http://zipkin.io:9411 24 | -------------------------------------------------------------------------------- /worker/src/test/java/io/servicecomb/company/worker/FibonacciRestEndpointTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.worker; 17 | 18 | import static org.mockito.Mockito.when; 19 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 20 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 21 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 22 | 23 | import com.seanyinx.github.unit.scaffolding.Randomness; 24 | import org.junit.Test; 25 | import org.junit.runner.RunWith; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 28 | import org.springframework.boot.test.mock.mockito.MockBean; 29 | import org.springframework.test.context.ActiveProfiles; 30 | import org.springframework.test.context.junit4.SpringRunner; 31 | import org.springframework.test.web.servlet.MockMvc; 32 | 33 | @RunWith(SpringRunner.class) 34 | @WebMvcTest(FibonacciRestEndpoint.class) 35 | @ActiveProfiles("dev") 36 | public class FibonacciRestEndpointTest { 37 | private final long expected = Randomness.nextLong(); 38 | private final int term = Randomness.nextInt(); 39 | 40 | @MockBean 41 | private FibonacciService fibonacciService; 42 | 43 | @Autowired 44 | private MockMvc mockMvc; 45 | 46 | @Test 47 | public void returnsTokenOfAuthenticatedUser() throws Exception { 48 | when(fibonacciService.term(term)).thenReturn(expected); 49 | 50 | mockMvc.perform( 51 | get("/fibonacci/term") 52 | .param("n", String.valueOf(term))) 53 | .andExpect(status().isOk()) 54 | .andExpect(content().string(String.valueOf(expected))); 55 | } 56 | } -------------------------------------------------------------------------------- /worker/src/test/java/io/servicecomb/company/worker/FibonacciRpcEndpointTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.servicecomb.company.worker; 18 | 19 | import static org.assertj.core.api.Assertions.assertThat; 20 | import static org.mockito.Mockito.when; 21 | 22 | import com.seanyinx.github.unit.scaffolding.Randomness; 23 | import org.junit.Test; 24 | import org.mockito.Mockito; 25 | 26 | public class FibonacciRpcEndpointTest { 27 | 28 | private final FibonacciService fibonacciService = Mockito.mock(FibonacciService.class); 29 | 30 | private final long expected = Randomness.nextLong(); 31 | private final int term = Randomness.nextInt(); 32 | 33 | private final FibonacciRpcEndpoint fibonacciRpcApi = new FibonacciRpcEndpoint(fibonacciService); 34 | 35 | @Test 36 | public void providesFibonacciTermWithUnderlyingService() { 37 | when(fibonacciService.term(term)).thenReturn(expected); 38 | 39 | long fibo = fibonacciRpcApi.term(term); 40 | 41 | assertThat(fibo).isEqualTo(expected); 42 | } 43 | } -------------------------------------------------------------------------------- /worker/src/test/java/io/servicecomb/company/worker/FibonacciServiceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Huawei Technologies Co., Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.servicecomb.company.worker; 17 | 18 | import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing; 19 | import static com.seanyinx.github.unit.scaffolding.Randomness.nextInt; 20 | import static org.assertj.core.api.Assertions.assertThat; 21 | 22 | import org.junit.Test; 23 | 24 | public class FibonacciServiceTest { 25 | 26 | private final int[] expected = { 27 | 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 28 | 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811 29 | }; 30 | 31 | private final FibonacciService calculator = new FibonacciServiceImpl(); 32 | 33 | @Test 34 | public void calculatesFibonacciOfTermN() { 35 | for (int i = 0, length = expected.length; i < length; i++) { 36 | long fib = calculator.term(i); 37 | 38 | assertThat(fib).isEqualTo(expected[i]); 39 | } 40 | } 41 | 42 | @Test 43 | public void blowsUpWhenInputIsNegative() { 44 | int term = -nextInt(128) - 1; 45 | try { 46 | calculator.term(term); 47 | expectFailing(IllegalArgumentException.class); 48 | } catch (IllegalArgumentException e) { 49 | assertThat(e.getMessage()).isEqualTo("Fibonacci term must not be negative: " + term); 50 | } 51 | } 52 | 53 | @Test 54 | public void calculatesFibonacciOfTerm90() { 55 | long fibo = calculator.term(90); 56 | 57 | assertThat(fibo).isEqualTo(2880067194370816120L); 58 | } 59 | } 60 | --------------------------------------------------------------------------------