├── .gitignore ├── .netflixoss ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── OSSMETADATA ├── README.md ├── build.gradle ├── buildViaTravis.sh ├── codequality ├── HEADER └── checkstyle.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images └── Interceptors-Flow.jpg ├── installViaTravis.sh ├── karyon2-admin-plugins ├── karyon-admin-healthcheck-plugin │ ├── build.gradle │ └── src │ │ ├── main │ │ └── java │ │ │ ├── com │ │ │ └── netflix │ │ │ │ └── adminresources │ │ │ │ └── HealthcheckResource.java │ │ │ └── netflix │ │ │ └── adminresources │ │ │ └── HealthCheckPlugin.java │ │ └── test │ │ ├── java │ │ └── netflix │ │ │ └── adminresources │ │ │ └── HealthCheckResourceTest.java │ │ └── resources │ │ └── log4j.properties ├── karyon2-admin-eureka-plugin │ ├── build.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── netflix │ │ │ └── adminresources │ │ │ ├── pages │ │ │ └── EurekaPage.java │ │ │ └── resources │ │ │ └── EurekaResource.java │ │ └── resources │ │ └── webadmin │ │ └── eureka │ │ ├── index.ftl │ │ └── index.js └── karyon2-admin-healthcheck-plugin │ ├── build.gradle │ └── src │ ├── main │ └── java │ │ └── netflix │ │ └── adminresources │ │ ├── HealthCheckPlugin.java │ │ └── HealthCheckResource.java │ └── test │ └── java │ └── netflix │ └── adminresources │ └── HealthCheckResourceTest.java ├── karyon2-admin-web ├── README.md ├── build.gradle └── src │ ├── main │ ├── java │ │ ├── com │ │ │ └── google │ │ │ │ └── inject │ │ │ │ └── grapher │ │ │ │ └── KaryonAbstractInjectorGrapher.java │ │ └── netflix │ │ │ └── adminresources │ │ │ ├── pages │ │ │ ├── AdminPageResource.java │ │ │ ├── EnvPage.java │ │ │ ├── GuiceGraphPage.java │ │ │ ├── GuicePage.java │ │ │ ├── GuiceProvisionPage.java │ │ │ ├── JarsPage.java │ │ │ ├── JmxPage.java │ │ │ ├── KaryonGrapherModule.java │ │ │ └── PropertiesPage.java │ │ │ ├── resources │ │ │ ├── AllPropsResource.java │ │ │ ├── EnvironmentResource.java │ │ │ ├── GuiceResource.java │ │ │ ├── JarsInfoResource.java │ │ │ ├── JsonGrapher.java │ │ │ ├── KaryonAdminResponse.java │ │ │ ├── KaryonWebAdminModule.java │ │ │ ├── MaskedResourceHelper.java │ │ │ ├── PairResponse.java │ │ │ ├── PropertiesHelper.java │ │ │ ├── PropertiesResource.java │ │ │ ├── jmx │ │ │ │ ├── DynaTreeNode.java │ │ │ │ ├── JMXResource.java │ │ │ │ └── JmxService.java │ │ │ └── model │ │ │ │ ├── Property.java │ │ │ │ └── PropertySource.java │ │ │ └── tableview │ │ │ ├── DataTableHelper.java │ │ │ ├── PropsTableView.java │ │ │ └── TableViewResource.java │ └── resources │ │ ├── css │ │ └── d3.flameGraph.css │ │ ├── js │ │ ├── d3.flameGraph.js │ │ └── d3.tip.js │ │ └── webadmin │ │ ├── archprops │ │ ├── index.ftl │ │ └── index.js │ │ ├── env │ │ ├── index.ftl │ │ └── index.js │ │ ├── guice │ │ ├── index.ftl │ │ └── index.js │ │ ├── guicegraph │ │ ├── index.ftl │ │ └── index.js │ │ ├── guiceprovision │ │ ├── index.ftl │ │ └── index.js │ │ ├── home.ftl │ │ ├── home.js │ │ ├── jars │ │ ├── index.ftl │ │ └── index.js │ │ └── jmx │ │ ├── index.ftl │ │ ├── index.js │ │ ├── view.ftl │ │ └── view.js │ └── test │ ├── java │ └── netflix │ │ └── adminresources │ │ ├── WebAdminTest.java │ │ └── tableview │ │ └── PropsTableViewTest.java │ └── log4j.properties ├── karyon2-admin ├── README.md ├── build.gradle └── src │ ├── main │ ├── java │ │ └── netflix │ │ │ ├── admin │ │ │ ├── AdminConfigImpl.java │ │ │ ├── AdminContainerConfig.java │ │ │ ├── AdminExplorerManager.java │ │ │ ├── AdminFreemarkerTemplateProvider.java │ │ │ ├── AdminUtils.java │ │ │ ├── DefaultGlobalContextOverride.java │ │ │ ├── DefaultRedirectRules.java │ │ │ ├── GlobalModelContextOverride.java │ │ │ └── RedirectRules.java │ │ │ └── adminresources │ │ │ ├── AbstractAdminPageInfo.java │ │ │ ├── AdminPage.java │ │ │ ├── AdminPageInfo.java │ │ │ ├── AdminPageRegistry.java │ │ │ ├── AdminResourcesContainer.java │ │ │ ├── AdminResourcesFilter.java │ │ │ ├── KaryonAdminModule.java │ │ │ ├── LoggingFilter.java │ │ │ └── RedirectFilter.java │ └── resources │ │ ├── admin-explorers.properties │ │ └── baseserver-explorer.properties │ └── test │ ├── java │ └── netflix │ │ ├── admin │ │ ├── AdminPageRegistryTest.java │ │ └── AdminUtilsTest.java │ │ └── adminresources │ │ ├── AdminResourceTest.java │ │ └── AuthFilter.java │ └── resources │ └── log4j.properties ├── karyon2-archaius ├── README.md ├── build.gradle └── src │ └── main │ └── java │ └── netflix │ └── karyon │ └── archaius │ ├── ArchaiusBootstrap.java │ ├── ArchaiusBootstrapModule.java │ ├── DefaultPropertiesLoader.java │ └── PropertiesLoader.java ├── karyon2-core ├── README.md ├── build.gradle └── src │ ├── main │ └── java │ │ └── netflix │ │ └── karyon │ │ ├── ShutdownListener.java │ │ ├── health │ │ ├── AlwaysHealthyHealthCheck.java │ │ ├── HealthCheckHandler.java │ │ └── HealthCheckInvocationStrategy.java │ │ └── transport │ │ ├── KaryonTransport.java │ │ ├── RequestRouter.java │ │ ├── http │ │ ├── HttpInterceptorKey.java │ │ ├── HttpInterceptorSupport.java │ │ ├── HttpKeyEvaluationContext.java │ │ ├── HttpRequestHandler.java │ │ ├── HttpRequestHandlerBuilder.java │ │ ├── MethodConstraintKey.java │ │ ├── QueryStringDecoder.java │ │ ├── RegexUriConstraintKey.java │ │ ├── ServletStyleUriConstraintKey.java │ │ └── SimpleUriRouter.java │ │ └── interceptor │ │ ├── AbstractAttacher.java │ │ ├── AbstractInterceptorSupport.java │ │ ├── DuplexInterceptor.java │ │ ├── InboundInterceptor.java │ │ ├── InterceptorExecutor.java │ │ ├── InterceptorHolder.java │ │ ├── InterceptorKey.java │ │ ├── InterceptorSupport.java │ │ ├── KeyEvaluationContext.java │ │ └── OutboundInterceptor.java │ └── test │ └── java │ └── netflix │ └── karyon │ └── server │ ├── MockChannelHandlerContext.java │ ├── http │ ├── InterceptorConstraintTestBase.java │ ├── MethodConstraintTest.java │ ├── RegExConstraintTest.java │ └── ServletStyleConstraintTest.java │ └── interceptor │ ├── InterceptorExecutorTest.java │ ├── MockKey.java │ ├── TestableDuplexInterceptor.java │ ├── TestableInboundInterceptor.java │ ├── TestableOutboundInterceptor.java │ └── TestableRequestRouter.java ├── karyon2-eureka ├── README.md ├── build.gradle └── src │ └── main │ └── java │ └── netflix │ └── karyon │ └── eureka │ ├── DefaultEurekaKaryonStatusBridge.java │ ├── EurekaHealthCheckHandler.java │ ├── EurekaKaryonStatusBridge.java │ └── KaryonEurekaModule.java ├── karyon2-examples ├── README.md ├── build.gradle └── src │ └── main │ ├── java │ └── netflix │ │ └── karyon │ │ └── examples │ │ ├── hellonoss │ │ ├── README.md │ │ ├── common │ │ │ ├── LoggingInterceptor.java │ │ │ ├── auth │ │ │ │ ├── AuthInterceptor.java │ │ │ │ ├── AuthenticationService.java │ │ │ │ └── AuthenticationServiceImpl.java │ │ │ └── health │ │ │ │ └── HealthCheck.java │ │ └── server │ │ │ ├── jersey │ │ │ ├── HealthcheckResource.java │ │ │ ├── HelloworldResource.java │ │ │ ├── JerseyHelloWorldApp.java │ │ │ └── README.md │ │ │ ├── rxnetty │ │ │ ├── MyApplicationRunner.java │ │ │ ├── README.md │ │ │ └── RxNettyHandler.java │ │ │ └── simple │ │ │ ├── HelloWorldEndpoint.java │ │ │ ├── README.md │ │ │ ├── SimpleRouter.java │ │ │ ├── annotation │ │ │ ├── README.md │ │ │ └── SimpleRoutingApp.java │ │ │ └── module │ │ │ ├── README.md │ │ │ ├── RouterWithInterceptors.java │ │ │ └── SimpleRunner.java │ │ ├── tcp │ │ ├── README.md │ │ ├── TcpPipelineApp.java │ │ └── TcpPipelineHandlers.java │ │ └── websockets │ │ ├── README.md │ │ └── WebSocketEchoServer.java │ └── resources │ ├── eureka-client.properties │ ├── hello-netflix-oss-dev.properties │ ├── hello-netflix-oss.properties │ ├── sample-rxnetty-tcp-noss.properties │ └── simplelogger.properties ├── karyon2-governator ├── README.md ├── build.gradle └── src │ ├── main │ └── java │ │ └── netflix │ │ └── karyon │ │ ├── AbstractKaryonServer.java │ │ ├── Karyon.java │ │ ├── KaryonBootstrap.java │ │ ├── KaryonBootstrapModule.java │ │ ├── KaryonRunner.java │ │ ├── KaryonServer.java │ │ ├── KaryonServerBackedServer.java │ │ ├── MainClassBasedServer.java │ │ ├── RxNettyServerBackedServer.java │ │ ├── ShutdownModule.java │ │ ├── health │ │ └── SyncHealthCheckInvocationStrategy.java │ │ ├── transport │ │ ├── AbstractServerModule.java │ │ ├── http │ │ │ ├── GovernatorHttpInterceptorSupport.java │ │ │ ├── HttpRxServerProvider.java │ │ │ ├── KaryonHttpModule.java │ │ │ ├── health │ │ │ │ └── HealthCheckEndpoint.java │ │ │ └── websockets │ │ │ │ ├── KaryonWebSocketsModule.java │ │ │ │ └── WebSocketsRxServerProvider.java │ │ ├── tcp │ │ │ ├── KaryonTcpModule.java │ │ │ └── TcpRxServerProvider.java │ │ └── util │ │ │ └── HttpContentInputStream.java │ │ └── utils │ │ └── TypeUtils.java │ └── test │ └── java │ └── netflix │ └── karyon │ └── transport │ ├── http │ ├── KaryonHttpModuleTest.java │ └── websockets │ │ └── KaryonWebSocketsModuleTest.java │ └── tcp │ └── KaryonTcpModuleTest.java ├── karyon2-jersey-blocking ├── README.md ├── build.gradle └── src │ ├── main │ ├── java │ │ └── netflix │ │ │ └── karyon │ │ │ └── jersey │ │ │ └── blocking │ │ │ ├── JerseyBasedRouter.java │ │ │ ├── KaryonJerseyModule.java │ │ │ ├── NettyContainer.java │ │ │ ├── NettyContainerProvider.java │ │ │ ├── NettyToJerseyBridge.java │ │ │ ├── PropertiesBasedResourceConfig.java │ │ │ └── ServiceIteratorProviderImpl.java │ └── resources │ │ └── META-INF │ │ └── services │ │ └── com.sun.jersey.spi.container.ContainerProvider │ └── test │ └── java │ └── netflix │ └── karyon │ └── jersey │ └── blocking │ ├── JerseyBlockingModule.java │ ├── JerseyBlockingTest.java │ └── JsonReadingResource.java ├── karyon2-servo ├── README.md ├── build.gradle └── src │ └── main │ └── java │ └── netflix │ └── karyon │ └── servo │ └── KaryonServoModule.java ├── print_junit_reports.sh └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | 27 | # OS generated files # 28 | ###################### 29 | .DS_Store* 30 | ehthumbs.db 31 | Icon? 32 | Thumbs.db 33 | 34 | # Editor Files # 35 | ################ 36 | *~ 37 | *.swp 38 | 39 | # Gradle Files # 40 | ################ 41 | .gradle 42 | .m2 43 | 44 | # Build output directies 45 | /target 46 | **/target 47 | /build 48 | **/build 49 | /bin 50 | **/bin 51 | 52 | # IntelliJ specific files/directories 53 | out 54 | .idea 55 | *.ipr 56 | *.iws 57 | *.iml 58 | atlassian-ide-plugin.xml 59 | 60 | # Eclipse specific files/directories 61 | .classpath 62 | .project 63 | .settings 64 | .metadata 65 | 66 | # NetBeans specific files/directories 67 | .nbattrs 68 | 69 | *.class 70 | *.log 71 | **/deps 72 | -------------------------------------------------------------------------------- /.netflixoss: -------------------------------------------------------------------------------- 1 | pullrequest_cloudbees=false 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | sudo: false 5 | install: ./installViaTravis.sh 6 | script: ./buildViaTravis.sh 7 | after_failure: print_junit_reports.sh 8 | cache: 9 | directories: 10 | - $HOME/.gradle/caches/ 11 | env: 12 | global: 13 | - secure: DLWB16Ak6uB11U6pSqHlJz+IVVGJDun6qOlPTcwKAbZb8pSaxegK5vAu9/xTUgtq6ctjO0uAhxq66Fq+oQWrLIx0cdLWsdZ4kxJ9uq6TkNBCM2U4/NmSPHrIO0z3u107ehO8SKxHeWQpbNQF/Y80e4hvAAbgTfR9bXjC/zBtUhg= 14 | - secure: G3PMnpBAUlry+FNda0iL44wEG6T2q2hbJSRokJqw3qVyYc4b89MnF1gYZBJssawWoyyBybfha7ZIwMY9h5IpRVt3XE46VBMGq3aror9AV784e+pvFYvvRQgILrROL63nDehv3BrNYXrpvA6lxL6djRhitpb2GVuAvtVF2gHdO3s= 15 | - secure: RwfGxwmXIaHBq0Q+NVPeAHlj5yA841jU/HWOxYsOjwlKTcIN5QIZnbiweeK4nr0/RF3vBlD8SUY4BwVQT307Sbn4ZL1Yd3swMFoQd3ta9eJVRUEIiCeZpFMO9/vZUS7m7ddAl1NWcCee6Mh+L/F0FUrumUR4Vx2Xll5uKGqoDjM= 16 | - secure: oJJKAPfS7SOdmy1t0C/Tcyp8PxsYPUul/1E6YgjFSTIE+U0DDPh//kyCe/SvbqGeJy3JoW1KKYO7c9bD7VY/+LyEBML3O/RNFRKhc0Rxa0bCkmVb9pDBDeC/Xt3vNagK/GgFrXKgvWpzaeXT58jPnOq3fBDNMCz1iQrIIUtGio8= 17 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /OSSMETADATA: -------------------------------------------------------------------------------- 1 | osslifecycle=active 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ===== 2 | Karyon 2.0 is no longer supported. We are in the process of retiring Karyon in favor of using Governator for bootstrapping and OSS components with -guice or -governator subprojects. 3 | ===== 4 | 5 | 6 | karyon 7 | ====== 8 | 9 | [![Build Status](https://travis-ci.org/Netflix/karyon.svg)](https://travis-ci.org/Netflix/karyon/builds) 10 | 11 | Karyon in the context of molecular biology is essentially "a part of the cell containing DNA and RNA and responsible for growth and reproduction." 12 | 13 | At Netflix, Karyon is a framework and library that essentially contains the blueprint of what it means to implement a cloud ready web service. All the other fine grained web services and applications that form our SOA graph can essentially be thought as being cloned from this basic blueprint. 14 | 15 | Karyon can be thought of as a nucleus that contains the following main ingredients. 16 | 17 | * Bootstrapping , dependency and Lifecycle Management (via [Governator](https://github.com/Netflix/governator)) 18 | * Runtime Insights and Diagnostics (via `karyon-admin-web` module) 19 | * Configuration Management (via [Archaius](https://github.com/Netflix/archaius)) 20 | * Service discovery (via [Eureka](https://github.com/Netflix/eureka)) 21 | * Powerful transport module (via [RxNetty](https://github.com/Netflix/RxNetty)) 22 | 23 | Getting Started 24 | =============== 25 | 26 | Easiest way to get started with karyon is to see the examples provided with karyon under [karyon-examples](karyon2-examples) module. 27 | 28 | Documentation 29 | ============== 30 | 31 | Please see [wiki] (https://github.com/Netflix/karyon/wiki) for detailed documentation. 32 | 33 | Have a question? 34 | =============== 35 | 36 | We have a discussion group for karyon users (i.e. you!) here: https://groups.google.com/forum/?fromgroups#!forum/karyon-users 37 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { jcenter() } 3 | dependencies { 4 | classpath 'com.netflix.nebula:gradle-extra-configurations-plugin:2.2.0' 5 | } 6 | } 7 | 8 | plugins { 9 | id 'nebula.netflixoss' version '2.2.9' 10 | } 11 | 12 | ext { 13 | githubProjectName = "karyon" 14 | } 15 | 16 | subprojects { 17 | apply plugin: 'nebula.netflixoss' 18 | apply plugin: 'groovy' 19 | apply plugin: 'nebula.provided-base' 20 | apply plugin: "jacoco" 21 | 22 | group = "com.netflix.karyon" 23 | 24 | repositories { 25 | jcenter() 26 | } 27 | 28 | dependencies { 29 | compile 'org.slf4j:slf4j-api:1.7.6' 30 | testCompile 'junit:junit:4.10' 31 | } 32 | 33 | eclipse { 34 | classpath { 35 | downloadSources = true 36 | downloadJavadoc = true 37 | } 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /buildViaTravis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script will build the project. 3 | 4 | if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then 5 | echo -e "Build Pull Request #$TRAVIS_PULL_REQUEST => Branch [$TRAVIS_BRANCH]" 6 | ./gradlew build --stacktrace --info 7 | elif [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_TAG" == "" ]; then 8 | echo -e 'Build Branch with Snapshot => Branch ['$TRAVIS_BRANCH']' 9 | ./gradlew -Prelease.travisci=true -PbintrayUser="${bintrayUser}" -PbintrayKey="${bintrayKey}" -PsonatypeUsername="${sonatypeUsername}" -PsonatypePassword="${sonatypePassword}" build snapshot 10 | elif [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_TAG" != "" ]; then 11 | echo -e 'Build Branch for Release => Branch ['$TRAVIS_BRANCH'] Tag ['$TRAVIS_TAG']' 12 | case "$TRAVIS_TAG" in 13 | *-rc\.*) 14 | ./gradlew -Prelease.travisci=true -Prelease.useLastTag=true -PbintrayUser="${bintrayUser}" -PbintrayKey="${bintrayKey}" -PsonatypeUsername="${sonatypeUsername}" -PsonatypePassword="${sonatypePassword}" candidate 15 | ;; 16 | *) 17 | ./gradlew -Prelease.travisci=true -Prelease.useLastTag=true -PbintrayUser="${bintrayUser}" -PbintrayKey="${bintrayKey}" -PsonatypeUsername="${sonatypeUsername}" -PsonatypePassword="${sonatypePassword}" final 18 | ;; 19 | esac 20 | else 21 | echo -e 'WARN: Should not be here => Branch ['$TRAVIS_BRANCH'] Tag ['$TRAVIS_TAG'] Pull Request ['$TRAVIS_PULL_REQUEST']' 22 | ./gradlew build 23 | fi 24 | -------------------------------------------------------------------------------- /codequality/HEADER: -------------------------------------------------------------------------------- 1 | Copyright ${year} Netflix, Inc. 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 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012 Netflix, Inc. 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 | org.gradle.daemon=true 17 | 18 | rxnetty_version=0.4.7 19 | jersey_version=1.19.1 20 | governator_version=1.14.2 21 | pytheas_version=1.29.0 22 | apache_httpclient_version=4.2.1 23 | eureka_version=1.1.151 24 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netflix/karyon/d50bc0ff37693ef3fbda373e90a109d1f92e0b9a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Jan 26 11:58:20 PST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /images/Interceptors-Flow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netflix/karyon/d50bc0ff37693ef3fbda373e90a109d1f92e0b9a/images/Interceptors-Flow.jpg -------------------------------------------------------------------------------- /installViaTravis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script will build the project. 3 | 4 | if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then 5 | echo -e "Assemble Pull Request #$TRAVIS_PULL_REQUEST => Branch [$TRAVIS_BRANCH]" 6 | ./gradlew assemble 7 | elif [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_TAG" == "" ]; then 8 | echo -e 'Assemble Branch with Snapshot => Branch ['$TRAVIS_BRANCH']' 9 | ./gradlew -Prelease.travisci=true assemble 10 | elif [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_TAG" != "" ]; then 11 | echo -e 'Assemble Branch for Release => Branch ['$TRAVIS_BRANCH'] Tag ['$TRAVIS_TAG']' 12 | ./gradlew -Prelease.travisci=true -Prelease.useLastTag=true assemble 13 | else 14 | echo -e 'WARN: Should not be here => Branch ['$TRAVIS_BRANCH'] Tag ['$TRAVIS_TAG'] Pull Request ['$TRAVIS_PULL_REQUEST']' 15 | ./gradlew assemble 16 | fi 17 | -------------------------------------------------------------------------------- /karyon2-admin-plugins/karyon-admin-healthcheck-plugin/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Netflix, Inc. 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 | apply plugin: 'osgi' 17 | 18 | tasks.withType(Javadoc).each { 19 | it.classpath = sourceSets.main.compileClasspath 20 | } 21 | 22 | dependencies { 23 | compile ('com.netflix.karyon:karyon-eureka:1.+') 24 | compile project(':karyon2-admin') 25 | 26 | testCompile 'org.slf4j:slf4j-log4j12:1.7.2' 27 | } 28 | 29 | eclipse { 30 | classpath { 31 | // include 'provided' dependencies on the classpath 32 | plusConfigurations += configurations.provided 33 | downloadSources = true 34 | downloadJavadoc = true 35 | } 36 | } 37 | 38 | idea { 39 | module { 40 | // include 'provided' dependencies on the classpath 41 | scopes.PROVIDED.plus += configurations.provided 42 | scopes.PROVIDED.plus += configurations.provided 43 | } 44 | } 45 | 46 | jar { 47 | manifest { 48 | name = 'karyon-admin-healthcheck-plugin' 49 | instruction 'Bundle-Vendor', 'Netflix' 50 | instruction 'Bundle-DocURL', 'https://github.com/Netflix/karyon' 51 | instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /karyon2-admin-plugins/karyon-admin-healthcheck-plugin/src/main/java/com/netflix/adminresources/HealthcheckResource.java: -------------------------------------------------------------------------------- 1 | package com.netflix.adminresources; 2 | 3 | import com.google.inject.Inject; 4 | import com.netflix.karyon.server.eureka.HealthCheckInvocationStrategy; 5 | import com.sun.jersey.spi.resource.Singleton; 6 | 7 | import javax.ws.rs.GET; 8 | import javax.ws.rs.Path; 9 | import javax.ws.rs.core.Response; 10 | import java.util.concurrent.TimeoutException; 11 | 12 | @Path("/v2/healthcheck") 13 | @Singleton 14 | public class HealthcheckResource { 15 | 16 | @Inject(optional = true) 17 | private HealthCheckInvocationStrategy invocationStrategy; 18 | 19 | @GET 20 | public Response doHealthCheck() { 21 | if (null != invocationStrategy) { 22 | try { 23 | int status = invocationStrategy.invokeCheck(); 24 | return Response.status(status).build(); 25 | 26 | } catch (TimeoutException e) { 27 | return Response.status(Response.Status.SERVICE_UNAVAILABLE).build(); 28 | 29 | } 30 | 31 | } else { 32 | return Response.status(Response.Status.NOT_FOUND).build(); 33 | 34 | } 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /karyon2-admin-plugins/karyon-admin-healthcheck-plugin/src/main/java/netflix/adminresources/HealthCheckPlugin.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources; 2 | 3 | @AdminPage 4 | public class HealthCheckPlugin extends AbstractAdminPageInfo { 5 | 6 | public static final String PAGE_ID = "karyon_healthCheck"; 7 | public static final String NAME = "HealthCheck"; 8 | 9 | public HealthCheckPlugin() { 10 | super(PAGE_ID, NAME); 11 | } 12 | 13 | @Override 14 | public String getJerseyResourcePackageList() { 15 | return "com.netflix.adminresources"; 16 | } 17 | 18 | @Override 19 | public boolean isVisible() { 20 | return false; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /karyon2-admin-plugins/karyon-admin-healthcheck-plugin/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012 Netflix, Inc. 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 | log4j.rootLogger=INFO, console 18 | 19 | log4j.appender.console=org.apache.log4j.ConsoleAppender 20 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 21 | log4j.appender.console.layout.ConversionPattern=%d %-5p %c{1}:%L %x %m [%t]%n 22 | log4j.logger.com.sun.jersey=TRACE -------------------------------------------------------------------------------- /karyon2-admin-plugins/karyon2-admin-eureka-plugin/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Netflix, Inc. 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 | apply plugin: 'osgi' 17 | 18 | tasks.withType(Javadoc).each { 19 | it.classpath = sourceSets.main.compileClasspath 20 | } 21 | 22 | dependencies { 23 | dependencies { 24 | compile project(':karyon2-admin-web') 25 | compile "com.netflix.eureka:eureka-client:${eureka_version}" 26 | } 27 | } 28 | 29 | eclipse { 30 | classpath { 31 | // include 'provided' dependencies on the classpath 32 | plusConfigurations += configurations.provided 33 | 34 | downloadSources = true 35 | downloadJavadoc = true 36 | } 37 | } 38 | 39 | idea { 40 | module { 41 | // include 'provided' dependencies on the classpath 42 | scopes.PROVIDED.plus += configurations.provided 43 | scopes.PROVIDED.plus += configurations.provided 44 | } 45 | } 46 | 47 | jar { 48 | manifest { 49 | name = 'karyon2-admin-eureka-plugin' 50 | instruction 'Bundle-Vendor', 'Netflix' 51 | instruction 'Bundle-DocURL', 'https://github.com/Netflix/karyon' 52 | instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /karyon2-admin-plugins/karyon2-admin-eureka-plugin/src/main/java/netflix/adminresources/pages/EurekaPage.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.pages; 2 | 3 | import netflix.adminresources.AbstractAdminPageInfo; 4 | import netflix.adminresources.AdminPage; 5 | 6 | @AdminPage 7 | public class EurekaPage extends AbstractAdminPageInfo { 8 | 9 | public static final String PAGE_ID = "eureka"; 10 | public static final String NAME = "Eureka"; 11 | 12 | public EurekaPage() { 13 | super(PAGE_ID, NAME); 14 | } 15 | } -------------------------------------------------------------------------------- /karyon2-admin-plugins/karyon2-admin-eureka-plugin/src/main/resources/webadmin/eureka/index.ftl: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 |
12 | -------------------------------------------------------------------------------- /karyon2-admin-plugins/karyon2-admin-eureka-plugin/src/main/resources/webadmin/eureka/index.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | "use strict"; 3 | 4 | $("#status-error").html(""); 5 | 6 | var source = "${ajax_base}/eureka"; 7 | 8 | var oTable = $('#discovery-table').dataTable( { 9 | "aoColumns": [ 10 | {"sTitle" : "Application", "mDataProp" : "application"}, 11 | {"sTitle" : "Instance Id", "mDataProp" : "id"}, 12 | {"sTitle" : "Status", "mDataProp" : "status"}, 13 | {"sTitle" : "IP Address", "mDataProp" : "ipAddress"}, 14 | {"sTitle" : "Hostname", "mDataProp" : "hostName"} 15 | ], 16 | "sAjaxSource": source, 17 | "fnServerData": function ( sSource, aoData, fnCallback ) { 18 | $.getJSON(sSource) 19 | .success(function(json) { 20 | $("#status-error").html(""); 21 | $("#status-lastupdate").html(new Date().format()); 22 | if (json.error) { 23 | $("#status-error").html(json.error.message); 24 | $("#status-error").addClass("status-error"); 25 | } 26 | else { 27 | $("#status-error").removeClass("status-error"); 28 | fnCallback({"aaData": json.data}); 29 | } 30 | }) 31 | .error(function(jqXHR, textStatus, errorThrown) { 32 | $("#status-error").html(textStatus + ": " + errorThrown); 33 | $("#status-error").addClass("status-error"); 34 | }); 35 | }, 36 | "bPaginate" : false, 37 | "bLengthChange" : false, 38 | "bAutoWidth" : false, 39 | "bFilter" : false, 40 | "fnInfoCallback": function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) { 41 | $("#status-visible").html(iTotal); 42 | $("#status-total").html(iMax); 43 | return ""; 44 | } 45 | }); 46 | 47 | $(".bse-filter").val(""); 48 | 49 | $(".bse-filter").die("keyup").live("keyup", function() { 50 | $('#discovery-table').dataTable().fnFilter($(".bse-filter").val(), null, false, true); 51 | }); 52 | 53 | $(".bse-refresh").die("click").live("click", function() { 54 | $('#discovery-table').dataTable().fnReloadAjax(); 55 | }); 56 | }); -------------------------------------------------------------------------------- /karyon2-admin-plugins/karyon2-admin-healthcheck-plugin/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Netflix, Inc. 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 | apply plugin: 'osgi' 17 | 18 | tasks.withType(Javadoc).each { 19 | it.classpath = sourceSets.main.compileClasspath 20 | } 21 | 22 | dependencies { 23 | dependencies { 24 | compile project(':karyon2-core') 25 | compile project(':karyon2-governator') 26 | compile project(':karyon2-admin-web') 27 | } 28 | } 29 | 30 | eclipse { 31 | classpath { 32 | // include 'provided' dependencies on the classpath 33 | plusConfigurations += configurations.provided 34 | 35 | downloadSources = true 36 | downloadJavadoc = true 37 | } 38 | } 39 | 40 | idea { 41 | module { 42 | // include 'provided' dependencies on the classpath 43 | scopes.PROVIDED.plus += configurations.provided 44 | scopes.PROVIDED.plus += configurations.provided 45 | } 46 | } 47 | 48 | jar { 49 | manifest { 50 | name = 'karyon2-admin-healthcheck-plugin' 51 | instruction 'Bundle-Vendor', 'Netflix' 52 | instruction 'Bundle-DocURL', 'https://github.com/Netflix/karyon' 53 | instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /karyon2-admin-plugins/karyon2-admin-healthcheck-plugin/src/main/java/netflix/adminresources/HealthCheckPlugin.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources; 2 | 3 | @AdminPage 4 | public class HealthCheckPlugin extends AbstractAdminPageInfo { 5 | 6 | public static final String PAGE_ID = "karyon2_healthCheck"; 7 | public static final String NAME = "HealthCheck"; 8 | 9 | public HealthCheckPlugin() { 10 | super(PAGE_ID, NAME); 11 | } 12 | 13 | @Override 14 | public String getJerseyResourcePackageList() { 15 | return "netflix.adminresources"; 16 | } 17 | 18 | @Override 19 | public boolean isVisible() { 20 | return false; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /karyon2-admin-plugins/karyon2-admin-healthcheck-plugin/src/main/java/netflix/adminresources/HealthCheckResource.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources; 2 | 3 | import com.google.inject.Inject; 4 | import com.google.inject.Singleton; 5 | import netflix.karyon.health.HealthCheckHandler; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import javax.ws.rs.GET; 10 | import javax.ws.rs.Path; 11 | import javax.ws.rs.Produces; 12 | import javax.ws.rs.core.MediaType; 13 | import javax.ws.rs.core.Response; 14 | 15 | @Path("/healthcheck") 16 | @Produces(MediaType.TEXT_HTML) 17 | @Singleton 18 | public class HealthCheckResource { 19 | private static final Logger logger = LoggerFactory.getLogger(HealthCheckResource.class); 20 | private HealthCheckHandler healthCheckHandler; 21 | 22 | @Inject 23 | public HealthCheckResource(HealthCheckHandler healthCheckHandler) { 24 | this.healthCheckHandler = healthCheckHandler; 25 | } 26 | 27 | @GET 28 | public Response getHealthCheck() { 29 | try { 30 | final int status = healthCheckHandler.getStatus(); 31 | return Response.ok().status(status).build(); 32 | } catch (Exception e) { 33 | logger.error("Exception in HealthCheckResource -- ", e); 34 | } 35 | return Response.status(Response.Status.BAD_REQUEST.getStatusCode()).build(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /karyon2-admin-web/README.md: -------------------------------------------------------------------------------- 1 | karyon-admin-web 2 | ====== 3 | 4 | The karyon web administration interface module. 5 | 6 | #### Guice Module 7 | 8 | [KaryonWebAdminModule](src/main/java/netflix/adminresources/resources/KaryonWebAdminModule.java) provides necessary guice bindings to use this web interface. 9 | 10 | See the [hello world example](../karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server) for a sample. 11 | -------------------------------------------------------------------------------- /karyon2-admin-web/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Netflix, Inc. 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 | apply plugin: 'osgi' 17 | 18 | dependencies { 19 | compile project(':karyon2-admin') 20 | compile "org.apache.httpcomponents:httpclient:${apache_httpclient_version}" 21 | compile 'com.google.code.gson:gson:2.1' 22 | runtime 'org.freemarker:freemarker:2.3.15' 23 | runtime 'org.codehaus.jackson:jackson-mapper-asl:1.9.11' 24 | } 25 | 26 | jar { 27 | manifest { 28 | name = 'karyon2-admin-web' 29 | instruction 'Bundle-Vendor', 'Netflix' 30 | instruction 'Bundle-DocURL', 'https://github.com/Netflix/karyon' 31 | instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/pages/EnvPage.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.pages; 2 | 3 | 4 | import netflix.adminresources.AbstractAdminPageInfo; 5 | import netflix.adminresources.AdminPage; 6 | 7 | @AdminPage 8 | public class EnvPage extends AbstractAdminPageInfo { 9 | 10 | public static final String PAGE_ID = "env"; 11 | public static final String NAME = "Environment"; 12 | 13 | public EnvPage() { 14 | super(PAGE_ID, NAME); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/pages/GuiceGraphPage.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.pages; 2 | 3 | import com.google.inject.Module; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import netflix.adminresources.AbstractAdminPageInfo; 9 | import netflix.adminresources.AdminPage; 10 | 11 | @AdminPage 12 | public class GuiceGraphPage extends AbstractAdminPageInfo { 13 | 14 | public static final String PAGE_ID = "guicegraph"; 15 | public static final String NAME = "GuiceGraph"; 16 | 17 | public GuiceGraphPage() { 18 | super(PAGE_ID, NAME); 19 | } 20 | 21 | @Override 22 | public List getGuiceModules() { 23 | return Arrays.asList(new KaryonGrapherModule()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/pages/GuicePage.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.pages; 2 | 3 | import com.google.inject.Module; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import netflix.adminresources.AbstractAdminPageInfo; 9 | import netflix.adminresources.AdminPage; 10 | 11 | @AdminPage 12 | public class GuicePage extends AbstractAdminPageInfo { 13 | 14 | public static final String PAGE_ID = "guice"; 15 | public static final String NAME = "Guice"; 16 | 17 | public GuicePage() { 18 | super(PAGE_ID, NAME); 19 | } 20 | 21 | @Override 22 | public List getGuiceModules() { 23 | return Arrays.asList(new KaryonGrapherModule()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/pages/GuiceProvisionPage.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.pages; 2 | 3 | import com.google.inject.Module; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import netflix.adminresources.AbstractAdminPageInfo; 9 | import netflix.adminresources.AdminPage; 10 | 11 | @AdminPage 12 | public class GuiceProvisionPage extends AbstractAdminPageInfo { 13 | 14 | public static final String PAGE_ID = "guiceprovision"; 15 | public static final String NAME = "GuiceProvision"; 16 | 17 | public GuiceProvisionPage() { 18 | super(PAGE_ID, NAME); 19 | } 20 | 21 | @Override 22 | public List getGuiceModules() { 23 | return Arrays.asList(new KaryonGrapherModule()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/pages/JarsPage.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.pages; 2 | 3 | import netflix.adminresources.AbstractAdminPageInfo; 4 | import netflix.adminresources.AdminPage; 5 | 6 | @AdminPage 7 | public class JarsPage extends AbstractAdminPageInfo { 8 | 9 | public static final String PAGE_ID = "jars"; 10 | public static final String NAME = "Jars"; 11 | 12 | public JarsPage() { 13 | super(PAGE_ID, NAME); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/pages/JmxPage.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.pages; 2 | 3 | import netflix.adminresources.AbstractAdminPageInfo; 4 | import netflix.adminresources.AdminPage; 5 | 6 | @AdminPage 7 | public class JmxPage extends AbstractAdminPageInfo { 8 | 9 | public static final String PAGE_ID = "jmx"; 10 | public static final String NAME = "JMX"; 11 | 12 | public JmxPage() { 13 | super(PAGE_ID, NAME); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/pages/KaryonGrapherModule.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.pages; 2 | 3 | import com.google.inject.AbstractModule; 4 | import com.google.inject.grapher.NameFactory; 5 | import com.google.inject.grapher.ShortNameFactory; 6 | import com.google.inject.grapher.graphviz.PortIdFactory; 7 | import com.google.inject.grapher.graphviz.PortIdFactoryImpl; 8 | 9 | public class KaryonGrapherModule extends AbstractModule { 10 | 11 | @Override 12 | protected void configure() { 13 | bind(NameFactory.class).to(ShortNameFactory.class); 14 | bind(PortIdFactory.class).to(PortIdFactoryImpl.class); 15 | } 16 | 17 | @Override 18 | public int hashCode() { 19 | return getClass().hashCode(); 20 | } 21 | 22 | @Override 23 | public boolean equals(Object obj) { 24 | return getClass().equals(obj.getClass()); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/pages/PropertiesPage.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.pages; 2 | 3 | 4 | import netflix.adminresources.AbstractAdminPageInfo; 5 | import netflix.adminresources.AdminPage; 6 | 7 | @AdminPage 8 | public class PropertiesPage extends AbstractAdminPageInfo { 9 | 10 | public static final String PAGE_ID = "archprops"; 11 | public static final String NAME = "Archaius"; 12 | 13 | public PropertiesPage() { 14 | super(PAGE_ID, NAME); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/resources/AllPropsResource.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.resources; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import netflix.adminresources.resources.model.Property; 6 | 7 | import javax.ws.rs.GET; 8 | import javax.ws.rs.Path; 9 | import javax.ws.rs.Produces; 10 | import javax.ws.rs.core.MediaType; 11 | import javax.ws.rs.core.Response; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | 16 | @Path("/allprops") 17 | @Produces(MediaType.APPLICATION_JSON) 18 | public class AllPropsResource { 19 | 20 | public static class PropsResponse { 21 | private Map props; 22 | 23 | public PropsResponse(Map props) { 24 | this.props = props; 25 | } 26 | 27 | public Map getProps() { 28 | return props; 29 | } 30 | } 31 | 32 | @GET 33 | public Response getAllProperties() { 34 | final List allProperties = PropertiesHelper.getAllProperties(); 35 | GsonBuilder gsonBuilder = new GsonBuilder().serializeNulls(); 36 | Gson gson = gsonBuilder.create(); 37 | String propsJson = gson.toJson(new PropsResponse(PropertiesHelper.buildPropertiesMap(allProperties))); 38 | return Response.ok(propsJson).build(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/resources/KaryonAdminResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Netflix, Inc. 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 netflix.adminresources.resources; 18 | 19 | /** 20 | * @author Nitesh Kant 21 | */ 22 | public class KaryonAdminResponse { 23 | 24 | private Object data; 25 | 26 | public KaryonAdminResponse(Object data) { 27 | this.data = data; 28 | } 29 | 30 | public Object getData() { 31 | return data; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/resources/KaryonWebAdminModule.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.resources; 2 | 3 | import netflix.adminresources.KaryonAdminModule; 4 | 5 | public class KaryonWebAdminModule extends KaryonAdminModule { 6 | 7 | @Override 8 | protected void configure() { 9 | super.configure(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/resources/MaskedResourceHelper.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.resources; 2 | 3 | import com.google.common.annotations.VisibleForTesting; 4 | import com.google.common.base.Splitter; 5 | import com.netflix.config.DynamicPropertyFactory; 6 | 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | public class MaskedResourceHelper { 11 | @VisibleForTesting 12 | public static final String MASKED_PROPERTY_NAMES = "netflix.platform.admin.resources.masked.property.names"; 13 | public static final String MASKED_ENV_NAMES = "netflix.platform.admin.resources.masked.env.names"; 14 | public static final String MASKED_PROPERTY_VALUE = "**** MASKED ****"; 15 | 16 | private static final Splitter SPLITTER = Splitter.on(',') 17 | .trimResults() 18 | .omitEmptyStrings(); 19 | 20 | public static Set getMaskedPropertiesSet() { 21 | String maskedResourceNames = DynamicPropertyFactory.getInstance().getStringProperty(MASKED_PROPERTY_NAMES, "").get(); 22 | Set maskedPropertiesSet = getMaskedResourceSet(maskedResourceNames); 23 | // add the MASKED_PROPERTY_NAMES property, itself, for super-duper security-obscurity 24 | maskedPropertiesSet.add(MASKED_PROPERTY_NAMES); 25 | return maskedPropertiesSet; 26 | } 27 | 28 | public static Set getMaskedEnvSet() { 29 | String maskedResourceNames = DynamicPropertyFactory.getInstance().getStringProperty(MASKED_ENV_NAMES, "").get(); 30 | return getMaskedResourceSet(maskedResourceNames); 31 | } 32 | 33 | 34 | private static Set getMaskedResourceSet(String maskedResourceNames) { 35 | Iterable maskedResourceNamesIter = SPLITTER.split(maskedResourceNames); 36 | 37 | Set maskedResourceSet = new HashSet(); 38 | for (String maskedResource : maskedResourceNamesIter) { 39 | maskedResourceSet.add(maskedResource); 40 | } 41 | return maskedResourceSet; 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/resources/PairResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Netflix, Inc. 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 netflix.adminresources.resources; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Map; 22 | 23 | /** 24 | * @author Nitesh Kant 25 | */ 26 | public class PairResponse { 27 | 28 | List data; 29 | 30 | public PairResponse() { 31 | data = new ArrayList(); 32 | } 33 | 34 | public PairResponse(Map input) { 35 | this(); 36 | for (Map.Entry entry : input.entrySet()) { 37 | data.add(new Pair(String.valueOf(entry.getKey()), entry.getValue())); 38 | } 39 | } 40 | 41 | public void addEntry(String name, String value) { 42 | data.add(new Pair(name, value)); 43 | } 44 | 45 | private static class Pair { 46 | 47 | private String name; 48 | private Object value; 49 | 50 | private Pair(String name, Object value) { 51 | this.name = name; 52 | this.value = value; 53 | } 54 | 55 | public String getName() { 56 | return name; 57 | } 58 | 59 | public Object getValue() { 60 | return value; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/resources/PropertiesHelper.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.resources; 2 | 3 | import com.netflix.config.ConfigurationManager; 4 | import netflix.adminresources.resources.model.Property; 5 | import org.apache.commons.configuration.AbstractConfiguration; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.util.*; 10 | 11 | public class PropertiesHelper { 12 | private static final Logger LOG = LoggerFactory.getLogger(PropertiesHelper.class); 13 | 14 | public static List getAllProperties() { 15 | final AbstractConfiguration configInstance = ConfigurationManager.getConfigInstance(); 16 | List properties = new ArrayList(); 17 | Iterator keys = null; 18 | try { 19 | keys = configInstance.getKeys(); 20 | } catch (Exception e) { 21 | LOG.error("Exception fetching all property keys ", e); 22 | } 23 | 24 | Set maskedResources = MaskedResourceHelper.getMaskedPropertiesSet(); 25 | 26 | while (keys.hasNext()) { 27 | final String key = (String) keys.next(); 28 | try { 29 | Object value = null; 30 | // mask the specified properties 31 | if (maskedResources.contains(key)) { 32 | value = MaskedResourceHelper.MASKED_PROPERTY_VALUE; 33 | } else { 34 | value = configInstance.getProperty(key); 35 | } 36 | Property property = new Property(key, value.toString(), null); 37 | properties.add(property); 38 | } catch (Exception e) { 39 | LOG.info("Exception fetching property value for key " + key, e); 40 | } 41 | 42 | } 43 | return properties; 44 | } 45 | 46 | public static Map buildPropertiesMap(List properties) { 47 | Map propsMap = new HashMap<>(); 48 | for (Property prop : properties) { 49 | propsMap.put(prop.getName(), prop.getValue()); 50 | } 51 | return propsMap; 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/resources/PropertiesResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Netflix, Inc. 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 netflix.adminresources.resources; 18 | 19 | import com.google.common.annotations.Beta; 20 | import com.google.gson.Gson; 21 | import com.google.gson.JsonObject; 22 | import com.google.inject.Inject; 23 | import netflix.adminresources.tableview.DataTableHelper; 24 | import netflix.adminresources.tableview.PropsTableView; 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | 28 | import javax.ws.rs.GET; 29 | import javax.ws.rs.Path; 30 | import javax.ws.rs.Produces; 31 | import javax.ws.rs.core.Context; 32 | import javax.ws.rs.core.MediaType; 33 | import javax.ws.rs.core.MultivaluedMap; 34 | import javax.ws.rs.core.Response; 35 | import javax.ws.rs.core.UriInfo; 36 | 37 | @Beta 38 | @Path("/archprops") 39 | @Produces(MediaType.APPLICATION_JSON) 40 | public class PropertiesResource { 41 | private static final Logger LOG = LoggerFactory.getLogger(PropertiesResource.class); 42 | 43 | @Inject(optional = true) 44 | private PropsTableView adminPropsResource; 45 | 46 | @GET 47 | public Response getProperties(@Context UriInfo uriInfo) { 48 | if (adminPropsResource != null) { 49 | MultivaluedMap queryParams = uriInfo.getQueryParameters(); 50 | JsonObject output = DataTableHelper.buildOutput(adminPropsResource, queryParams); 51 | return Response.ok().entity(new Gson().toJson(output)).build(); 52 | } else { 53 | return Response.status(Response.Status.BAD_REQUEST).build(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/resources/model/Property.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.resources.model; 2 | 3 | import javax.xml.bind.annotation.XmlRootElement; 4 | import java.util.List; 5 | 6 | @XmlRootElement(name = "property") 7 | public class Property { 8 | private String name; 9 | private String value; 10 | private List sources; 11 | 12 | public Property(String name, String value, List sources) { 13 | this.name = name; 14 | this.value = value; 15 | this.sources = sources; 16 | } 17 | 18 | public Property() { 19 | 20 | } 21 | 22 | public String getName() { 23 | return name; 24 | } 25 | 26 | public void setName(String name) { 27 | this.name = name; 28 | } 29 | 30 | public String getValue() { 31 | return value; 32 | } 33 | 34 | public void setValue(String value) { 35 | this.value = value; 36 | } 37 | 38 | public List getSources() { 39 | return sources; 40 | } 41 | 42 | public void setSources(List sources) { 43 | this.sources = sources; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return "Property [name=" + name + ", value=" + value + ", sources=" + sources + "]"; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/resources/model/PropertySource.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.resources.model; 2 | 3 | public class PropertySource { 4 | private String sourceName; 5 | private String value; 6 | 7 | public PropertySource() { 8 | } 9 | 10 | public PropertySource(String sourceName, String value) { 11 | this.sourceName = sourceName; 12 | this.value = value; 13 | } 14 | 15 | public String getSourceName() { 16 | return sourceName; 17 | } 18 | 19 | public void setSourceName(String sourceName) { 20 | this.sourceName = sourceName; 21 | } 22 | 23 | public String getValue() { 24 | return value; 25 | } 26 | 27 | public void setValue(String value) { 28 | this.value = value; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "PropertySource [sourceName=" + sourceName + ", value=" + value + "]"; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/java/netflix/adminresources/tableview/TableViewResource.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources.tableview; 2 | 3 | import com.google.gson.JsonArray; 4 | 5 | import java.util.List; 6 | 7 | public interface TableViewResource { 8 | 9 | List getColumns(); 10 | 11 | TableViewResource setColumnSearchTerm(String column, String term); 12 | 13 | TableViewResource setAllColumnsSearchTerm(String term); 14 | 15 | TableViewResource enableColumnSort(String column, boolean isDescending); 16 | 17 | JsonArray getData(); 18 | 19 | int getTotalNumOfRecords(); 20 | 21 | int getFilteredNumOfRecords(); 22 | 23 | TableViewResource setCurrentPageInfo(int startIndex, int count); 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/css/d3.flameGraph.css: -------------------------------------------------------------------------------- 1 | .d3-flame-graph rect { 2 | stroke: #EEEEEE; 3 | fill-opacity: .8; 4 | } 5 | 6 | .d3-flame-graph rect:hover { 7 | stroke: #474747; 8 | stroke-width: 0.5; 9 | cursor: pointer; 10 | } 11 | 12 | .d3-flame-graph .label { 13 | pointer-events: none; 14 | white-space: nowrap; 15 | text-overflow: ellipsis; 16 | overflow: hidden; 17 | font-size: 12px; 18 | font-family: Verdana; 19 | margin-left: 4px; 20 | margin-right: 4px; 21 | line-height: 1.5; 22 | padding: 0 0 0; 23 | font-weight: 400; 24 | color: black; 25 | text-align: left; 26 | } 27 | 28 | .d3-flame-graph .fade { 29 | opacity: 0.6 !important; 30 | } 31 | 32 | .d3-flame-graph .title { 33 | font-size: 20px; 34 | font-family: Verdana; 35 | } 36 | 37 | .d3-flame-graph-tip { 38 | line-height: 1; 39 | font-family: Verdana; 40 | font-size: 12px; 41 | padding: 12px; 42 | background: rgba(0, 0, 0, 0.8); 43 | color: #fff; 44 | border-radius: 2px; 45 | pointer-events: none; 46 | } 47 | 48 | /* Creates a small triangle extender for the tooltip */ 49 | .d3-flame-graph-tip:after { 50 | box-sizing: border-box; 51 | display: inline; 52 | font-size: 10px; 53 | width: 100%; 54 | line-height: 1; 55 | color: rgba(0, 0, 0, 0.8); 56 | position: absolute; 57 | pointer-events: none; 58 | } 59 | 60 | /* Northward tooltips */ 61 | .d3-flame-graph-tip.n:after { 62 | content: "\25BC"; 63 | margin: -1px 0 0 0; 64 | top: 100%; 65 | left: 0; 66 | text-align: center; 67 | } 68 | 69 | /* Eastward tooltips */ 70 | .d3-flame-graph-tip.e:after { 71 | content: "\25C0"; 72 | margin: -4px 0 0 0; 73 | top: 50%; 74 | left: -8px; 75 | } 76 | 77 | /* Southward tooltips */ 78 | .d3-flame-graph-tip.s:after { 79 | content: "\25B2"; 80 | margin: 0 0 1px 0; 81 | top: -8px; 82 | left: 0; 83 | text-align: center; 84 | } 85 | 86 | /* Westward tooltips */ 87 | .d3-flame-graph-tip.w:after { 88 | content: "\25B6"; 89 | margin: -4px 0 0 -1px; 90 | top: 50%; 91 | left: 100%; 92 | } -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/archprops/index.ftl: -------------------------------------------------------------------------------- 1 | 4 | 5 | 73 | 74 | <#import "/layout/bootstrap/form.ftl" as form/> 75 | <#import "/layout/bootstrap/bootstrap.ftl" as bs/> 76 | 77 | 78 |
79 | 80 | 81 | 82 | <@form.modalform action="/webadmin/props" id="property-new-template" title="New property" class="span10"> 83 | <@form.modalbody> 84 | <@form.text label="Property Name" name="name" /> 85 | <@form.textarea label="Property Value" name="value"/> 86 | 87 | 88 | <@form.modalfooter> 89 | <@form.submit "Create"/> 90 | <@form.cancel "Cancel"/> 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/archprops/index.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | "use strict"; 3 | 4 | $("#status-error").html(""); 5 | var source = "${ajax_base}/archprops"; 6 | 7 | $('#props-table').dataTable({ 8 | "aoColumns": [ 9 | { "sTitle": "Name", "sWidth" : "30%", "sDefaultContent" : "-" }, 10 | { "sTitle": "Value", "sWidth" : "70%", "sDefaultContent" : "-"} 11 | ], 12 | "sAjaxSource" : source, 13 | "fnServerData" : function (sSource, aoData, fnCallback) { 14 | $.getJSON(sSource, aoData, function (json) { 15 | $("#status-lastupdate").html(new Date().format()); 16 | if (json.iTotalDisplayRecords) { 17 | $("#status-visible").html(json.iTotalDisplayRecords); 18 | } 19 | if (json.iTotalRecords) { 20 | $("#status-total").html(json.iTotalRecords); 21 | } 22 | fnCallback(json); 23 | }); 24 | }, 25 | "bLengthChange" : false, 26 | "bServerSide" : true, 27 | "bProcessing" : true, 28 | "sPaginationType": "bootstrap", 29 | "iDisplayLength" : 50, 30 | "bDestroy" : true, 31 | "bFilter" : true, 32 | "bAutoWidth" : false, 33 | "fnInfoCallback" : function (oSettings, iStart, iEnd, iMax, iTotal, sPre) { 34 | $("#status-visible").html(iTotal); 35 | $("#status-total").html(iMax); 36 | return ""; 37 | } 38 | }); 39 | 40 | $(".bse-filter").val(""); 41 | $("#props-table_filter").hide(); 42 | 43 | $(".bse-filter").die("keyup").live("keyup", function () { 44 | $('#props-table').dataTable().fnFilter($(".bse-filter").val(), null, false, true); 45 | }); 46 | 47 | $(".bse-refresh").die("click").live("click", function () { 48 | $('#props-table').dataTable().fnReloadAjax(); 49 | }); 50 | }); -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/env/index.ftl: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | 14 |
15 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/env/index.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | "use strict"; 3 | 4 | $("#status-error").html(""); 5 | 6 | var source = "${ajax_base}/env"; 7 | 8 | var oTable = $('#env-table').dataTable( { 9 | "aoColumns": [ 10 | { "sTitle" : "Name", 'sWidth' : '50%' }, 11 | { "sTitle" : "Value", 'sWidth' : '50%' } 12 | ], 13 | "sAjaxSource": source, 14 | "fnServerData": function ( sSource, aoData, fnCallback ) { 15 | $.getJSON(sSource) 16 | .success(function(json) { 17 | $("#status-error").html(""); 18 | $("#status-lastupdate").html(new Date().format()); 19 | if (json.error) { 20 | $("#status-error").html(json.error.message); 21 | $("#status-error").addClass("status-error"); 22 | } 23 | else { 24 | $("#status-error").removeClass("status-error"); 25 | var items = []; 26 | var envObj = json.env; 27 | for (var key in envObj) { 28 | if (envObj.hasOwnProperty(key)) { 29 | items.push([key, json.env[key]]); 30 | } 31 | } 32 | fnCallback({"aaData": items}); 33 | } 34 | }) 35 | .error(function(jqXHR, textStatus, errorThrown) { 36 | $("#status-error").html(textStatus + ": " + errorThrown); 37 | $("#status-error").addClass("status-error"); 38 | }); 39 | }, 40 | "bPaginate" : false, 41 | "bLengthChange" : false, 42 | "bDestroy" : true, 43 | "bFilter" : true, 44 | "fnInfoCallback" : function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) { 45 | $("#status-visible").html(iTotal); 46 | $("#status-total").html(iMax); 47 | return ""; 48 | } 49 | }); 50 | 51 | $(".bse-filter").val(""); 52 | $("#env-table_filter").hide(); 53 | 54 | $(".bse-filter").die("keyup").live("keyup", function() { 55 | $('#env-table').dataTable().fnFilter($(".bse-filter").val(), null, false, true); 56 | }); 57 | 58 | $(".bse-refresh").die("click").live("click", function() { 59 | $('#env-table').dataTable().fnReloadAjax(); 60 | }); 61 | 62 | }); -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/guice/index.ftl: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 |
12 | 
-------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/guice/index.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | "use strict"; 3 | 4 | $("#status-error").html(""); 5 | 6 | var source = "${ajax_base}/guice/keys"; 7 | 8 | $.get(source, function(json) { 9 | var code = JSON.stringify(json, null, 2); 10 | $("#guice-keys").text(code); 11 | }); 12 | }); -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/guicegraph/index.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 38 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/guiceprovision/index.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 41 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/guiceprovision/index.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | var flamegraph = d3.flameGraph() 3 | .width(1280) 4 | .height(340) 5 | .label(function(d) { 6 | return d.name + " " + d.value + " msec"; 7 | }); 8 | 9 | d3.json("${ajax_base}/guice/metrics", function(error, data) { 10 | if (error) { 11 | console.warn(error); 12 | } else { 13 | d3.select(".middle-center") 14 | .datum(data) 15 | .call(flamegraph); 16 | } 17 | }); 18 | }); -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/home.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#macro body> 4 | 12 | 13 | <#import "/layout/bootstrap/macros.ftl" as nf/> 14 | 15 | 38 | 39 |
40 | 65 |
66 | 67 | 68 |
69 |
70 |
71 |
72 | 73 | 74 | 80 | 81 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/home.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | "use strict"; 3 | var templateBaseUrl = '${template_base}'; 4 | 5 | $("div.outer-center").layout({ 6 | defaults: { 7 | resizable : false, 8 | slideable : false, 9 | spacing_open: 0, 10 | spacing_closed: 0 11 | }, 12 | north: { paneSelector : ".middle-north" }, 13 | south: { paneSelector : ".middle-south" }, 14 | center: { paneSelector : ".middle-center-wrapper" } 15 | }); 16 | 17 | var ajaxCallBase = '${ajax_base}'; 18 | var init = $.getHashParams(); 19 | var state = {}; 20 | 21 | 22 | $(".nav a").click( function(e) { 23 | e.preventDefault(); 24 | $.modifyHashParams({"view": $(this).attr("id").substring("submenu-".length)}); 25 | }); 26 | 27 | $("#machine-readable").click(function(e) { 28 | e.preventDefault(); 29 | window.open(ajaxCallBase + "/" + $.getHashParams()["view"]); 30 | }); 31 | 32 | 33 | /** 34 | * Load page elements based on the location hash 35 | */ 36 | function applyHashChange(prev, curr) { 37 | if (!curr.view) 38 | curr.view = "env"; 39 | if (curr.view == state.view && curr.app == state.app && curr.inst == state.inst) 40 | return; 41 | 42 | $("#bc-app").text(curr.app ? curr.app : ""); 43 | $("#bc-instance").text(curr.inst ? curr.inst : ""); 44 | $("#bc-view").text($("#submenu-{0} span".format(curr.view)).text()); 45 | 46 | populateContents(curr.view, curr.inst); 47 | } 48 | 49 | /** 50 | * Load the view for the currently select instance 51 | */ 52 | function populateContents(view, inst) { 53 | state.view = view; 54 | if (!state.view) { 55 | state.view = "env"; 56 | } 57 | state.inst = inst; 58 | var $view = $(".middle-center"); 59 | if (view) { 60 | var url = templateBaseUrl + "/{0}".format(state.view); 61 | $(".nav li").removeClass("active"); 62 | $("#submenu-{0}".format(state.view)).parent().addClass("active"); 63 | 64 | $view.ajaxBusy(); 65 | $view.html(""); 66 | $view.load(url, function() { 67 | $view.ajaxBusy('remove'); 68 | }); 69 | } else { 70 | $view.html("Select an instance or valid view"); 71 | } 72 | } 73 | 74 | $.listenHashChange(applyHashChange); 75 | }); -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/jars/index.ftl: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 |
12 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/jmx/index.ftl: -------------------------------------------------------------------------------- 1 | 4 | 5 | 11 | 12 |
13 |
14 |
15 |
16 |
17 |
18 | 19 |
20 | 21 | 22 | 23 | 24 |
25 |
26 |
27 |
28 |
29 | -------------------------------------------------------------------------------- /karyon2-admin-web/src/main/resources/webadmin/jmx/view.ftl: -------------------------------------------------------------------------------- 1 | 4 | 5 | <#import "/layout/main/macros.ftl" as nf/> 6 | 7 | 34 | 35 |
36 |

${key}

37 |

Attributes

38 |
39 |
40 |
41 | 42 |
43 |

Operations

44 |
45 |
46 | 47 |

Results

48 |
49 |
50 |
51 |
-------------------------------------------------------------------------------- /karyon2-admin-web/src/test/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootCategory=debug,stdout 2 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 3 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 4 | log4j.appender.stdout.layout.ConversionPattern=%d %-5p %C:%L [%t] [%M] %m%n -------------------------------------------------------------------------------- /karyon2-admin/README.md: -------------------------------------------------------------------------------- 1 | karyon-admin 2 | ====== 3 | 4 | Base module for karyon administration console. 5 | The actual web interface is provided by the [karyon2-admin-web](../karyon2-admin-web) module. 6 | -------------------------------------------------------------------------------- /karyon2-admin/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Netflix, Inc. 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 | apply plugin: 'osgi' 17 | 18 | dependencies { 19 | dependencies { 20 | compile 'javax.ws.rs:jsr311-api:1.1.1' 21 | compile 'javax.servlet:javax.servlet-api:3.0.1' 22 | compile 'org.mortbay.jetty:jetty:6.1.26' 23 | compile 'com.google.inject.extensions:guice-servlet:4.1.0' 24 | compile 'com.sun.jersey.contribs:jersey-guice:${jersey_version}' 25 | compile "com.sun.jersey:jersey-servlet:${jersey_version}" 26 | compile "com.sun.jersey:jersey-server:${jersey_version}" 27 | compile "com.netflix.pytheas:pytheas-core:${pytheas_version}" 28 | compile "com.sun.jersey:jersey-core:${jersey_version}" 29 | compile "com.sun.jersey:jersey-servlet:${jersey_version}" 30 | compile "com.sun.jersey:jersey-server:${jersey_version}" 31 | compile "com.sun.jersey:jersey-json:${jersey_version}" 32 | runtime 'org.codehaus.jackson:jackson-mapper-asl:1.9.11' 33 | 34 | testCompile "org.apache.httpcomponents:httpclient:${apache_httpclient_version}" 35 | testCompile 'log4j:log4j:1.2.17' 36 | testCompile 'org.slf4j:slf4j-log4j12:1.7.2' 37 | } 38 | } 39 | 40 | jar { 41 | manifest { 42 | name = 'karyon2-admin' 43 | instruction 'Bundle-Vendor', 'Netflix' 44 | instruction 'Bundle-DocURL', 'https://github.com/Netflix/karyon' 45 | instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/java/netflix/admin/AdminContainerConfig.java: -------------------------------------------------------------------------------- 1 | package netflix.admin; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import javax.servlet.Filter; 7 | 8 | import com.google.inject.ImplementedBy; 9 | import org.mortbay.jetty.Connector; 10 | 11 | @ImplementedBy(AdminConfigImpl.class) 12 | public interface AdminContainerConfig { 13 | boolean shouldIsolateResources(); 14 | boolean shouldEnable(); 15 | String templateResourceContext(); 16 | String ajaxDataResourceContext(); 17 | String jerseyResourcePkgList(); 18 | String jerseyViewableResourcePkgList(); 19 | boolean shouldScanClassPathForPluginDiscovery(); 20 | int listenPort(); 21 | List additionalFilters(); 22 | List additionalConnectors(); 23 | Map getJerseyConfigProperties(); 24 | List homeScriptResources(); 25 | } 26 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/java/netflix/admin/AdminUtils.java: -------------------------------------------------------------------------------- 1 | package netflix.admin; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.Properties; 9 | 10 | public class AdminUtils { 11 | private static final Logger LOG = LoggerFactory.getLogger(AdminExplorerManager.class); 12 | 13 | public static Properties loadAdminConsoleProps() { 14 | final Properties properties = new Properties(); 15 | final InputStream propsResourceStream = AdminUtils.class.getClassLoader().getResourceAsStream("admin-explorers.properties"); 16 | if (propsResourceStream != null) { 17 | try { 18 | properties.load(propsResourceStream); 19 | } catch (IOException e) { 20 | LOG.error("Exception loading admin console properties file.", e); 21 | } 22 | } 23 | 24 | return properties; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/java/netflix/admin/DefaultGlobalContextOverride.java: -------------------------------------------------------------------------------- 1 | package netflix.admin; 2 | 3 | import java.util.Properties; 4 | 5 | public class DefaultGlobalContextOverride implements GlobalModelContextOverride { 6 | @Override 7 | public Properties overrideProperties(Properties properties) { 8 | return properties; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/java/netflix/admin/DefaultRedirectRules.java: -------------------------------------------------------------------------------- 1 | package netflix.admin; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import javax.inject.Singleton; 7 | import javax.inject.Inject; 8 | import javax.servlet.http.HttpServletRequest; 9 | 10 | @Singleton 11 | public class DefaultRedirectRules implements RedirectRules { 12 | 13 | private AdminContainerConfig adminContainerConfig; 14 | 15 | @Inject 16 | public DefaultRedirectRules(AdminContainerConfig adminContainerConfig) { 17 | this.adminContainerConfig = adminContainerConfig; 18 | } 19 | 20 | @Override 21 | public Map getMappings() { 22 | Map urlRedirects = new HashMap<>(); 23 | urlRedirects.put("/", adminContainerConfig.templateResourceContext()); 24 | return urlRedirects; 25 | } 26 | 27 | @Override 28 | public String getRedirect(HttpServletRequest httpServletRequest) { 29 | return httpServletRequest.getRequestURI(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/java/netflix/admin/GlobalModelContextOverride.java: -------------------------------------------------------------------------------- 1 | package netflix.admin; 2 | 3 | import com.google.inject.ImplementedBy; 4 | 5 | import java.util.Properties; 6 | 7 | @ImplementedBy(DefaultGlobalContextOverride.class) 8 | public interface GlobalModelContextOverride { 9 | Properties overrideProperties(Properties properties); 10 | } 11 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/java/netflix/admin/RedirectRules.java: -------------------------------------------------------------------------------- 1 | package netflix.admin; 2 | 3 | import com.google.inject.ImplementedBy; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | import java.util.Map; 7 | 8 | @ImplementedBy(DefaultRedirectRules.class) 9 | public interface RedirectRules { 10 | Map getMappings(); 11 | String getRedirect(HttpServletRequest httpServletRequest); 12 | } 13 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/java/netflix/adminresources/AbstractAdminPageInfo.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources; 2 | 3 | import com.google.inject.Module; 4 | import com.netflix.config.ConfigurationManager; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public abstract class AbstractAdminPageInfo implements AdminPageInfo { 12 | public static final String ADMIN_PAGE_DISABLE_PROP_PREFIX = "netflix.platform.admin.pages."; 13 | public static final String DISABLED = ".disabled"; 14 | 15 | private final String pageId; 16 | private final String name; 17 | 18 | public AbstractAdminPageInfo(String pageId, String name) { 19 | this.pageId = pageId; 20 | this.name = name; 21 | } 22 | 23 | public String getPageId() { 24 | return pageId; 25 | } 26 | 27 | @Override 28 | public String getName() { 29 | return name; 30 | } 31 | 32 | @Override 33 | public String getPageTemplate() { 34 | return "/webadmin/" + pageId + "/index.ftl"; 35 | } 36 | 37 | @Override 38 | public String getJerseyResourcePackageList() { 39 | return ""; 40 | } 41 | 42 | @Override 43 | public boolean isEnabled() { 44 | final String disablePagePropId = ADMIN_PAGE_DISABLE_PROP_PREFIX + pageId + DISABLED; 45 | boolean isDisabled = ConfigurationManager.getConfigInstance().getBoolean(disablePagePropId, false); 46 | return !isDisabled; 47 | } 48 | 49 | @Override 50 | public List getGuiceModules() { 51 | return new ArrayList<>(0); 52 | } 53 | 54 | @Override 55 | public Map getDataModel() { 56 | return new HashMap<>(); 57 | } 58 | 59 | @Override 60 | public boolean isVisible() { 61 | return true; 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/java/netflix/adminresources/AdminPage.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources; 2 | 3 | @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) 4 | @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) 5 | public @interface AdminPage { 6 | } 7 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/java/netflix/adminresources/AdminPageInfo.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources; 2 | 3 | import com.google.inject.Module; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public interface AdminPageInfo { 9 | // id of the new page 10 | String getPageId(); 11 | 12 | // title as shown in tab UI 13 | String getName(); 14 | 15 | // freemarker template path 16 | String getPageTemplate(); 17 | 18 | // exports additional bindings needed by the plugin 19 | Map getDataModel(); 20 | 21 | // additional jersey resource package list if needed 22 | String getJerseyResourcePackageList(); 23 | 24 | // Guice modules that need to be added to the injector 25 | List getGuiceModules(); 26 | 27 | // controls if the module should be visible/enabled in admin console 28 | boolean isEnabled(); 29 | 30 | // should it be visible (by rendering page template as defined above) 31 | boolean isVisible(); 32 | } 33 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/java/netflix/adminresources/AdminResourcesFilter.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources; 2 | 3 | import java.util.Collections; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | import javax.inject.Inject; 9 | import javax.servlet.ServletException; 10 | 11 | import com.google.inject.Injector; 12 | import com.netflix.explorers.providers.FreemarkerTemplateProvider; 13 | import com.netflix.explorers.providers.WebApplicationExceptionMapper; 14 | import com.sun.jersey.api.core.PackagesResourceConfig; 15 | import com.sun.jersey.api.core.ResourceConfig; 16 | import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; 17 | import com.sun.jersey.spi.container.servlet.WebConfig; 18 | 19 | import netflix.admin.AdminFreemarkerTemplateProvider; 20 | 21 | /** 22 | * This class is a minimal simulation of GuiceFilter. Due to the number of 23 | * statics used in GuiceFilter, there cannot be more than one in an application. 24 | * The AdminResources app needs minimal features and this class provides those. 25 | */ 26 | class AdminResourcesFilter extends GuiceContainer { 27 | private Map props = Collections.emptyMap(); 28 | 29 | @Inject 30 | AdminResourcesFilter(Injector injector) { 31 | super(injector); 32 | } 33 | 34 | @Override 35 | protected ResourceConfig getDefaultResourceConfig(Map props, 36 | WebConfig webConfig) throws ServletException { 37 | HashMap mergedProps = new HashMap<>(props); 38 | mergedProps.putAll(this.props); 39 | return new PackagesResourceConfig(mergedProps) { 40 | @Override 41 | public Set> getProviderClasses() { 42 | Set> providers = super.getProviderClasses(); 43 | // remove conflicting provider if present 44 | providers.remove(FreemarkerTemplateProvider.class); 45 | providers.add(AdminFreemarkerTemplateProvider.class); 46 | providers.add(WebApplicationExceptionMapper.class); 47 | return providers; 48 | } 49 | }; 50 | } 51 | 52 | public void setProperties(Map props) { 53 | this.props = new HashMap<>(props); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/java/netflix/adminresources/KaryonAdminModule.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources; 2 | 3 | import javax.inject.Named; 4 | 5 | import com.google.inject.AbstractModule; 6 | import com.google.inject.Provides; 7 | 8 | public class KaryonAdminModule extends AbstractModule { 9 | 10 | public static final String ADMIN_RESOURCES_SERVER_PORT = "adminResourcesServerPort"; 11 | 12 | @Override 13 | protected void configure() { 14 | bind(AdminResourcesContainer.class).asEagerSingleton(); 15 | } 16 | 17 | @Provides 18 | @Named(ADMIN_RESOURCES_SERVER_PORT) 19 | public int adminListenPort(AdminResourcesContainer adminResourcesContainer) { 20 | return adminResourcesContainer.getServerPort(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/java/netflix/adminresources/RedirectFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Netflix, Inc. 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 netflix.adminresources; 18 | 19 | import com.google.inject.Inject; 20 | import com.google.inject.Singleton; 21 | import netflix.admin.RedirectRules; 22 | 23 | import javax.servlet.*; 24 | import javax.servlet.http.HttpServletRequest; 25 | import javax.servlet.http.HttpServletResponse; 26 | import java.io.IOException; 27 | import java.util.Map; 28 | 29 | @Singleton 30 | public class RedirectFilter implements Filter { 31 | 32 | private RedirectRules redirectRules; 33 | 34 | @Inject 35 | public RedirectFilter(RedirectRules redirectRules) { 36 | this.redirectRules = redirectRules; 37 | } 38 | 39 | @Override 40 | public void destroy() { 41 | } 42 | 43 | @Override 44 | public void doFilter(ServletRequest request, ServletResponse response, 45 | FilterChain chain) throws IOException, ServletException { 46 | HttpServletRequest httpRequest = (HttpServletRequest) request; 47 | final String requestURI = httpRequest.getRequestURI(); 48 | 49 | // redirect based on a simple table lookup 50 | final Map mappings = redirectRules.getMappings(); 51 | for (Map.Entry mapping : mappings.entrySet()) { 52 | if (requestURI.equals(mapping.getKey())) { 53 | ((HttpServletResponse) response).sendRedirect(mapping.getValue()); 54 | return; 55 | } 56 | } 57 | 58 | // redirect based on a custom logic for request 59 | final String redirectTo = redirectRules.getRedirect(httpRequest); 60 | if (redirectTo != null && !redirectTo.isEmpty() && !redirectTo.equals(requestURI)) { 61 | ((HttpServletResponse) response).sendRedirect(redirectTo); 62 | return; 63 | } 64 | 65 | chain.doFilter(httpRequest, response); 66 | } 67 | 68 | @Override 69 | public void init(FilterConfig config) throws ServletException { 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/resources/admin-explorers.properties: -------------------------------------------------------------------------------- 1 | com.netflix.explorers.environmentName=test 2 | com.netflix.explorers.applicationName=Admin 3 | com.netflix.explorers.applicationVersion=1.0 4 | com.netflix.explorers.currentRegion=us-east-1 5 | -------------------------------------------------------------------------------- /karyon2-admin/src/main/resources/baseserver-explorer.properties: -------------------------------------------------------------------------------- 1 | com.netflix.explorers.baseserver.title=Admin Resources 2 | com.netflix.explorers.baseserver.pageLayout=bootstrap 3 | com.netflix.explorers.baseserver.description=Admin web resources 4 | 5 | -------------------------------------------------------------------------------- /karyon2-admin/src/test/java/netflix/admin/AdminUtilsTest.java: -------------------------------------------------------------------------------- 1 | package netflix.admin; 2 | 3 | 4 | import com.netflix.explorers.PropertiesGlobalModelContext; 5 | import org.junit.Test; 6 | 7 | import java.util.Properties; 8 | 9 | import static junit.framework.Assert.assertTrue; 10 | 11 | public class AdminUtilsTest { 12 | 13 | @Test 14 | public void environmentPropertyLoaded() { 15 | final Properties properties = AdminUtils.loadAdminConsoleProps(); 16 | assertTrue(properties.getProperty(PropertiesGlobalModelContext.PROPERTY_ENVIRONMENT_NAME) != null); 17 | } 18 | 19 | @Test 20 | public void regionPropertyLoaded() { 21 | final Properties properties = AdminUtils.loadAdminConsoleProps(); 22 | assertTrue(properties.getProperty(PropertiesGlobalModelContext.PROPERTY_CURRENT_REGION) != null); 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /karyon2-admin/src/test/java/netflix/adminresources/AuthFilter.java: -------------------------------------------------------------------------------- 1 | package netflix.adminresources; 2 | 3 | import javax.servlet.*; 4 | import javax.servlet.http.HttpServletRequest; 5 | import javax.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | 8 | public class AuthFilter implements Filter { 9 | @Override 10 | public void init(FilterConfig filterConfig) throws ServletException {} 11 | 12 | @Override 13 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 14 | if (request instanceof HttpServletRequest) { 15 | String url = ((HttpServletRequest)request).getRequestURI(); 16 | if (url.startsWith("/main") || url.startsWith("/auth")) { 17 | ((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN); 18 | } 19 | chain.doFilter(request, response); 20 | } 21 | } 22 | 23 | @Override 24 | public void destroy() { 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /karyon2-admin/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012 Netflix, Inc. 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 | log4j.rootLogger=INFO, console 18 | 19 | log4j.appender.console=org.apache.log4j.ConsoleAppender 20 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 21 | log4j.appender.console.layout.ConversionPattern=%d %-5p %c{1}:%L %x %m [%t]%n 22 | -------------------------------------------------------------------------------- /karyon2-archaius/README.md: -------------------------------------------------------------------------------- 1 | karyon-eureka 2 | ====== 3 | 4 | This module provides integration with [Archaius](https://github.com/Netflix/archaius) 5 | 6 | ##### @ArchaiusBootstrap 7 | 8 | This annotation is the integration with archiaus and sets up the necessary bindings using [ArchaiusSuite](src/main/java/netflix/karyon/archaius/ArchaiusSuite.java) 9 | 10 | See the [hello world example](../karyon2-examples/hello-netflix-oss) for a sample. 11 | -------------------------------------------------------------------------------- /karyon2-archaius/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Netflix, Inc. 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 | apply plugin: 'osgi' 17 | 18 | dependencies { 19 | compile project(':karyon2-governator') 20 | compile 'com.netflix.archaius:archaius-core:0.7.2' 21 | compile "com.netflix.governator:governator-archaius:$governator_version" 22 | } 23 | 24 | jar { 25 | manifest { 26 | name = 'karyon2-archaius' 27 | instruction 'Bundle-Vendor', 'Netflix' 28 | instruction 'Bundle-DocURL', 'https://github.com/Netflix/karyon' 29 | instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /karyon2-archaius/src/main/java/netflix/karyon/archaius/ArchaiusBootstrap.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.archaius; 2 | 3 | import com.netflix.governator.guice.annotations.Bootstrap; 4 | 5 | import java.lang.annotation.Documented; 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * @author Nitesh Kant 12 | */ 13 | @Documented 14 | @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) 15 | @Target({ElementType.TYPE}) 16 | @Bootstrap(bootstrap = ArchaiusBootstrapModule.class) 17 | public @interface ArchaiusBootstrap { 18 | 19 | Class loader() default DefaultPropertiesLoader.class; 20 | } -------------------------------------------------------------------------------- /karyon2-archaius/src/main/java/netflix/karyon/archaius/PropertiesLoader.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.archaius; 2 | 3 | /** 4 | * @author Nitesh Kant 5 | */ 6 | public interface PropertiesLoader { 7 | 8 | void load(); 9 | } 10 | -------------------------------------------------------------------------------- /karyon2-core/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Netflix, Inc. 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 | apply plugin: 'osgi' 17 | 18 | dependencies { 19 | compile "io.reactivex:rxnetty-contexts:${rxnetty_version}" 20 | } 21 | 22 | jar { 23 | manifest { 24 | name = 'karyon2-core' 25 | instruction 'Bundle-Vendor', 'Netflix' 26 | instruction 'Bundle-DocURL', 'https://github.com/Netflix/karyon' 27 | instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/health/AlwaysHealthyHealthCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Netflix, Inc. 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 netflix.karyon.health; 18 | 19 | /** 20 | * Default health check handler implementation which always returns healthy. There is always a single instance of this 21 | * class which can be obtained via {@link #INSTANCE} 22 | * 23 | * @author Nitesh Kant 24 | */ 25 | public class AlwaysHealthyHealthCheck implements HealthCheckHandler { 26 | 27 | public static final AlwaysHealthyHealthCheck INSTANCE = new AlwaysHealthyHealthCheck(); 28 | 29 | public AlwaysHealthyHealthCheck() { 30 | } 31 | 32 | @Override 33 | public int getStatus() { 34 | return 200; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/health/HealthCheckHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Netflix, Inc. 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 netflix.karyon.health; 18 | 19 | /** 20 | * This is an extension to the callback handler 21 | * in eureka to provide a 22 | * more flexible health check response (an HTTP status code) as a healthcheck request.
23 | * 24 | * This healthcheck handler is also used to have a fixed healthcheck endpoint created by karyon.
25 | * 26 | * @author Nitesh Kant 27 | */ 28 | public interface HealthCheckHandler { 29 | 30 | /** 31 | * Checks the health of the application and returns a status code, which can be directly consumed as a HTTP status 32 | * code.
33 | * Kayon considers any status code >= 200 and < 300 as healthy. 34 | * 35 | * @return The health status of the application. 36 | */ 37 | int getStatus(); 38 | } 39 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/health/HealthCheckInvocationStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Netflix, Inc. 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 netflix.karyon.health; 18 | 19 | import java.util.concurrent.TimeoutException; 20 | 21 | /** 22 | * A strategy to make application specific healthchecks. Since, the application health checks can be poorly implemented 23 | * and hence take a long time to complete, in some cases, it is wise to have an SLA around the health check response 24 | * times. 25 | * There is a 1:1 mapping between a strategy instance and a {@link HealthCheckHandler} instance and hence it is assumed 26 | * that the strategy already knows about the handler instance. 27 | * 28 | * @author Nitesh Kant 29 | */ 30 | public interface HealthCheckInvocationStrategy { 31 | 32 | /** 33 | * Invokes the handler associated with this strategy and returns the response. This method may block waiting for results.
34 | * If this strategy supports timeouts, this call must not wait more than the timeout value. 35 | * 36 | * @return The health check result. 37 | * 38 | * @throws TimeoutException If the healthcheck did not return after the stipulated time (governed entirely by this 39 | * strategy implementation) 40 | */ 41 | int invokeCheck() throws TimeoutException; 42 | 43 | /** 44 | * Returns the instance of {@link HealthCheckHandler} associated with this strategy. 45 | * 46 | * @return The instance of {@link HealthCheckHandler} associated with this strategy. 47 | */ 48 | HealthCheckHandler getHandler(); 49 | } 50 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/KaryonTransport.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport; 2 | 3 | import io.reactivex.netty.contexts.RxContexts; 4 | import io.reactivex.netty.protocol.http.server.HttpServer; 5 | import io.reactivex.netty.protocol.http.server.HttpServerBuilder; 6 | import io.reactivex.netty.protocol.http.server.RequestHandler; 7 | import netflix.karyon.transport.http.HttpRequestHandler; 8 | 9 | /** 10 | * A factory class for creating karyon transport servers which are created using 11 | * RxNetty 12 | * 13 | * @author Nitesh Kant 14 | */ 15 | public final class KaryonTransport { 16 | 17 | public static final String DEFAULT_REQUEST_ID_CTX_KEY = "X-Karyon-REQUEST_ID"; 18 | 19 | static { 20 | RxContexts.useRequestIdContextKey(DEFAULT_REQUEST_ID_CTX_KEY); 21 | } 22 | 23 | private KaryonTransport() { 24 | } 25 | 26 | public static HttpServerBuilder newHttpServerBuilder(int port, RequestHandler router) { 27 | return RxContexts.newHttpServerBuilder(port, new HttpRequestHandler(router), RxContexts.DEFAULT_CORRELATOR); 28 | } 29 | 30 | public static HttpServerBuilder newHttpServerBuilder(int port, HttpRequestHandler requestHandler) { 31 | return RxContexts.newHttpServerBuilder(port, requestHandler, RxContexts.DEFAULT_CORRELATOR); 32 | } 33 | 34 | public static HttpServer newHttpServer(int port, RequestHandler router) { 35 | return newHttpServerBuilder(port, router).build(); 36 | } 37 | 38 | public static HttpServer newHttpServer(int port, HttpRequestHandler requestHandler) { 39 | return newHttpServerBuilder(port, requestHandler).build(); 40 | } 41 | 42 | /** 43 | * Karyon 44 | * 45 | * @param name The name of the context key to be used as default. 46 | */ 47 | public static void useRequestIdContextKey(String name) { 48 | RxContexts.useRequestIdContextKey(name); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/RequestRouter.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport; 2 | 3 | import rx.Observable; 4 | 5 | /** 6 | * @author Nitesh Kant 7 | * 8 | * @deprecated Use RxNetty's {@link io.reactivex.netty.channel.Handler} instead. 9 | */ 10 | @Deprecated 11 | public interface RequestRouter { 12 | 13 | Observable route(I request, O response); 14 | } 15 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/http/HttpInterceptorKey.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.http; 2 | 3 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 4 | import netflix.karyon.transport.interceptor.InterceptorKey; 5 | 6 | /** 7 | * @author Nitesh Kant 8 | */ 9 | public interface HttpInterceptorKey extends InterceptorKey, HttpKeyEvaluationContext> { 10 | } 11 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/http/HttpInterceptorSupport.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.http; 2 | 3 | import io.netty.handler.codec.http.HttpMethod; 4 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 5 | import io.reactivex.netty.protocol.http.server.HttpServerResponse; 6 | import netflix.karyon.transport.interceptor.AbstractAttacher; 7 | import netflix.karyon.transport.interceptor.AbstractInterceptorSupport; 8 | import netflix.karyon.transport.interceptor.InterceptorKey; 9 | 10 | /** 11 | * An extension of {@link netflix.karyon.transport.interceptor.InterceptorSupport} to add HTTP specific methods for attaching interceptors. 12 | * 13 | * @author Nitesh Kant 14 | */ 15 | public class HttpInterceptorSupport extends 16 | AbstractInterceptorSupport, HttpServerResponse, HttpKeyEvaluationContext, 17 | HttpInterceptorSupport.HttpAttacher, HttpInterceptorSupport> { 18 | 19 | @Override 20 | protected HttpAttacher newAttacher(InterceptorKey, HttpKeyEvaluationContext> key) { 21 | return new HttpAttacher(this, key); 22 | } 23 | 24 | public HttpAttacher forUri(String uri) { 25 | if (null == uri || uri.isEmpty()) { 26 | throw new IllegalArgumentException("Uri can not be null or empty."); 27 | } 28 | return getAttacherForKey(new ServletStyleUriConstraintKey(uri, "")); 29 | } 30 | 31 | public HttpAttacher forUriRegex(String uriRegEx) { 32 | if (null == uriRegEx || uriRegEx.isEmpty()) { 33 | throw new IllegalArgumentException("Uri regular expression can not be null or empty."); 34 | } 35 | return getAttacherForKey(new RegexUriConstraintKey(uriRegEx)); 36 | } 37 | 38 | public HttpAttacher forHttpMethod(HttpMethod method) { 39 | if (null == method) { 40 | throw new IllegalArgumentException("Uri can not be null or empty."); 41 | } 42 | return getAttacherForKey(new MethodConstraintKey(method)); 43 | } 44 | 45 | public static class HttpAttacher 46 | extends AbstractAttacher, HttpServerResponse, HttpKeyEvaluationContext, 47 | HttpInterceptorSupport> { 48 | 49 | public HttpAttacher(HttpInterceptorSupport support, 50 | InterceptorKey, HttpKeyEvaluationContext> key) { 51 | super(support, key); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/http/HttpRequestHandler.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.http; 2 | 3 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 4 | import io.reactivex.netty.protocol.http.server.HttpServerResponse; 5 | import io.reactivex.netty.protocol.http.server.RequestHandler; 6 | import netflix.karyon.transport.interceptor.AbstractInterceptorSupport; 7 | import netflix.karyon.transport.interceptor.InterceptorExecutor; 8 | import rx.Observable; 9 | 10 | /** 11 | * An implementation of {@link RequestHandler} for karyon. 12 | * 13 | * @author Nitesh Kant 14 | */ 15 | public class HttpRequestHandler implements RequestHandler { 16 | 17 | private final InterceptorExecutor, HttpServerResponse, HttpKeyEvaluationContext> executor; 18 | 19 | public HttpRequestHandler(RequestHandler router) { 20 | this(router, new HttpInterceptorSupport()); 21 | } 22 | 23 | public HttpRequestHandler(RequestHandler router, 24 | AbstractInterceptorSupport, HttpServerResponse, HttpKeyEvaluationContext, ?, ?> interceptorSupport) { 25 | executor = new InterceptorExecutor, HttpServerResponse, HttpKeyEvaluationContext>(interceptorSupport, router); 26 | } 27 | 28 | @Override 29 | public Observable handle(HttpServerRequest request, HttpServerResponse response) { 30 | return executor.execute(request, response, new HttpKeyEvaluationContext(response.getChannel())); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/http/HttpRequestHandlerBuilder.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.http; 2 | 3 | import io.netty.handler.codec.http.HttpMethod; 4 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 5 | import io.reactivex.netty.protocol.http.server.RequestHandler; 6 | import netflix.karyon.transport.interceptor.InterceptorKey; 7 | 8 | /** 9 | * A convenience builder to create {@link HttpRequestHandler} instances. 10 | * 11 | * @author Nitesh Kant 12 | */ 13 | public class HttpRequestHandlerBuilder { 14 | 15 | private final HttpInterceptorSupport interceptorSupport; 16 | private final RequestHandler router; 17 | 18 | public HttpRequestHandlerBuilder(RequestHandler router) { 19 | this(new HttpInterceptorSupport(), router); 20 | } 21 | 22 | public HttpRequestHandlerBuilder(HttpInterceptorSupport interceptorSupport, 23 | RequestHandler router) { 24 | this.interceptorSupport = interceptorSupport; 25 | this.router = router; 26 | } 27 | 28 | public HttpInterceptorSupport.HttpAttacher forKey(InterceptorKey, HttpKeyEvaluationContext> key) { 29 | return interceptorSupport.forKey(key); 30 | } 31 | 32 | public HttpInterceptorSupport.HttpAttacher forUri(String uri) { 33 | return interceptorSupport.forUri(uri); 34 | } 35 | 36 | public HttpInterceptorSupport.HttpAttacher forUriRegex(String uriRegEx) { 37 | return interceptorSupport.forUriRegex(uriRegEx); 38 | } 39 | 40 | public HttpInterceptorSupport.HttpAttacher forHttpMethod(HttpMethod method) { 41 | return interceptorSupport.forHttpMethod(method); 42 | } 43 | 44 | public HttpInterceptorSupport getInterceptorSupport() { 45 | return interceptorSupport; 46 | } 47 | 48 | public RequestHandler getRouter() { 49 | return router; 50 | } 51 | 52 | public HttpRequestHandler build() { 53 | interceptorSupport.finish(); 54 | return new HttpRequestHandler(router, interceptorSupport); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/http/MethodConstraintKey.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.http; 2 | 3 | import io.netty.handler.codec.http.HttpMethod; 4 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | /** 9 | * @author Nitesh Kant 10 | */ 11 | public class MethodConstraintKey implements HttpInterceptorKey { 12 | 13 | private static final Logger logger = LoggerFactory.getLogger(MethodConstraintKey.class); 14 | 15 | private final HttpMethod method; 16 | 17 | public MethodConstraintKey(HttpMethod method) { 18 | if (null == method) { 19 | throw new NullPointerException("HTTP method in the interceptor constraint can not be null."); 20 | } 21 | this.method = method; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "MethodConstraintKey{" + "method=" + method + '}'; 27 | } 28 | 29 | @Override 30 | public boolean apply(HttpServerRequest request, HttpKeyEvaluationContext context) { 31 | boolean matches = request.getHttpMethod().equals(method); 32 | if (logger.isDebugEnabled()) { 33 | logger.debug("Result for HTTP method constraint for method {} and required method {} : {}", 34 | request.getHttpMethod(), method, matches); 35 | } 36 | 37 | return matches; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/http/QueryStringDecoder.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.http; 2 | 3 | /** 4 | * A simple wrapper over {@link io.netty.handler.codec.http.QueryStringDecoder} to also provide access to the uri string. 5 | * 6 | * @author Nitesh Kant 7 | */ 8 | public class QueryStringDecoder { 9 | 10 | private final io.netty.handler.codec.http.QueryStringDecoder nettyDecoder; 11 | private final String uri; 12 | 13 | public QueryStringDecoder(String uri) { 14 | if (null == uri) { 15 | throw new NullPointerException("Uri can not be null."); 16 | } 17 | this.uri = uri; 18 | uri = io.netty.handler.codec.http.QueryStringDecoder.decodeComponent(uri); 19 | if (!uri.endsWith("/") && !uri.contains(".") && !uri.contains("?")) { 20 | // Normalize the URI for better matching of Servlet style URI constraints. 21 | uri += "/"; 22 | } 23 | nettyDecoder = new io.netty.handler.codec.http.QueryStringDecoder(uri); 24 | } 25 | 26 | public io.netty.handler.codec.http.QueryStringDecoder nettyDecoder() { 27 | return nettyDecoder; 28 | } 29 | 30 | public String uri() { 31 | return uri; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/http/RegexUriConstraintKey.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.http; 2 | 3 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | /** 11 | * Provides constraint implementation for {@link netflix.karyon.transport.interceptor.InterceptorKey} for matching URI paths as regular expressions as 12 | * supported by {@link java.util.regex.Pattern}. 13 | * The request URI path is as retrieved using: {@link HttpKeyEvaluationContext#getRequestUriPath(HttpServerRequest)} 14 | * 15 | * @author Nitesh Kant 16 | */ 17 | public class RegexUriConstraintKey implements HttpInterceptorKey { 18 | 19 | private static final Logger logger = LoggerFactory.getLogger(RegexUriConstraintKey.class); 20 | 21 | private final Pattern regEx; 22 | 23 | public RegexUriConstraintKey(String constraint) { 24 | if (null == constraint) { 25 | throw new NullPointerException("Constraint can not be null."); 26 | } 27 | regEx = Pattern.compile(constraint); 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return "RegexUriConstraintKey{" + "regEx=" + regEx + '}'; 33 | } 34 | 35 | @Override 36 | public boolean apply(HttpServerRequest request, HttpKeyEvaluationContext context) { 37 | String requestUriPath = context.getRequestUriPath(request); 38 | boolean matches = false; 39 | if (null != requestUriPath) { 40 | Matcher matcher = regEx.matcher(requestUriPath); 41 | matches = matcher.matches(); 42 | } 43 | if (logger.isDebugEnabled()) { 44 | logger.debug("Result for regex based uri constraint for uri path {} and pattern {} : {}", requestUriPath, 45 | regEx, matches); 46 | } 47 | return matches; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/interceptor/AbstractAttacher.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.interceptor; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | /** 7 | * @author Nitesh Kant 8 | */ 9 | public class AbstractAttacher { 10 | 11 | protected final S interceptorSupport; 12 | protected final InterceptorKey key; 13 | 14 | public AbstractAttacher(S interceptorSupport, InterceptorKey key) { 15 | this.interceptorSupport = interceptorSupport; 16 | this.key = key; 17 | } 18 | 19 | @SuppressWarnings({"unchecked", "rawtypes"}) 20 | public S intercept(InboundInterceptor... interceptors) { 21 | List list = interceptorSupport.getInboundInterceptors(); 22 | list.add(new InterceptorHolder>(key, Arrays.asList(interceptors))); 23 | return interceptorSupport; 24 | } 25 | 26 | @SuppressWarnings({"unchecked", "rawtypes"}) 27 | public S intercept(OutboundInterceptor... interceptors) { 28 | List list = interceptorSupport.getOutboundInterceptors(); 29 | list.add(new InterceptorHolder>(key, Arrays.asList(interceptors))); 30 | return interceptorSupport; 31 | } 32 | 33 | @SuppressWarnings({"unchecked", "rawtypes"}) 34 | public S intercept(DuplexInterceptor... interceptors) { 35 | List ins = interceptorSupport.getInboundInterceptors(); 36 | ins.add(new InterceptorHolder(key, Arrays.asList(interceptors))); 37 | List outs = interceptorSupport.getOutboundInterceptors(); 38 | outs.add(new InterceptorHolder(key, Arrays.asList(interceptors))); 39 | return interceptorSupport; 40 | } 41 | 42 | public InterceptorKey getKey() { 43 | return key; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/interceptor/DuplexInterceptor.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.interceptor; 2 | 3 | /** 4 | * 5 | * @author Nitesh Kant 6 | */ 7 | public interface DuplexInterceptor extends InboundInterceptor, OutboundInterceptor { 8 | } 9 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/interceptor/InboundInterceptor.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.interceptor; 2 | 3 | import rx.Observable; 4 | 5 | /** 6 | * @author Nitesh Kant 7 | */ 8 | public interface InboundInterceptor { 9 | 10 | Observable in(I request, O response); 11 | } 12 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/interceptor/InterceptorHolder.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.interceptor; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author Nitesh Kant 7 | */ 8 | public class InterceptorHolder { 9 | 10 | private final InterceptorKey key; 11 | private final List interceptors; 12 | 13 | public InterceptorHolder(InterceptorKey key, List interceptors) { 14 | this.key = key; 15 | this.interceptors = interceptors; 16 | } 17 | 18 | public InterceptorKey getKey() { 19 | return key; 20 | } 21 | 22 | public List getInterceptors() { 23 | return interceptors; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/interceptor/InterceptorKey.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.interceptor; 2 | 3 | /** 4 | * Key for a {@link InboundInterceptor} or {@link OutboundInterceptor} which determines whether a interceptor must 5 | * be applied for a particular request.
6 | * Any implementation for the key must be aware that it will be invoked for every request so it should always optimize 7 | * for speed of evaluation. 8 | * 9 | * @author Nitesh Kant 10 | */ 11 | public interface InterceptorKey { 12 | 13 | /** 14 | * This is invoked for a request to determine whether the interceptor attached to this key must be executed for this 15 | * request. 16 | * 17 | * @param request Request to determine whether the attached interceptor is to be applied or not. 18 | * @param context Context for the key evaluation, usually used to cache costly operations like parsing request 19 | * URI. 20 | * 21 | * @return {@code true} if the interceptor must be applied for this request. 22 | */ 23 | boolean apply(I request, C context); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/interceptor/InterceptorSupport.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.interceptor; 2 | 3 | /** 4 | * A contract to support interceptors for requests i.e. how to attach filters to a request processing. 5 | * 6 | * @author Nitesh Kant 7 | */ 8 | public class InterceptorSupport 9 | extends AbstractInterceptorSupport, InterceptorSupport> { 10 | 11 | @Override 12 | protected Attacher newAttacher(InterceptorKey key) { 13 | return new Attacher(this, key); 14 | } 15 | 16 | public static class Attacher 17 | extends AbstractAttacher> { 18 | 19 | public Attacher(InterceptorSupport interceptorSupport, InterceptorKey key) { 20 | super(interceptorSupport, key); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/interceptor/KeyEvaluationContext.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.interceptor; 2 | 3 | import io.netty.channel.Channel; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * A context to store results of costly operations during evaluation of filter keys, eg: request URI parsing. 10 | * This context is not thread-safe. 11 | */ 12 | public class KeyEvaluationContext { 13 | 14 | protected final Channel channel; 15 | 16 | public KeyEvaluationContext(Channel channel) { 17 | this.channel = channel; 18 | } 19 | 20 | enum KeyEvaluationResult { Apply, Skip, NotExecuted } 21 | 22 | private final Map, Boolean> keyEvaluationCache = new HashMap, Boolean>(); 23 | 24 | protected void updateKeyEvaluationResult(InterceptorKey key, boolean result) { 25 | keyEvaluationCache.put(key, result); 26 | } 27 | 28 | protected KeyEvaluationResult getEvaluationResult(InterceptorKey key) { 29 | Boolean result = keyEvaluationCache.get(key); 30 | return null == result ? KeyEvaluationResult.NotExecuted 31 | : result ? KeyEvaluationResult.Apply : KeyEvaluationResult.Skip; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /karyon2-core/src/main/java/netflix/karyon/transport/interceptor/OutboundInterceptor.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.interceptor; 2 | 3 | import rx.Observable; 4 | 5 | /** 6 | * @author Nitesh Kant 7 | */ 8 | public interface OutboundInterceptor { 9 | 10 | Observable out(O response); 11 | } 12 | -------------------------------------------------------------------------------- /karyon2-core/src/test/java/netflix/karyon/server/http/InterceptorConstraintTestBase.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.server.http; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.handler.codec.http.DefaultHttpRequest; 5 | import io.netty.handler.codec.http.HttpMethod; 6 | import io.netty.handler.codec.http.HttpVersion; 7 | import io.reactivex.netty.protocol.http.UnicastContentSubject; 8 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 9 | import netflix.karyon.server.MockChannelHandlerContext; 10 | import netflix.karyon.transport.http.HttpKeyEvaluationContext; 11 | import netflix.karyon.transport.interceptor.InterceptorKey; 12 | 13 | /** 14 | * @author Nitesh Kant 15 | */ 16 | public class InterceptorConstraintTestBase { 17 | 18 | protected static boolean doApplyForGET(InterceptorKey, HttpKeyEvaluationContext> key, String uri) { 19 | return doApply(key, uri, HttpMethod.GET); 20 | } 21 | 22 | protected static boolean doApply(InterceptorKey, HttpKeyEvaluationContext> key, String uri, 23 | HttpMethod httpMethod) { 24 | DefaultHttpRequest nettyRequest = new DefaultHttpRequest(HttpVersion.HTTP_1_0, httpMethod, uri); 25 | return key.apply(new HttpServerRequest(nettyRequest, 26 | UnicastContentSubject.createWithoutNoSubscriptionTimeout()), 27 | new HttpKeyEvaluationContext(new MockChannelHandlerContext("mock").channel())); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /karyon2-core/src/test/java/netflix/karyon/server/http/MethodConstraintTest.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.server.http; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.handler.codec.http.HttpMethod; 5 | import netflix.karyon.transport.http.MethodConstraintKey; 6 | import org.junit.Assert; 7 | import org.junit.Test; 8 | 9 | /** 10 | * @author Nitesh Kant 11 | */ 12 | public class MethodConstraintTest extends InterceptorConstraintTestBase { 13 | 14 | @Test 15 | public void testMethodConstraint() throws Exception { 16 | MethodConstraintKey key = new MethodConstraintKey(HttpMethod.HEAD); 17 | boolean keyApplicable = doApply(key, "a/b/c", HttpMethod.HEAD); 18 | Assert.assertTrue("Http Method style constraint failed.", keyApplicable); 19 | } 20 | 21 | @Test 22 | public void testMethodConstraintFail() throws Exception { 23 | MethodConstraintKey key = new MethodConstraintKey(HttpMethod.HEAD); 24 | boolean keyApplicable = doApply(key, "a/b/c", HttpMethod.GET); 25 | Assert.assertFalse("Http Method style constraint failed.", keyApplicable); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /karyon2-core/src/test/java/netflix/karyon/server/http/RegExConstraintTest.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.server.http; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import netflix.karyon.transport.http.RegexUriConstraintKey; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | /** 9 | * @author Nitesh Kant 10 | */ 11 | public class RegExConstraintTest extends InterceptorConstraintTestBase { 12 | 13 | @Test 14 | public void testRegExConstraint() throws Exception { 15 | RegexUriConstraintKey key = new RegexUriConstraintKey("a/.*"); 16 | boolean keyApplicable = doApplyForGET(key, "a/b/c"); 17 | Assert.assertTrue("Regex style constraint failed.", keyApplicable); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /karyon2-core/src/test/java/netflix/karyon/server/interceptor/MockKey.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.server.interceptor; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import netflix.karyon.transport.interceptor.InterceptorKey; 5 | import netflix.karyon.transport.interceptor.KeyEvaluationContext; 6 | 7 | /** 8 | * @author Nitesh Kant 9 | */ 10 | class MockKey implements InterceptorKey { 11 | 12 | private final boolean result; 13 | 14 | public MockKey(boolean result) { 15 | this.result = result; 16 | } 17 | 18 | @Override 19 | public boolean apply(ByteBuf request, KeyEvaluationContext context) { 20 | return result; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /karyon2-core/src/test/java/netflix/karyon/server/interceptor/TestableDuplexInterceptor.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.server.interceptor; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import netflix.karyon.server.MockChannelHandlerContext; 5 | import netflix.karyon.transport.interceptor.DuplexInterceptor; 6 | import netflix.karyon.transport.interceptor.InterceptorKey; 7 | import netflix.karyon.transport.interceptor.KeyEvaluationContext; 8 | import rx.Observable; 9 | 10 | /** 11 | * @author Nitesh Kant 12 | */ 13 | public class TestableDuplexInterceptor implements DuplexInterceptor { 14 | 15 | private final InterceptorKey filterKey; 16 | private volatile boolean inCalled; 17 | private volatile boolean outCalled; 18 | private volatile boolean wasLastInCallValid; 19 | private volatile boolean wasLastOutCallValid; 20 | 21 | @SuppressWarnings("unchecked") 22 | public TestableDuplexInterceptor(InterceptorKey filterKey) { 23 | this.filterKey = filterKey; 24 | } 25 | 26 | public boolean isCalledForIn() { 27 | return inCalled; 28 | } 29 | 30 | public boolean isCalledForOut() { 31 | return outCalled; 32 | } 33 | 34 | public boolean wasLastInCallValid() { 35 | return wasLastInCallValid; 36 | } 37 | 38 | public boolean wasLastOutCallValid() { 39 | return wasLastOutCallValid; 40 | } 41 | 42 | @Override 43 | public Observable in(ByteBuf request, ByteBuf response) { 44 | inCalled = true; 45 | MockChannelHandlerContext mock = new MockChannelHandlerContext("mock"); 46 | wasLastInCallValid = filterKey.apply(request, new KeyEvaluationContext(mock.channel())); 47 | return Observable.empty(); 48 | } 49 | 50 | @Override 51 | public Observable out(ByteBuf response) { 52 | outCalled = true; 53 | wasLastOutCallValid = filterKey.apply(response, new KeyEvaluationContext(new MockChannelHandlerContext("").channel())); 54 | return Observable.empty(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /karyon2-core/src/test/java/netflix/karyon/server/interceptor/TestableInboundInterceptor.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.server.interceptor; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import netflix.karyon.server.MockChannelHandlerContext; 5 | import netflix.karyon.transport.interceptor.InboundInterceptor; 6 | import netflix.karyon.transport.interceptor.InterceptorKey; 7 | import netflix.karyon.transport.interceptor.KeyEvaluationContext; 8 | import rx.Observable; 9 | 10 | /** 11 | * @author Nitesh Kant 12 | */ 13 | class TestableInboundInterceptor implements InboundInterceptor { 14 | 15 | private final InterceptorKey filterKey; 16 | private volatile boolean wasLastCallValid; 17 | private volatile boolean receivedACall; 18 | 19 | public TestableInboundInterceptor(InterceptorKey filterKey) { 20 | this.filterKey = filterKey; 21 | } 22 | 23 | public boolean wasLastCallValid() { 24 | return wasLastCallValid; 25 | } 26 | 27 | boolean isReceivedACall() { 28 | return receivedACall; 29 | } 30 | 31 | @Override 32 | public Observable in(ByteBuf request, ByteBuf response) { 33 | MockChannelHandlerContext context = new MockChannelHandlerContext("mock"); 34 | wasLastCallValid = filterKey.apply(request, new KeyEvaluationContext(context.channel())); 35 | receivedACall = true; 36 | return Observable.empty(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /karyon2-core/src/test/java/netflix/karyon/server/interceptor/TestableOutboundInterceptor.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.server.interceptor; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import netflix.karyon.transport.interceptor.InterceptorKey; 5 | import netflix.karyon.transport.interceptor.KeyEvaluationContext; 6 | 7 | /** 8 | * @author Nitesh Kant 9 | */ 10 | public class TestableOutboundInterceptor extends TestableDuplexInterceptor { 11 | 12 | public TestableOutboundInterceptor(InterceptorKey filterKey) { 13 | super(filterKey); 14 | } 15 | 16 | public boolean isReceivedACall() { 17 | return isCalledForOut(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /karyon2-core/src/test/java/netflix/karyon/server/interceptor/TestableRequestRouter.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.server.interceptor; 2 | 3 | import io.reactivex.netty.channel.Handler; 4 | import rx.Observable; 5 | import rx.functions.Action0; 6 | 7 | /** 8 | * @author Nitesh Kant 9 | */ 10 | class TestableRequestRouter implements Handler { 11 | 12 | private volatile boolean called; 13 | private volatile boolean unsubscribed; 14 | 15 | public boolean isReceivedACall() { 16 | return called; 17 | } 18 | 19 | public boolean isUnsubscribed() { 20 | return unsubscribed; 21 | } 22 | 23 | @Override 24 | public Observable handle(I input, O output) { 25 | called = true; 26 | return Observable.empty().doOnUnsubscribe(new Action0() { 27 | @Override 28 | public void call() { 29 | unsubscribed = true; 30 | } 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /karyon2-eureka/README.md: -------------------------------------------------------------------------------- 1 | karyon-eureka 2 | ====== 3 | 4 | This module provides integration with [Eureka](https://github.com/Netflix/eureka) 5 | 6 | #### KaryonEurekaModule 7 | 8 | Install this in your application to guice to enable eureka. 9 | 10 | See the [hello world example](../karyon-examples/hello-netflix-oss) for a sample. -------------------------------------------------------------------------------- /karyon2-eureka/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Netflix, Inc. 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 | apply plugin: 'osgi' 17 | 18 | dependencies { 19 | compile project(':karyon2-governator') 20 | compile "com.netflix.eureka:eureka-client:${eureka_version}" 21 | } 22 | 23 | jar { 24 | manifest { 25 | name = 'karyon2-eureka' 26 | instruction 'Bundle-Vendor', 'Netflix' 27 | instruction 'Bundle-DocURL', 'https://github.com/Netflix/karyon' 28 | instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /karyon2-eureka/src/main/java/netflix/karyon/eureka/DefaultEurekaKaryonStatusBridge.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.eureka; 2 | 3 | import com.netflix.appinfo.InstanceInfo; 4 | 5 | /** 6 | * @author Nitesh Kant 7 | */ 8 | public class DefaultEurekaKaryonStatusBridge implements EurekaKaryonStatusBridge { 9 | 10 | @Override 11 | public InstanceInfo.InstanceStatus interpretKaryonStatus(int karyonStatus) { 12 | if(karyonStatus == 204) { 13 | return InstanceInfo.InstanceStatus.STARTING; 14 | } else if (karyonStatus >= 200 && karyonStatus < 300) { 15 | return InstanceInfo.InstanceStatus.UP; 16 | } 17 | 18 | return InstanceInfo.InstanceStatus.DOWN; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /karyon2-eureka/src/main/java/netflix/karyon/eureka/EurekaHealthCheckHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Netflix, Inc. 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 netflix.karyon.eureka; 18 | 19 | import com.netflix.appinfo.InstanceInfo; 20 | import netflix.karyon.health.HealthCheckHandler; 21 | 22 | import javax.inject.Inject; 23 | 24 | /** 25 | * @author Nitesh Kant 26 | */ 27 | public class EurekaHealthCheckHandler implements com.netflix.appinfo.HealthCheckHandler { 28 | 29 | private final HealthCheckHandler healthCheckHandler; 30 | private final EurekaKaryonStatusBridge eurekaKaryonStatusBridge; 31 | 32 | @Inject 33 | public EurekaHealthCheckHandler(HealthCheckHandler healthCheckHandler, 34 | EurekaKaryonStatusBridge eurekaKaryonStatusBridge) { 35 | this.healthCheckHandler = healthCheckHandler; 36 | this.eurekaKaryonStatusBridge = eurekaKaryonStatusBridge; 37 | } 38 | 39 | @Override 40 | public InstanceInfo.InstanceStatus getStatus(InstanceInfo.InstanceStatus currentStatus) { 41 | int healthStatus = healthCheckHandler.getStatus(); 42 | return eurekaKaryonStatusBridge.interpretKaryonStatus(healthStatus); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /karyon2-eureka/src/main/java/netflix/karyon/eureka/EurekaKaryonStatusBridge.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.eureka; 2 | 3 | import com.google.inject.ImplementedBy; 4 | import com.netflix.appinfo.InstanceInfo; 5 | 6 | /** 7 | * @author Nitesh Kant 8 | */ 9 | @ImplementedBy(DefaultEurekaKaryonStatusBridge.class) 10 | public interface EurekaKaryonStatusBridge { 11 | 12 | InstanceInfo.InstanceStatus interpretKaryonStatus(int karyonStatus); 13 | } 14 | -------------------------------------------------------------------------------- /karyon2-eureka/src/main/java/netflix/karyon/eureka/KaryonEurekaModule.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.eureka; 2 | 3 | import com.google.inject.AbstractModule; 4 | import com.google.inject.binder.LinkedBindingBuilder; 5 | import com.netflix.appinfo.ApplicationInfoManager; 6 | import com.netflix.appinfo.EurekaInstanceConfig; 7 | import com.netflix.appinfo.providers.CloudInstanceConfigProvider; 8 | import com.netflix.discovery.DiscoveryClient; 9 | import com.netflix.discovery.EurekaClientConfig; 10 | import com.netflix.discovery.EurekaNamespace; 11 | import com.netflix.discovery.providers.DefaultEurekaClientConfigProvider; 12 | import com.netflix.governator.guice.BootstrapModule; 13 | import netflix.karyon.Karyon; 14 | 15 | /** 16 | * Initialize Eureka, by binding the "eureka." namespace and adding providers for EurekaClientConfig 17 | * and EurekaInstanceConfig. 18 | * 19 | * @author Nitesh Kant 20 | */ 21 | public class KaryonEurekaModule extends AbstractModule { 22 | 23 | private final String eurekaNamespace; 24 | 25 | public KaryonEurekaModule() { 26 | this("eureka."); 27 | } 28 | 29 | public KaryonEurekaModule(String eurekaNamespace) { 30 | this.eurekaNamespace = eurekaNamespace; 31 | } 32 | 33 | @Override 34 | protected void configure() { 35 | bind(com.netflix.appinfo.HealthCheckHandler.class).to(EurekaHealthCheckHandler.class); 36 | bind(ApplicationInfoManager.class).asEagerSingleton(); 37 | bind(DiscoveryClient.class).asEagerSingleton(); 38 | 39 | configureEureka(); 40 | } 41 | 42 | protected void configureEureka() { 43 | bindEurekaNamespace().toInstance(eurekaNamespace); 44 | bindEurekaInstanceConfig().toProvider(CloudInstanceConfigProvider.class); 45 | bindEurekaClientConfig().toProvider(DefaultEurekaClientConfigProvider.class); 46 | } 47 | 48 | protected LinkedBindingBuilder bindEurekaInstanceConfig() { 49 | return bind(EurekaInstanceConfig.class); 50 | } 51 | 52 | protected LinkedBindingBuilder bindEurekaClientConfig() { 53 | return bind(EurekaClientConfig.class); 54 | } 55 | 56 | protected LinkedBindingBuilder bindEurekaNamespace() { 57 | return bind(String.class).annotatedWith(EurekaNamespace.class); 58 | } 59 | 60 | public static BootstrapModule asBootstrapModule() { 61 | return Karyon.toBootstrapModule(KaryonEurekaModule.class); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /karyon2-examples/README.md: -------------------------------------------------------------------------------- 1 | Karyon Examples 2 | ================ 3 | 4 | This module provides a catalog for the variety of ways to interact with karyon. 5 | 6 | Examples Catalog 7 | ================ 8 | 9 | Category | Example | Description 10 | -------------------|----------------------------------------------------------------------------------------------|------------ 11 | Simple URI Routing | [Annotation based](src/main/java/netflix/karyon/examples/hellonoss/server/simple/annotation) | A simple URI based routing application that uses karyon's annotation based bootstrapping model. 12 | Simple URI Routing | [Guice module based](src/main/java/netflix/karyon/examples/hellonoss/server/simple/module) | A simple URI based routing application that uses karyon's guice modules based bootstrapping model. 13 | Jersey | [Annotation based](src/main/java/netflix/karyon/examples/hellonoss/server/jersey) | An example of how to use blocking jersey resources inside karyon. 14 | RxNetty | [Guice module based](src/main/java/netflix/karyon/examples/hellonoss/server/rxnetty) | An example of how to directly use an RxNetty based `RequestHandler` inside karyon. 15 | TCP | [Karyon TCP server](src/main/java/netflix/karyon/examples/tcp) | An example of how to create a raw TCP karyon server. 16 | WebSockets | [Karyon WebSocket Echo server](src/main/java/netflix/karyon/examples/websockets) | An example of WebSockets server. 17 | 18 | Build 19 | ===== 20 | 21 | To build: 22 | 23 | ``` 24 | $ cd karyon/karyon-examples 25 | $ ../gradlew build 26 | ``` 27 | 28 | Run 29 | === 30 | 31 | It is possible to run these examples using Gradle. For list of available tasks check "Examples" group 32 | in the gradle task list: 33 | 34 | ``` 35 | $ ../gradlew tasks 36 | ``` 37 | 38 | For example to run the simple URI router example run the following command: 39 | 40 | ``` 41 | $ ../gradlew runSimpleRouterHelloNOSS 42 | ``` 43 | 44 | Some of the examples require parameters. They must be passed with ```-P=``` option. 45 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/common/LoggingInterceptor.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.common; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 5 | import io.reactivex.netty.protocol.http.server.HttpServerResponse; 6 | import netflix.karyon.transport.interceptor.DuplexInterceptor; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import rx.Observable; 10 | 11 | /** 12 | * @author Nitesh Kant 13 | */ 14 | public class LoggingInterceptor implements DuplexInterceptor, HttpServerResponse> { 15 | 16 | private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class); 17 | 18 | private static int count; 19 | private final int id; 20 | 21 | public LoggingInterceptor() { 22 | id = ++count; 23 | } 24 | 25 | @Override 26 | public Observable in(HttpServerRequest request, HttpServerResponse response) { 27 | logger.info("Logging interceptor with id {} invoked for direction IN.", id); 28 | return Observable.empty(); 29 | } 30 | 31 | @Override 32 | public Observable out(HttpServerResponse response) { 33 | logger.info("Logging interceptor with id {} invoked for direction OUT.", id); 34 | return Observable.empty(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/common/auth/AuthInterceptor.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.common.auth; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 5 | import io.reactivex.netty.protocol.http.server.HttpServerResponse; 6 | import netflix.karyon.transport.interceptor.InboundInterceptor; 7 | import rx.Observable; 8 | import rx.functions.Func1; 9 | 10 | import javax.inject.Inject; 11 | 12 | /** 13 | * @author Nitesh Kant 14 | */ 15 | public class AuthInterceptor implements InboundInterceptor, HttpServerResponse> { 16 | 17 | private final AuthenticationService authService; 18 | 19 | @Inject 20 | public AuthInterceptor(AuthenticationService authService) { 21 | this.authService = authService; 22 | } 23 | 24 | @Override 25 | public Observable in(HttpServerRequest request, HttpServerResponse response) { 26 | return authService.authenticate(request).map(new Func1() { 27 | @Override 28 | public Void call(Boolean aBoolean) { 29 | return null; 30 | } 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/common/auth/AuthenticationService.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.common.auth; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 5 | import rx.Observable; 6 | 7 | /** 8 | * @author Nitesh Kant 9 | */ 10 | public interface AuthenticationService { 11 | 12 | Observable authenticate(HttpServerRequest request); 13 | } 14 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/common/auth/AuthenticationServiceImpl.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.common.auth; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 5 | import rx.Observable; 6 | 7 | /** 8 | * @author Nitesh Kant 9 | */ 10 | public class AuthenticationServiceImpl implements AuthenticationService { 11 | 12 | public static final String AUTH_HEADER_NAME = "MY-USER-ID"; 13 | 14 | @Override 15 | public Observable authenticate(HttpServerRequest request) { 16 | if (request.getHeaders().contains(AUTH_HEADER_NAME)) { 17 | return Observable.just(Boolean.TRUE); 18 | } else { 19 | return Observable.error(new IllegalArgumentException("Should pass a header: " + AUTH_HEADER_NAME)); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/common/health/HealthCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Netflix, Inc. 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 netflix.karyon.examples.hellonoss.common.health; 18 | 19 | import com.google.inject.Singleton; 20 | import netflix.karyon.health.HealthCheckHandler; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import javax.annotation.PostConstruct; 25 | 26 | /** 27 | * @author Nitesh Kant (nkant@netflix.com) 28 | */ 29 | @Singleton 30 | public class HealthCheck implements HealthCheckHandler { 31 | 32 | private static final Logger logger = LoggerFactory.getLogger(HealthCheck.class); 33 | 34 | @PostConstruct 35 | public void init() { 36 | logger.info("Health check initialized."); 37 | } 38 | 39 | @Override 40 | public int getStatus() { 41 | // TODO: Health check logic. 42 | logger.info("Health check invoked."); 43 | return 200; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/jersey/HealthcheckResource.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.server.jersey; 2 | 3 | import com.google.inject.Inject; 4 | import netflix.karyon.health.HealthCheckHandler; 5 | 6 | import javax.ws.rs.GET; 7 | import javax.ws.rs.Path; 8 | import javax.ws.rs.Produces; 9 | import javax.ws.rs.core.MediaType; 10 | import javax.ws.rs.core.Response; 11 | 12 | /** 13 | * @author Nitesh Kant 14 | */ 15 | @Path("/healthcheck") 16 | public class HealthcheckResource { 17 | 18 | private final HealthCheckHandler healthCheckHandler; 19 | 20 | @Inject 21 | public HealthcheckResource(HealthCheckHandler healthCheckHandler) { 22 | this.healthCheckHandler = healthCheckHandler; 23 | } 24 | 25 | @GET 26 | @Produces(MediaType.APPLICATION_JSON) 27 | public Response healthcheck() { 28 | return Response.status(healthCheckHandler.getStatus()).build(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/jersey/JerseyHelloWorldApp.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.server.jersey; 2 | 3 | import com.netflix.governator.annotations.Modules; 4 | import netflix.adminresources.resources.KaryonWebAdminModule; 5 | import netflix.karyon.KaryonBootstrap; 6 | import netflix.karyon.ShutdownModule; 7 | import netflix.karyon.archaius.ArchaiusBootstrap; 8 | import netflix.karyon.examples.hellonoss.common.LoggingInterceptor; 9 | import netflix.karyon.examples.hellonoss.common.auth.AuthInterceptor; 10 | import netflix.karyon.examples.hellonoss.common.auth.AuthenticationService; 11 | import netflix.karyon.examples.hellonoss.common.auth.AuthenticationServiceImpl; 12 | import netflix.karyon.examples.hellonoss.common.health.HealthCheck; 13 | import netflix.karyon.examples.hellonoss.server.jersey.JerseyHelloWorldApp.KaryonJerseyModuleImpl; 14 | import netflix.karyon.jersey.blocking.KaryonJerseyModule; 15 | import netflix.karyon.servo.KaryonServoModule; 16 | 17 | @ArchaiusBootstrap 18 | @KaryonBootstrap(name = "hello-netflix-oss", healthcheck = HealthCheck.class) 19 | @Modules(include = { 20 | ShutdownModule.class, 21 | KaryonWebAdminModule.class, 22 | // KaryonEurekaModule.class, // Uncomment this to enable Eureka client. 23 | KaryonJerseyModuleImpl.class, 24 | KaryonServoModule.class 25 | }) 26 | public interface JerseyHelloWorldApp { 27 | 28 | class KaryonJerseyModuleImpl extends KaryonJerseyModule { 29 | @Override 30 | protected void configureServer() { 31 | bind(AuthenticationService.class).to(AuthenticationServiceImpl.class); 32 | interceptorSupport().forUri("/*").intercept(LoggingInterceptor.class); 33 | interceptorSupport().forUri("/hello").interceptIn(AuthInterceptor.class); 34 | server().port(8888).threadPoolSize(100); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/jersey/README.md: -------------------------------------------------------------------------------- 1 | Hello Netflix OSS (Jersey) 2 | ====== 3 | 4 | A helloworld using jersey based endpoints. 5 | 6 | Apart from the common modules used by all examples, this example uses the following karyon module: 7 | 8 | * _[karyon-jersey-blocking](../../karyon-jersey-blocking) extension_: For jersey based resources. 9 | 10 | Running the example 11 | =================== 12 | 13 | This example can be run using gradle. 14 | 15 | `../gradlew runJerseyHelloNOSS` 16 | 17 | What to see 18 | =========== 19 | 20 | After the server starts, you can use the following commands to verify the server's endpoints: 21 | 22 | * _Hello to 'newbee'_: 23 | 24 | ``` 25 | curl -H"MY-USER-ID: nkant" "http://localhost:8888/hello/to/newbee" 26 | ``` 27 | Which will produce the output: 28 | ``` 29 | {"Message":"Hello newbee from Netflix OSS"} 30 | ``` 31 | 32 | * _Hello to Anonymous_: 33 | 34 | ``` 35 | curl -H"MY-USER-ID: nkant" "http://localhost:8888/hello/" 36 | ``` 37 | Which will produce the output: 38 | ``` 39 | {"Message":"Hello from Netflix OSS"} 40 | ``` 41 | 42 | * _Healthcheck_: 43 | 44 | ``` 45 | curl -v "http://localhost:8888/healthcheck" 46 | ``` 47 | Which will produce the output: 48 | ``` 49 | > GET /healthcheck HTTP/1.1 50 | > User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5 51 | > Host: localhost:8888 52 | > Accept: */* 53 | > 54 | < HTTP/1.1 200 OK 55 | < Content-Type: application/json 56 | < Transfer-Encoding: chunked 57 | < 58 | ``` 59 | 60 | This demonstrate the healthcheck endpoint added by this application and using karyon's `HealthCheckHandler` contract. 61 | 62 | * _Admin console_ 63 | 64 | Use the URL: `http://localhost:8077/` to navigate to karyon's admin console. 65 | 66 | This will take you to the karyon admin user interface. 67 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/rxnetty/MyApplicationRunner.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.server.rxnetty; 2 | 3 | import netflix.adminresources.resources.KaryonWebAdminModule; 4 | import netflix.karyon.Karyon; 5 | import netflix.karyon.KaryonBootstrapModule; 6 | import netflix.karyon.ShutdownModule; 7 | import netflix.karyon.archaius.ArchaiusBootstrapModule; 8 | import netflix.karyon.examples.hellonoss.common.health.HealthCheck; 9 | import netflix.karyon.servo.KaryonServoModule; 10 | import netflix.karyon.transport.http.health.HealthCheckEndpoint; 11 | 12 | /** 13 | * @author Nitesh Kant 14 | */ 15 | public class MyApplicationRunner { 16 | 17 | public static void main(String[] args) { 18 | HealthCheck healthCheckHandler = new HealthCheck(); 19 | Karyon.forRequestHandler(8888, 20 | new RxNettyHandler("/healthcheck", 21 | new HealthCheckEndpoint(healthCheckHandler)), 22 | new KaryonBootstrapModule(healthCheckHandler), 23 | new ArchaiusBootstrapModule("hello-netflix-oss"), 24 | // KaryonEurekaModule.asBootstrapModule(), /* Uncomment if you need eureka */ 25 | Karyon.toBootstrapModule(KaryonWebAdminModule.class), 26 | ShutdownModule.asBootstrapModule(), 27 | KaryonServoModule.asBootstrapModule() 28 | ).startAndWaitTillShutdown(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/rxnetty/README.md: -------------------------------------------------------------------------------- 1 | Hello Netflix OSS (RxNetty) 2 | ====== 3 | 4 | This helloworld example demonstrates how to directly use an [RxNetty](https://github.com/ReactiveX/RxNetty) 5 | `RequestHandler` inside karyon and still leverage all bootstrapping facilities of karyon. 6 | 7 | Running the example 8 | =================== 9 | 10 | This example can be run using gradle. 11 | 12 | `../gradlew runPureRxNettyHelloNOSS` 13 | 14 | What to see 15 | =========== 16 | 17 | After the server starts, you can use the following commands to verify the server's endpoints: 18 | 19 | * _Hello to 'newbee'_: 20 | 21 | ``` 22 | curl -H"MY-USER-ID: nkant" "http://localhost:8888/hello/to/newbee" 23 | ``` 24 | Which will produce the output: 25 | ``` 26 | {"Message":"Hello newbee from Netflix OSS"} 27 | ``` 28 | 29 | * _Hello to Anonymous_: 30 | 31 | ``` 32 | curl -H"MY-USER-ID: nkant" "http://localhost:8888/hello/" 33 | ``` 34 | Which will produce the output: 35 | ``` 36 | {"Message":"Hello from Netflix OSS"} 37 | ``` 38 | 39 | * _Healthcheck_: 40 | 41 | ``` 42 | curl -v "http://localhost:8888/healthcheck" 43 | ``` 44 | Which will produce the output: 45 | ``` 46 | > GET /healthcheck HTTP/1.1 47 | > User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5 48 | > Host: localhost:8888 49 | > Accept: */* 50 | > 51 | < HTTP/1.1 200 OK 52 | < Content-Type: application/json 53 | < Transfer-Encoding: chunked 54 | < 55 | ``` 56 | 57 | This demonstrate the healthcheck endpoint added by this application and using karyon's `HealthCheckHandler` contract. 58 | 59 | * _Admin console_ 60 | 61 | Use the URL: `http://localhost:8077/` to navigate to karyon's admin console. 62 | 63 | This will take you to the karyon admin user interface. 64 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/rxnetty/RxNettyHandler.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.server.rxnetty; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.handler.codec.http.HttpResponseStatus; 5 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 6 | import io.reactivex.netty.protocol.http.server.HttpServerResponse; 7 | import io.reactivex.netty.protocol.http.server.RequestHandler; 8 | import netflix.karyon.transport.http.health.HealthCheckEndpoint; 9 | import rx.Observable; 10 | 11 | /** 12 | * @author Nitesh Kant 13 | */ 14 | public class RxNettyHandler implements RequestHandler { 15 | 16 | private final String healthCheckUri; 17 | private final HealthCheckEndpoint healthCheckEndpoint; 18 | 19 | public RxNettyHandler(String healthCheckUri, HealthCheckEndpoint healthCheckEndpoint) { 20 | this.healthCheckUri = healthCheckUri; 21 | this.healthCheckEndpoint = healthCheckEndpoint; 22 | } 23 | 24 | @Override 25 | public Observable handle(HttpServerRequest request, HttpServerResponse response) { 26 | if (request.getUri().startsWith(healthCheckUri)) { 27 | return healthCheckEndpoint.handle(request, response); 28 | } else if (request.getUri().startsWith("/hello/to/")) { 29 | int prefixLength = "/hello/to".length(); 30 | String userName = request.getPath().substring(prefixLength); 31 | if (userName.isEmpty() || userName.length() == 1 /*The uri is /hello/to/ but no name */) { 32 | response.setStatus(HttpResponseStatus.BAD_REQUEST); 33 | return response.writeStringAndFlush( 34 | "{\"Error\":\"Please provide a username to say hello. The URI should be /hello/to/{username}\"}"); 35 | } else { 36 | String msg = "Hello " + userName.substring(1) /*Remove the / prefix*/ + " from Netflix OSS"; 37 | return response.writeStringAndFlush("{\"Message\":\"" + msg + "\"}"); 38 | } 39 | } else if (request.getUri().startsWith("/hello")) { 40 | return response.writeStringAndFlush("{\"Message\":\"Hello newbee from Netflix OSS\"}"); 41 | } else { 42 | response.setStatus(HttpResponseStatus.NOT_FOUND); 43 | return response.close(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/simple/HelloWorldEndpoint.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.server.simple; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.handler.codec.http.HttpResponseStatus; 5 | import io.reactivex.netty.channel.StringTransformer; 6 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 7 | import io.reactivex.netty.protocol.http.server.HttpServerResponse; 8 | import org.codehaus.jettison.json.JSONException; 9 | import org.codehaus.jettison.json.JSONObject; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import rx.Observable; 13 | 14 | /** 15 | * @author Tomasz Bak 16 | */ 17 | public class HelloWorldEndpoint { 18 | 19 | private static final Logger logger = LoggerFactory.getLogger(HelloWorldEndpoint.class); 20 | 21 | public Observable sayHello(HttpServerResponse response) { 22 | JSONObject content = new JSONObject(); 23 | try { 24 | content.put("Message", "Hello from Netflix OSS"); 25 | response.write(content.toString(), StringTransformer.DEFAULT_INSTANCE); 26 | return response.close(); 27 | } catch (JSONException e) { 28 | logger.error("Error creating json response.", e); 29 | return Observable.error(e); 30 | } 31 | } 32 | 33 | public Observable sayHelloToUser(HttpServerRequest request, HttpServerResponse response) { 34 | JSONObject content = new JSONObject(); 35 | 36 | int prefixLength = "/hello/to".length(); 37 | String userName = request.getPath().substring(prefixLength); 38 | 39 | try { 40 | if (userName.isEmpty() || userName.length() == 1 /*The uri is /hello/to/ but no name */) { 41 | response.setStatus(HttpResponseStatus.BAD_REQUEST); 42 | content.put("Error", "Please provide a username to say hello. The URI should be /hello/to/{username}"); 43 | } else { 44 | content.put("Message", "Hello " + userName.substring(1) /*Remove the / prefix*/ + " from Netflix OSS"); 45 | } 46 | } catch (JSONException e) { 47 | logger.error("Error creating json response.", e); 48 | return Observable.error(e); 49 | } 50 | 51 | response.write(content.toString(), StringTransformer.DEFAULT_INSTANCE); 52 | return response.close(); 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/simple/README.md: -------------------------------------------------------------------------------- 1 | Hello Netflix OSS (Simple Routing) 2 | ====== 3 | 4 | This helloworld example demonstrates how to use karyon's simple but powerful [SimpleUriRouter](https://github.com/Netflix/karyon/blob/master/karyon-core/src/main/java/com/netflix/karyon/transport/http/SimpleUriRouter.java) 5 | to provide HTTP endpoints. 6 | 7 | This module demonstrates how one can use karyon's annotation based bootstrapping and guice modules based bootstrapping 8 | as provided by [karyon-governator](https://github.com/Netflix/karyon/tree/master/karyon-governator) 9 | 10 | Running the example 11 | =================== 12 | 13 | This example can be run using gradle. 14 | 15 | * _Annotation based bootstrapping_: 16 | 17 | `../gradlew runSimpleRouterAnnotationHelloNOSS` 18 | 19 | * _Guice modules based bootstrapping_: 20 | 21 | `../gradlew runSimpleRouterGuiceHelloNOSS` 22 | 23 | What to see 24 | =========== 25 | 26 | After the server starts, you can use the following commands to verify the server's endpoints: 27 | 28 | * _Hello to 'newbee'_: 29 | 30 | ``` 31 | curl -H"MY-USER-ID: nkant" "http://localhost:8888/hello/to/newbee" 32 | ``` 33 | Which will produce the output: 34 | ``` 35 | {"Message":"Hello newbee from Netflix OSS"} 36 | ``` 37 | 38 | * _Hello to Anonymous_: 39 | 40 | ``` 41 | curl -H"MY-USER-ID: nkant" "http://localhost:8888/hello/" 42 | ``` 43 | Which will produce the output: 44 | ``` 45 | {"Message":"Hello from Netflix OSS"} 46 | ``` 47 | 48 | * _Healthcheck_: 49 | 50 | ``` 51 | curl -v "http://localhost:8888/healthcheck" 52 | ``` 53 | Which will produce the output: 54 | ``` 55 | > GET /healthcheck HTTP/1.1 56 | > User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5 57 | > Host: localhost:8888 58 | > Accept: */* 59 | > 60 | < HTTP/1.1 200 OK 61 | < Content-Type: application/json 62 | < Transfer-Encoding: chunked 63 | < 64 | ``` 65 | 66 | This demonstrate the healthcheck endpoint added by this application and using karyon's `HealthCheckHandler` contract. 67 | 68 | * _Admin console_ 69 | 70 | Use the URL: `http://localhost:8077/` to navigate to karyon's admin console. 71 | 72 | This will take you to the karyon admin user interface. 73 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/simple/SimpleRouter.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.server.simple; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 5 | import io.reactivex.netty.protocol.http.server.HttpServerResponse; 6 | import io.reactivex.netty.protocol.http.server.RequestHandler; 7 | import netflix.karyon.examples.hellonoss.common.health.HealthCheck; 8 | import netflix.karyon.transport.http.SimpleUriRouter; 9 | import netflix.karyon.transport.http.health.HealthCheckEndpoint; 10 | import rx.Observable; 11 | 12 | /** 13 | * A {@link RequestHandler} implementation for this example. 14 | * 15 | * @author Nitesh Kant 16 | */ 17 | public class SimpleRouter implements RequestHandler { 18 | 19 | private final SimpleUriRouter delegate; 20 | 21 | public SimpleRouter() { 22 | final HelloWorldEndpoint endpoint = new HelloWorldEndpoint(); 23 | delegate = new SimpleUriRouter(); 24 | 25 | delegate.addUri("/healthcheck", 26 | new HealthCheckEndpoint(new HealthCheck())) 27 | .addUri("/hello", 28 | new RequestHandler() { 29 | @Override 30 | public Observable handle( 31 | HttpServerRequest request, 32 | HttpServerResponse response) { 33 | return endpoint.sayHello(response); 34 | } 35 | }) 36 | .addUri("/hello/to/*", 37 | new RequestHandler() { 38 | @Override 39 | public Observable handle(HttpServerRequest request, 40 | HttpServerResponse response) { 41 | return endpoint.sayHelloToUser(request, response); 42 | } 43 | }); 44 | } 45 | 46 | @Override 47 | public Observable handle(HttpServerRequest request, HttpServerResponse response) { 48 | return delegate.handle(request, response); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/simple/annotation/README.md: -------------------------------------------------------------------------------- 1 | Hello Netflix OSS (Simple Routing - Annotations based bootstrapping) 2 | ====== 3 | 4 | This helloworld example demonstrates how to use karyon's simple but powerful [SimpleUriRouter](https://github.com/Netflix/karyon/blob/master/karyon-core/src/main/java/com/netflix/karyon/transport/http/SimpleUriRouter.java) 5 | to provide HTTP endpoints. 6 | 7 | This module uses karyon's annotation based bootstrapping as provided by [karyon-governator](https://github.com/Netflix/karyon/tree/master/karyon-governator) 8 | 9 | Running the example 10 | =================== 11 | 12 | This example can be run using gradle. 13 | 14 | `../gradlew runSimpleRouterAnnotationHelloNOSS` 15 | 16 | What to see 17 | =========== 18 | 19 | After the server starts, you can use the following commands to verify the server's endpoints: 20 | 21 | * _Hello to 'newbee'_: 22 | 23 | ``` 24 | curl -H"MY-USER-ID: nkant" "http://localhost:8888/hello/to/newbee" 25 | ``` 26 | Which will produce the output: 27 | ``` 28 | {"Message":"Hello newbee from Netflix OSS"} 29 | ``` 30 | 31 | * _Hello to Anonymous_: 32 | 33 | ``` 34 | curl -H"MY-USER-ID: nkant" "http://localhost:8888/hello/" 35 | ``` 36 | Which will produce the output: 37 | ``` 38 | {"Message":"Hello from Netflix OSS"} 39 | ``` 40 | 41 | * _Healthcheck_: 42 | 43 | ``` 44 | curl -v "http://localhost:8888/healthcheck" 45 | ``` 46 | Which will produce the output: 47 | ``` 48 | > GET /healthcheck HTTP/1.1 49 | > User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5 50 | > Host: localhost:8888 51 | > Accept: */* 52 | > 53 | < HTTP/1.1 200 OK 54 | < Content-Type: application/json 55 | < Transfer-Encoding: chunked 56 | < 57 | ``` 58 | 59 | This demonstrate the healthcheck endpoint added by this application and using karyon's `HealthCheckHandler` contract. 60 | 61 | * _Admin console_ 62 | 63 | Use the URL: `http://localhost:8077/` to navigate to karyon's admin console. 64 | 65 | This will take you to the karyon admin user interface. 66 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/simple/annotation/SimpleRoutingApp.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.server.simple.annotation; 2 | 3 | import com.google.inject.Singleton; 4 | import com.netflix.governator.annotations.Modules; 5 | import io.netty.buffer.ByteBuf; 6 | import netflix.adminresources.resources.KaryonWebAdminModule; 7 | import netflix.karyon.KaryonBootstrap; 8 | import netflix.karyon.ShutdownModule; 9 | import netflix.karyon.archaius.ArchaiusBootstrap; 10 | import netflix.karyon.examples.hellonoss.common.LoggingInterceptor; 11 | import netflix.karyon.examples.hellonoss.common.auth.AuthInterceptor; 12 | import netflix.karyon.examples.hellonoss.common.auth.AuthenticationService; 13 | import netflix.karyon.examples.hellonoss.common.auth.AuthenticationServiceImpl; 14 | import netflix.karyon.examples.hellonoss.common.health.HealthCheck; 15 | import netflix.karyon.examples.hellonoss.server.simple.SimpleRouter; 16 | import netflix.karyon.examples.hellonoss.server.simple.annotation.SimpleRoutingApp.KaryonRxRouterModuleImpl; 17 | import netflix.karyon.servo.KaryonServoModule; 18 | import netflix.karyon.transport.http.KaryonHttpModule; 19 | 20 | /** 21 | * @author Tomasz Bak 22 | */ 23 | @ArchaiusBootstrap 24 | @KaryonBootstrap(name = "hello-netflix-oss", healthcheck = HealthCheck.class) 25 | @Singleton 26 | @Modules(include = { 27 | ShutdownModule.class, 28 | KaryonServoModule.class, 29 | KaryonWebAdminModule.class, 30 | // KaryonEurekaModule.class, // Uncomment this to enable Eureka client. 31 | KaryonRxRouterModuleImpl.class 32 | }) 33 | public interface SimpleRoutingApp { 34 | 35 | class KaryonRxRouterModuleImpl extends KaryonHttpModule { 36 | 37 | public KaryonRxRouterModuleImpl() { 38 | super("httpServerA", ByteBuf.class, ByteBuf.class); 39 | } 40 | 41 | @Override 42 | protected void configureServer() { 43 | bindRouter().toInstance(new SimpleRouter()); 44 | 45 | bind(AuthenticationService.class).to(AuthenticationServiceImpl.class); 46 | interceptorSupport().forUri("/*").intercept(LoggingInterceptor.class); 47 | interceptorSupport().forUri("/hello").interceptIn(AuthInterceptor.class); 48 | 49 | server().port(8888); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/simple/module/README.md: -------------------------------------------------------------------------------- 1 | Hello Netflix OSS (Simple Routing - Guice module based bootstrapping) 2 | ====== 3 | 4 | This helloworld example demonstrates how to use karyon's simple but powerful [SimpleUriRouter](https://github.com/Netflix/karyon/blob/master/karyon-core/src/main/java/com/netflix/karyon/transport/http/SimpleUriRouter.java) 5 | to provide HTTP endpoints. 6 | 7 | This module uses karyon's guice module based bootstrapping as provided by [karyon-governator](https://github.com/Netflix/karyon/tree/master/karyon-governator) 8 | 9 | Running the example 10 | =================== 11 | 12 | This example can be run using gradle. 13 | 14 | `../gradlew runSimpleRouterGuiceHelloNOSS` 15 | 16 | What to see 17 | =========== 18 | 19 | After the server starts, you can use the following commands to verify the server's endpoints: 20 | 21 | * _Hello to 'newbee'_: 22 | 23 | ``` 24 | curl -H"MY-USER-ID: nkant" "http://localhost:8888/hello/to/newbee" 25 | ``` 26 | Which will produce the output: 27 | ``` 28 | {"Message":"Hello newbee from Netflix OSS"} 29 | ``` 30 | 31 | * _Hello to Anonymous_: 32 | 33 | ``` 34 | curl -H"MY-USER-ID: nkant" "http://localhost:8888/hello/" 35 | ``` 36 | Which will produce the output: 37 | ``` 38 | {"Message":"Hello from Netflix OSS"} 39 | ``` 40 | 41 | * _Healthcheck_: 42 | 43 | ``` 44 | curl -v "http://localhost:8888/healthcheck" 45 | ``` 46 | Which will produce the output: 47 | ``` 48 | > GET /healthcheck HTTP/1.1 49 | > User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5 50 | > Host: localhost:8888 51 | > Accept: */* 52 | > 53 | < HTTP/1.1 200 OK 54 | < Content-Type: application/json 55 | < Transfer-Encoding: chunked 56 | < 57 | ``` 58 | 59 | This demonstrate the healthcheck endpoint added by this application and using karyon's `HealthCheckHandler` contract. 60 | 61 | * _Admin console_ 62 | 63 | Use the URL: `http://localhost:8077/` to navigate to karyon's admin console. 64 | 65 | This will take you to the karyon admin user interface. 66 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/simple/module/RouterWithInterceptors.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.server.simple.module; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 5 | import io.reactivex.netty.protocol.http.server.HttpServerResponse; 6 | import io.reactivex.netty.protocol.http.server.RequestHandler; 7 | import netflix.karyon.examples.hellonoss.common.LoggingInterceptor; 8 | import netflix.karyon.examples.hellonoss.common.auth.AuthInterceptor; 9 | import netflix.karyon.examples.hellonoss.common.auth.AuthenticationServiceImpl; 10 | import netflix.karyon.examples.hellonoss.server.simple.SimpleRouter; 11 | import netflix.karyon.transport.http.HttpInterceptorSupport; 12 | import netflix.karyon.transport.http.HttpRequestHandler; 13 | import rx.Observable; 14 | 15 | /** 16 | * @author Nitesh Kant 17 | */ 18 | public class RouterWithInterceptors implements RequestHandler { 19 | 20 | private final HttpRequestHandler delegate; 21 | 22 | public RouterWithInterceptors() { 23 | SimpleRouter router = new SimpleRouter(); 24 | HttpInterceptorSupport interceptorSupport = new HttpInterceptorSupport(); 25 | interceptorSupport.forUri("/*").intercept(new LoggingInterceptor()); 26 | interceptorSupport.forUri("/hello").intercept(new AuthInterceptor(new AuthenticationServiceImpl())); 27 | delegate = new HttpRequestHandler(router, interceptorSupport); 28 | } 29 | 30 | @Override 31 | public Observable handle(HttpServerRequest request, HttpServerResponse response) { 32 | return delegate.handle(request, response); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/hellonoss/server/simple/module/SimpleRunner.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.hellonoss.server.simple.module; 2 | 3 | import netflix.adminresources.resources.KaryonWebAdminModule; 4 | import netflix.karyon.Karyon; 5 | import netflix.karyon.KaryonBootstrapModule; 6 | import netflix.karyon.ShutdownModule; 7 | import netflix.karyon.archaius.ArchaiusBootstrapModule; 8 | import netflix.karyon.servo.KaryonServoModule; 9 | 10 | /** 11 | * @author Nitesh Kant 12 | */ 13 | public class SimpleRunner { 14 | 15 | public static void main(String[] args) { 16 | 17 | Karyon.forRequestHandler(8888, 18 | // new SimpleRouter(), /* Use this instead of RouterWithInterceptors below if interceptors are not required */ 19 | new RouterWithInterceptors(), 20 | new KaryonBootstrapModule(), 21 | new ArchaiusBootstrapModule("hello-netflix-oss"), 22 | // KaryonEurekaModule.asBootstrapModule(), /* Uncomment if you need eureka */ 23 | Karyon.toBootstrapModule(KaryonWebAdminModule.class), 24 | ShutdownModule.asBootstrapModule(), 25 | KaryonServoModule.asBootstrapModule()) 26 | .startAndWaitTillShutdown(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/tcp/README.md: -------------------------------------------------------------------------------- 1 | TCP pipeline 2 | ====== 3 | 4 | It is a simple example of how to run multiple Karyon TCP servers. 5 | There are two servers created: 6 | * frontend, that reads user input and sends it an internal queue 7 | * backend, that reads messages from the internal queue and sends them out to a user 8 | 9 | Running the example 10 | =================== 11 | 12 | `../gradlew runTcpPipelineApp` 13 | 14 | What to see 15 | =========== 16 | 17 | * _Message pipeline_ 18 | 19 | After the server starts, connect with telnet to frontend and backend servers: 20 | * frontend:```telnet localhost 7770``` 21 | * backend: ```telnet localhost 7771``` 22 | 23 | The text entered on first client, should be print out on the second one. 24 | 25 | * _Admin console_ 26 | 27 | Use the URL: `http://localhost:8077/` to navigate to karyon's admin console. 28 | 29 | This will take you to the karyon admin user interface. 30 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/tcp/TcpPipelineApp.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.tcp; 2 | 3 | import com.google.inject.AbstractModule; 4 | import com.netflix.governator.annotations.Modules; 5 | import io.netty.buffer.ByteBuf; 6 | import netflix.adminresources.resources.KaryonWebAdminModule; 7 | import netflix.karyon.KaryonBootstrap; 8 | import netflix.karyon.ShutdownModule; 9 | import netflix.karyon.archaius.ArchaiusBootstrap; 10 | import netflix.karyon.examples.tcp.TcpPipelineApp.ApplicationModule; 11 | import netflix.karyon.examples.tcp.TcpPipelineApp.TcpBackendModule; 12 | import netflix.karyon.examples.tcp.TcpPipelineApp.TcpFrontendModule; 13 | import netflix.karyon.transport.tcp.KaryonTcpModule; 14 | 15 | /** 16 | * @author Tomasz Bak 17 | */ 18 | @ArchaiusBootstrap 19 | @KaryonBootstrap(name = "sample-rxnetty-tcp-noss") 20 | @Modules(include = { 21 | ShutdownModule.class, 22 | KaryonWebAdminModule.class, 23 | // KaryonEurekaModule.class, // Uncomment this to enable Eureka client. 24 | ApplicationModule.class, 25 | TcpFrontendModule.class, TcpBackendModule.class 26 | }) 27 | public interface TcpPipelineApp { 28 | 29 | class ApplicationModule extends AbstractModule { 30 | @Override 31 | protected void configure() { 32 | bind(TcpPipelineHandlers.QueueProvider.class).asEagerSingleton(); 33 | } 34 | } 35 | 36 | class TcpFrontendModule extends KaryonTcpModule { 37 | public TcpFrontendModule() { 38 | super("tcpFrontServer", ByteBuf.class, ByteBuf.class); 39 | } 40 | 41 | @Override 42 | protected void configureServer() { 43 | bindConnectionHandler().to(TcpPipelineHandlers.FrontendConnectionHandler.class); 44 | server().port(7770); 45 | } 46 | } 47 | 48 | class TcpBackendModule extends KaryonTcpModule { 49 | public TcpBackendModule() { 50 | super("tcpBackendServer", ByteBuf.class, ByteBuf.class); 51 | } 52 | 53 | @Override 54 | protected void configureServer() { 55 | bindConnectionHandler().to(TcpPipelineHandlers.BackendConnectionHandler.class); 56 | server().port(7771); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/websockets/README.md: -------------------------------------------------------------------------------- 1 | WebSocket Example 2 | ====== 3 | 4 | It is a simple example of how to run WebSocket server with Karyon. 5 | 6 | Running the example 7 | =================== 8 | 9 | `../gradlew runWebSocketEcho` 10 | 11 | What to see 12 | =========== 13 | 14 | Connect with any WebSocket client and send a text message at localhost:8888. 15 | You should get a reply with the same content, but all letters capitalized. -------------------------------------------------------------------------------- /karyon2-examples/src/main/java/netflix/karyon/examples/websockets/WebSocketEchoServer.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.examples.websockets; 2 | 3 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; 4 | import io.netty.handler.codec.http.websocketx.WebSocketFrame; 5 | import io.reactivex.netty.RxNetty; 6 | import io.reactivex.netty.channel.ConnectionHandler; 7 | import io.reactivex.netty.channel.ObservableConnection; 8 | import io.reactivex.netty.server.RxServer; 9 | import netflix.adminresources.resources.KaryonWebAdminModule; 10 | import netflix.karyon.Karyon; 11 | import netflix.karyon.KaryonBootstrapModule; 12 | import netflix.karyon.ShutdownModule; 13 | import netflix.karyon.archaius.ArchaiusBootstrapModule; 14 | import netflix.karyon.servo.KaryonServoModule; 15 | import rx.Observable; 16 | import rx.functions.Func1; 17 | 18 | /** 19 | * Simple WebSockets echo server. 20 | * 21 | * @author Tomasz Bak 22 | */ 23 | public final class WebSocketEchoServer { 24 | 25 | public static void main(final String[] args) { 26 | RxServer webSocketServer = RxNetty.newWebSocketServerBuilder( 27 | 8888, 28 | new ConnectionHandler() { 29 | @Override 30 | public Observable handle(final ObservableConnection connection) { 31 | return connection.getInput().flatMap(new Func1>() { 32 | @Override 33 | public Observable call(WebSocketFrame wsFrame) { 34 | TextWebSocketFrame textFrame = (TextWebSocketFrame) wsFrame; 35 | System.out.println("Got message: " + textFrame.text()); 36 | return connection.writeAndFlush(new TextWebSocketFrame(textFrame.text().toUpperCase())); 37 | } 38 | }); 39 | } 40 | } 41 | ).build(); 42 | Karyon.forWebSocketServer( 43 | webSocketServer, 44 | new KaryonBootstrapModule(), 45 | new ArchaiusBootstrapModule("websocket-echo-server"), 46 | // KaryonEurekaModule.asBootstrapModule(), /* Uncomment if you need eureka */ 47 | Karyon.toBootstrapModule(KaryonWebAdminModule.class), 48 | ShutdownModule.asBootstrapModule(), 49 | KaryonServoModule.asBootstrapModule()) 50 | .startAndWaitTillShutdown(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/resources/eureka-client.properties: -------------------------------------------------------------------------------- 1 | # Eureka Client configuration for your service. These properties are used by eureka to contact the eureka server 2 | # for all eureka operations. 3 | # Properties based configuration for eureka client. The properties specified here is mostly what the users 4 | # need to change. All of these can be specified as a java system property with -D option (eg)-Deureka.region=us-east-1 5 | # Refer to eureka wiki (https://github.com/Netflix/eureka/wiki/Configuring-Eureka) for details about these configurations. 6 | 7 | 8 | #Region where eureka is deployed -For AWS specify one of the AWS regions, for other datacenters specify a arbitrary string 9 | #indicating the region.This is normally specified as a -D option (eg) -Deureka.region=us-east-1 10 | eureka.region=default 11 | 12 | #Name of the application to be identified by other services 13 | 14 | eureka.name=hello-netflix-oss 15 | 16 | #Virtual host name by which the clients identifies this service 17 | eureka.vipAddress=hello-netflix-oss.mydomain.net 18 | 19 | #The port where the service will be running and serving requests 20 | eureka.port=8001 21 | 22 | #For eureka clients running in eureka server, it needs to connect to servers in other zones 23 | eureka.preferSameZone=false 24 | 25 | #Change this if you want to use a DNS based lookup for determining other eureka servers. 26 | eureka.shouldUseDns=false 27 | 28 | eureka.us-east-1.availabilityZones=default 29 | 30 | eureka.serviceUrl.default=http://us-east-1.discoverytest.netflix.net:7001/discovery/v2/ 31 | -------------------------------------------------------------------------------- /karyon2-examples/src/main/resources/hello-netflix-oss-dev.properties: -------------------------------------------------------------------------------- 1 | eureka.validateInstanceId=false -------------------------------------------------------------------------------- /karyon2-examples/src/main/resources/hello-netflix-oss.properties: -------------------------------------------------------------------------------- 1 | com.sun.jersey.config.property.packages=netflix.karyon.examples.hellonoss -------------------------------------------------------------------------------- /karyon2-examples/src/main/resources/sample-rxnetty-tcp-noss.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Netflix/karyon/d50bc0ff37693ef3fbda373e90a109d1f92e0b9a/karyon2-examples/src/main/resources/sample-rxnetty-tcp-noss.properties -------------------------------------------------------------------------------- /karyon2-examples/src/main/resources/simplelogger.properties: -------------------------------------------------------------------------------- 1 | org.slf4j.simpleLogger.defaultLogLevel=INFO 2 | org.slf4j.simplelogger.showdatetime=true 3 | org.slf4j.simplelogger.showthreadname=true 4 | 5 | -------------------------------------------------------------------------------- /karyon2-governator/README.md: -------------------------------------------------------------------------------- 1 | karyon-governator 2 | ====== 3 | 4 | This module provides bootstrapping for karyon using [Governator](https://github.com/Netflix/governator). Bootstrapping 5 | is categorized into two broad categories: 6 | 7 | #### Annotation Based 8 | 9 | This model leverages [Governators](https://github.com/Netflix/governator) `@Bootstrap` annotations to provide syntactic 10 | sugar for discovering applicable modules. 11 | Under this model, one provides all `@Bootstrap` annotations on a class/interface which is referred to as an 12 | _Application_ class and is consumed by Karyon to create a [KaryonServer](src/main/java/netflix/karyon/KaryonServer.java) 13 | 14 | An example of this model can be found under [karyon examples](../karyon2-examples) 15 | 16 | ###### KaryonRunner 17 | 18 | [KaryonRunner](src/main/java/netflix/karyon/KaryonRunner.java) is a utility class which can be used as the startup 19 | for all _Application_ classes created in this annotation based model. This class has a main method which expects an 20 | _Application_ class name to be passed as the program argument. 21 | 22 | #### Guice modules Based 23 | 24 | The annotation based model above leverages this basic guice module based bootstrapping model which requires the user to 25 | explicitly provide the guice modules which are required by the application. 26 | 27 | An example of this model can be found under[karyon examples](../karyon2-examples) 28 | -------------------------------------------------------------------------------- /karyon2-governator/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Netflix, Inc. 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 | apply plugin: 'osgi' 17 | 18 | dependencies { 19 | compile "com.netflix.governator:governator:${governator_version}" 20 | compile project(':karyon2-core') 21 | } 22 | 23 | jar { 24 | manifest { 25 | name = 'karyon2-governator' 26 | instruction 'Bundle-Vendor', 'Netflix' 27 | instruction 'Bundle-DocURL', 'https://github.com/Netflix/karyon' 28 | instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /karyon2-governator/src/main/java/netflix/karyon/AbstractKaryonServer.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon; 2 | 3 | import com.google.inject.Injector; 4 | import com.netflix.governator.guice.BootstrapModule; 5 | import com.netflix.governator.lifecycle.LifecycleManager; 6 | 7 | import java.util.Arrays; 8 | 9 | /** 10 | * @author Nitesh Kant 11 | * @deprecated 2016-07-20 Karyon2 no longer supported. See https://github.com/Netflix/karyon/issues/347 for more info 12 | */ 13 | @Deprecated 14 | abstract class AbstractKaryonServer implements KaryonServer { 15 | 16 | protected final BootstrapModule[] bootstrapModules; 17 | protected LifecycleManager lifecycleManager; 18 | protected Injector injector; 19 | 20 | public AbstractKaryonServer(BootstrapModule... bootstrapModules) { 21 | this.bootstrapModules = bootstrapModules; 22 | } 23 | 24 | @Override 25 | public final void start() { 26 | startWithAdditionalBootstrapModules(); 27 | } 28 | 29 | public final void startWithAdditionalBootstrapModules(BootstrapModule... additionalBootstrapModules) { 30 | BootstrapModule[] applicableBootstrapModules = this.bootstrapModules; 31 | if (null != additionalBootstrapModules && additionalBootstrapModules.length != 0) { 32 | applicableBootstrapModules = Arrays.copyOf(bootstrapModules, bootstrapModules.length + additionalBootstrapModules.length); 33 | System.arraycopy(additionalBootstrapModules, 0, applicableBootstrapModules, bootstrapModules.length, additionalBootstrapModules.length); 34 | } 35 | 36 | injector = newInjector(applicableBootstrapModules); 37 | 38 | startLifecycleManager(); 39 | _start(); 40 | } 41 | 42 | protected abstract void _start(); 43 | 44 | @Override 45 | public void shutdown() { 46 | if (lifecycleManager != null) { 47 | lifecycleManager.close(); 48 | } 49 | } 50 | 51 | @Override 52 | public void startAndWaitTillShutdown() { 53 | start(); 54 | waitTillShutdown(); 55 | } 56 | 57 | protected abstract Injector newInjector(BootstrapModule... applicableBootstrapModules); 58 | 59 | protected void startLifecycleManager() { 60 | lifecycleManager = injector.getInstance(LifecycleManager.class); 61 | try { 62 | lifecycleManager.start(); 63 | } catch (Exception e) { 64 | throw new RuntimeException(e); // So that this does not pollute the API. 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /karyon2-governator/src/main/java/netflix/karyon/KaryonBootstrap.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon; 2 | 3 | import com.netflix.governator.guice.annotations.Bootstrap; 4 | import netflix.karyon.health.AlwaysHealthyHealthCheck; 5 | import netflix.karyon.health.HealthCheckHandler; 6 | 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.ElementType; 9 | import java.lang.annotation.Retention; 10 | import java.lang.annotation.RetentionPolicy; 11 | import java.lang.annotation.Target; 12 | 13 | /** 14 | * @author Nitesh Kant 15 | * @deprecated 2016-07-20 Karyon2 no longer supported. See https://github.com/Netflix/karyon/issues/347 for more info 16 | */ 17 | @Documented 18 | @Retention(RetentionPolicy.RUNTIME) 19 | @Target(ElementType.TYPE) 20 | @Bootstrap(bootstrap = KaryonBootstrapModule.class) 21 | @Deprecated 22 | public @interface KaryonBootstrap { 23 | 24 | String name(); 25 | 26 | Class healthcheck() default AlwaysHealthyHealthCheck.class; 27 | } 28 | -------------------------------------------------------------------------------- /karyon2-governator/src/main/java/netflix/karyon/KaryonRunner.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon; 2 | 3 | import com.netflix.governator.guice.BootstrapModule; 4 | import com.netflix.governator.guice.annotations.Bootstrap; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | /** 9 | * An application runner which consumes a main class annotated with governator's {@link Bootstrap} annotations. 10 | * 11 | * This is shorthand for: 12 | * 13 |
14 |      com.netflix.karyon.forApplication(MyApp.class).startAndWaitTillShutdown()
15 |  
16 | * 17 | * where the name of the Application class is passed as the argument to the main method. 18 | * 19 | * This is useful while creating standard packaging scripts where the main class for starting the JVM remains the same 20 | * and the actual application class differs from one application to another. 21 | * 22 | * If you are bootstrapping karyon programmatically, it is better to use {@code Karyon} directly. 23 | * 24 | * @author Nitesh Kant 25 | * @deprecated 2016-07-20 Karyon2 no longer supported. See https://github.com/Netflix/karyon/issues/347 for more info 26 | */ 27 | @Deprecated 28 | public class KaryonRunner { 29 | 30 | private static final Logger logger = LoggerFactory.getLogger(KaryonRunner.class); 31 | 32 | public static void main(String[] args) { 33 | if (args.length == 0) { 34 | System.out.println("Usage: " + KaryonRunner.class.getCanonicalName() + "
"); 35 | System.exit(-1); 36 | } 37 | 38 | String mainClassName = args[0]; 39 | System.out.println("Using main class: " + mainClassName); 40 | 41 | try { 42 | Karyon.forApplication(Class.forName(mainClassName), (BootstrapModule[]) null) 43 | .startAndWaitTillShutdown(); 44 | } catch (@SuppressWarnings("UnusedCatchParameter") ClassNotFoundException e) { 45 | System.out.println("Main class: " + mainClassName + " not found."); 46 | System.exit(-1); 47 | } catch (Exception e) { 48 | logger.error("Error while starting karyon server.", e); 49 | System.exit(-1); 50 | } 51 | 52 | // In case we have non-daemon threads running 53 | System.exit(0); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /karyon2-governator/src/main/java/netflix/karyon/KaryonServer.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon; 2 | 3 | /** 4 | * A logical abstraction to manage the lifecycle of a karyon based application. 5 | * This does not define any contracts of handling and processing requests, those should all be defined by means of 6 | * modules. 7 | * @deprecated 2016-07-20 Karyon2 no longer supported. See https://github.com/Netflix/karyon/issues/347 for more info 8 | */ 9 | @Deprecated 10 | public interface KaryonServer { 11 | 12 | /** 13 | * Starts the server and hence the modules associated with this server. 14 | */ 15 | void start(); 16 | 17 | /** 18 | * Shutdown the server and hence the modules associated with this server. 19 | */ 20 | void shutdown(); 21 | 22 | /** 23 | * A utility method to block the caller thread till the server is shutdown (by external invocation). 24 | * This method does not start or shutdown the server. It just waits for shutdown. 25 | */ 26 | void waitTillShutdown(); 27 | 28 | /** 29 | * A shorthand for calling {@link #start()} and {@link #waitTillShutdown()} 30 | */ 31 | void startAndWaitTillShutdown(); 32 | } 33 | -------------------------------------------------------------------------------- /karyon2-governator/src/main/java/netflix/karyon/KaryonServerBackedServer.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon; 2 | 3 | import com.netflix.governator.guice.BootstrapModule; 4 | 5 | /** 6 | * An implementation of {@link KaryonServer} which wraps an existing {@link KaryonServer}. 7 | * 8 | * @author Nitesh Kant 9 | * @deprecated 2016-07-20 Karyon2 no longer supported. See https://github.com/Netflix/karyon/issues/347 for more info 10 | */ 11 | @Deprecated 12 | class KaryonServerBackedServer implements KaryonServer { 13 | 14 | private final AbstractKaryonServer delegate; 15 | private final BootstrapModule[] bootstrapModules; 16 | 17 | KaryonServerBackedServer(AbstractKaryonServer delegate, BootstrapModule... bootstrapModules) { 18 | this.delegate = delegate; 19 | this.bootstrapModules = bootstrapModules; 20 | } 21 | 22 | @Override 23 | public void start() { 24 | delegate.startWithAdditionalBootstrapModules(bootstrapModules); 25 | } 26 | 27 | @Override 28 | public void shutdown() { 29 | delegate.shutdown(); 30 | } 31 | 32 | @Override 33 | public void waitTillShutdown() { 34 | delegate.waitTillShutdown(); 35 | } 36 | 37 | @Override 38 | public void startAndWaitTillShutdown() { 39 | start(); 40 | waitTillShutdown(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /karyon2-governator/src/main/java/netflix/karyon/MainClassBasedServer.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon; 2 | 3 | import com.google.inject.Injector; 4 | import com.netflix.governator.guice.BootstrapModule; 5 | import com.netflix.governator.guice.LifecycleInjector; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.util.concurrent.CountDownLatch; 10 | 11 | /** 12 | * @author Nitesh Kant 13 | * @deprecated 2016-07-20 Karyon2 no longer supported. See https://github.com/Netflix/karyon/issues/347 for more info 14 | */ 15 | @Deprecated 16 | class MainClassBasedServer extends AbstractKaryonServer { 17 | 18 | private static final Logger logger = LoggerFactory.getLogger(MainClassBasedServer.class); 19 | 20 | private final Class mainClass; 21 | 22 | protected MainClassBasedServer(Class mainClass, BootstrapModule... bootstrapModules) { 23 | super(bootstrapModules); 24 | this.mainClass = mainClass; 25 | } 26 | 27 | @Override 28 | public void waitTillShutdown() { 29 | final CountDownLatch shutdownFinished = new CountDownLatch(1); 30 | 31 | Runtime.getRuntime().addShutdownHook(new Thread() { 32 | @Override 33 | public void run() { 34 | try { 35 | shutdown(); 36 | logger.info("Leaving main loop - shutdown finished."); 37 | } finally { 38 | shutdownFinished.countDown(); 39 | } 40 | } 41 | }); 42 | 43 | try { 44 | shutdownFinished.await(); 45 | } catch (InterruptedException e) { 46 | logger.error("Interrupted while waiting for shutdown.", e); 47 | Thread.interrupted(); 48 | throw new RuntimeException(e); 49 | } 50 | } 51 | 52 | @Override 53 | protected void _start() { 54 | // No Op. 55 | } 56 | 57 | @Override 58 | protected Injector newInjector(BootstrapModule... applicableBootstrapModules) { 59 | return LifecycleInjector.bootstrap(mainClass, applicableBootstrapModules); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /karyon2-governator/src/main/java/netflix/karyon/RxNettyServerBackedServer.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon; 2 | 3 | import com.netflix.governator.guice.BootstrapModule; 4 | import io.reactivex.netty.server.AbstractServer; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | /** 9 | * An implementation of {@link KaryonServer} which wraps an RxNetty's server. 10 | * 11 | * @author Nitesh Kant 12 | * @deprecated 2016-07-20 Karyon2 no longer supported. See https://github.com/Netflix/karyon/issues/347 for more info 13 | */ 14 | @Deprecated 15 | class RxNettyServerBackedServer extends MainClassBasedServer { 16 | 17 | private static final Logger logger = LoggerFactory.getLogger(RxNettyServerBackedServer.class); 18 | 19 | @SuppressWarnings("rawtypes") private final AbstractServer rxNettyServer; 20 | 21 | RxNettyServerBackedServer(AbstractServer rxNettyServer, BootstrapModule... bootstrapModules) { 22 | super(RxNettyServerBackedServer.class, bootstrapModules); 23 | this.rxNettyServer = rxNettyServer; 24 | } 25 | 26 | @Override 27 | protected void _start() { 28 | rxNettyServer.start(); 29 | } 30 | 31 | @Override 32 | public void shutdown() { 33 | super.shutdown(); 34 | try { 35 | rxNettyServer.shutdown(); 36 | } catch (InterruptedException e) { 37 | logger.error("Interrupted while shutdown.", e); 38 | Thread.interrupted(); 39 | throw new RuntimeException(e); 40 | } 41 | } 42 | 43 | @Override 44 | public void waitTillShutdown() { 45 | try { 46 | rxNettyServer.waitTillShutdown(); 47 | } catch (InterruptedException e) { 48 | logger.error("Interrupted while waiting for shutdown.", e); 49 | Thread.interrupted(); 50 | throw new RuntimeException(e); 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /karyon2-governator/src/main/java/netflix/karyon/health/SyncHealthCheckInvocationStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Netflix, Inc. 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 netflix.karyon.health; 18 | 19 | import javax.inject.Inject; 20 | import java.util.concurrent.TimeoutException; 21 | 22 | /** 23 | * An implementation of {@link netflix.karyon.health.HealthCheckInvocationStrategy} that synchronously calls the underlying 24 | * {@link netflix.karyon.health.HealthCheckHandler}. 25 | * 26 | * @author Nitesh Kant 27 | */ 28 | @SuppressWarnings("unused") 29 | public class SyncHealthCheckInvocationStrategy implements HealthCheckInvocationStrategy { 30 | 31 | private final HealthCheckHandler handler; 32 | 33 | @Inject 34 | public SyncHealthCheckInvocationStrategy(HealthCheckHandler handler) { 35 | this.handler = handler; 36 | } 37 | 38 | @Override 39 | public int invokeCheck() throws TimeoutException { 40 | return handler.getStatus(); 41 | } 42 | 43 | @Override 44 | public HealthCheckHandler getHandler() { 45 | return handler; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /karyon2-governator/src/main/java/netflix/karyon/transport/AbstractServerModule.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport; 2 | 3 | import com.google.inject.AbstractModule; 4 | import com.google.inject.Key; 5 | import com.google.inject.binder.LinkedBindingBuilder; 6 | import com.google.inject.name.Named; 7 | import com.google.inject.name.Names; 8 | import io.reactivex.netty.pipeline.PipelineConfigurator; 9 | import netflix.karyon.transport.AbstractServerModule.ServerConfigBuilder; 10 | 11 | /** 12 | * @author Tomasz Bak 13 | */ 14 | @SuppressWarnings("rawtypes") 15 | public abstract class AbstractServerModule extends AbstractModule { 16 | 17 | protected final Named nameAnnotation; 18 | protected final Class iType; 19 | protected final Class oType; 20 | 21 | protected final Key pipelineConfiguratorKey; 22 | 23 | protected final Key serverConfigKey; 24 | protected final B serverConfigBuilder; 25 | 26 | protected AbstractServerModule(String moduleName, Class iType, Class oType) { 27 | nameAnnotation = Names.named(moduleName); 28 | this.iType = iType; 29 | this.oType = oType; 30 | 31 | pipelineConfiguratorKey = Key.get(PipelineConfigurator.class, nameAnnotation); 32 | serverConfigKey = Key.get(ServerConfig.class, nameAnnotation); 33 | 34 | serverConfigBuilder = newServerConfigBuilder(); 35 | } 36 | 37 | protected abstract void configureServer(); 38 | 39 | protected abstract B newServerConfigBuilder(); 40 | 41 | protected LinkedBindingBuilder bindPipelineConfigurator() { 42 | return bind(pipelineConfiguratorKey); 43 | } 44 | 45 | protected B server() { 46 | return serverConfigBuilder; 47 | } 48 | 49 | public static class ServerConfig { 50 | private final int port; 51 | 52 | public ServerConfig(int port) { 53 | this.port = port; 54 | } 55 | 56 | public int getPort() { 57 | return port; 58 | } 59 | } 60 | 61 | @SuppressWarnings("unchecked") 62 | public static class ServerConfigBuilder { 63 | 64 | protected int port = 8080; 65 | 66 | public B port(int port) { 67 | this.port = port; 68 | return (B) this; 69 | } 70 | 71 | public C build() { 72 | return (C) new ServerConfig(port); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /karyon2-governator/src/main/java/netflix/karyon/transport/http/health/HealthCheckEndpoint.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.http.health; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.handler.codec.http.HttpResponseStatus; 5 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 6 | import io.reactivex.netty.protocol.http.server.HttpServerResponse; 7 | import io.reactivex.netty.protocol.http.server.RequestHandler; 8 | import netflix.karyon.health.HealthCheckHandler; 9 | import rx.Observable; 10 | 11 | import javax.inject.Inject; 12 | 13 | /** 14 | * An implementation of {@link RequestHandler} to provide health status over HTTP. 15 | * 16 | * This endpoint does NOT validate whether the passed request URI is actually of healthcheck or not. It assumes 17 | * that it is used by a higher level router that makes appropriate decisions of which handler to call based on the URI. 18 | * 19 | * @author Nitesh Kant 20 | */ 21 | public class HealthCheckEndpoint implements RequestHandler { 22 | 23 | private final HealthCheckHandler healthCheckHandler; 24 | 25 | @Inject 26 | public HealthCheckEndpoint(HealthCheckHandler healthCheckHandler) { 27 | this.healthCheckHandler = healthCheckHandler; 28 | } 29 | 30 | @Override 31 | public Observable handle(HttpServerRequest request, HttpServerResponse response) { 32 | int httpStatus = healthCheckHandler.getStatus(); 33 | response.setStatus(HttpResponseStatus.valueOf(httpStatus)); 34 | return response.close(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /karyon2-governator/src/main/java/netflix/karyon/transport/tcp/KaryonTcpModule.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.transport.tcp; 2 | 3 | import com.google.inject.Key; 4 | import com.google.inject.binder.LinkedBindingBuilder; 5 | import com.google.inject.multibindings.MapBinder; 6 | import io.reactivex.netty.channel.ConnectionHandler; 7 | import io.reactivex.netty.server.RxServer; 8 | import netflix.karyon.transport.AbstractServerModule; 9 | import netflix.karyon.transport.AbstractServerModule.ServerConfigBuilder; 10 | 11 | import static netflix.karyon.utils.TypeUtils.keyFor; 12 | 13 | /** 14 | * @author Tomasz Bak 15 | */ 16 | @SuppressWarnings("rawtypes") 17 | public abstract class KaryonTcpModule extends AbstractServerModule { 18 | 19 | protected final Key> connectionHandlerKey; 20 | protected final Key> serverKey; 21 | 22 | 23 | protected KaryonTcpModule(String moduleName, Class iType, Class oType) { 24 | super(moduleName, iType, oType); 25 | connectionHandlerKey = keyFor(ConnectionHandler.class, iType, oType, nameAnnotation); 26 | serverKey = keyFor(RxServer.class, iType, oType, nameAnnotation); 27 | } 28 | 29 | @Override 30 | protected void configure() { 31 | configureServer(); 32 | bind(serverConfigKey).toInstance(serverConfigBuilder.build()); 33 | MapBinder.newMapBinder(binder(), String.class, RxServer.class).addBinding(nameAnnotation.value()).toProvider( 34 | new TcpRxServerProvider>(nameAnnotation.value(), iType, oType) 35 | ).asEagerSingleton(); 36 | } 37 | 38 | @Override 39 | protected ServerConfigBuilder newServerConfigBuilder() { 40 | return new ServerConfigBuilder(); 41 | } 42 | 43 | public LinkedBindingBuilder> bindConnectionHandler() { 44 | return bind(connectionHandlerKey); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /karyon2-governator/src/main/java/netflix/karyon/utils/TypeUtils.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.utils; 2 | 3 | import com.google.inject.Key; 4 | import com.google.inject.TypeLiteral; 5 | import com.google.inject.util.Types; 6 | 7 | import java.lang.annotation.Annotation; 8 | 9 | /** 10 | * Set of utility methods. 11 | * 12 | * @author Tomasz Bak 13 | */ 14 | public final class TypeUtils { 15 | private TypeUtils() { 16 | } 17 | 18 | @SuppressWarnings("unchecked") 19 | public static Key keyFor(Class type, Class typeArg1, Class typeArg2, Annotation annotation) { 20 | TypeLiteral typeLiteral = (TypeLiteral) TypeLiteral.get(Types.newParameterizedType(type, typeArg1, typeArg2)); 21 | return Key.get(typeLiteral, annotation); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /karyon2-jersey-blocking/README.md: -------------------------------------------------------------------------------- 1 | karyon-jersey-blocking 2 | ====== 3 | 4 | A karyon extension providing jersey support for karyon. 5 | 6 | See the [Hello Netflix OSS example](../karyon-examples/src/main/java/com/netflix/karyon/examples/hellonoss/server/jersey) for a sample. 7 | -------------------------------------------------------------------------------- /karyon2-jersey-blocking/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Netflix, Inc. 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 | apply plugin: 'osgi' 18 | 19 | dependencies { 20 | compile project(':karyon2-governator') 21 | compile 'com.google.guava:guava:14.0.1' 22 | compile 'com.netflix.archaius:archaius-core:0.6.3' 23 | compile "com.sun.jersey:jersey-core:${jersey_version}" 24 | compile "com.sun.jersey.contribs:jersey-guice:${jersey_version}" 25 | compile "com.sun.jersey:jersey-servlet:${jersey_version}" 26 | compile "com.sun.jersey:jersey-server:${jersey_version}" 27 | } 28 | 29 | jar { 30 | manifest { 31 | name = 'karyon2-jersey-blocking' 32 | instruction 'Bundle-Vendor', 'Netflix' 33 | instruction 'Bundle-DocURL', 'https://github.com/Netflix/karyon' 34 | instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /karyon2-jersey-blocking/src/main/java/netflix/karyon/jersey/blocking/KaryonJerseyModule.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.jersey.blocking; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import netflix.karyon.transport.http.KaryonHttpModule; 5 | 6 | /** 7 | * @author Nitesh Kant 8 | */ 9 | public abstract class KaryonJerseyModule extends KaryonHttpModule { 10 | 11 | public KaryonJerseyModule() { 12 | super("karyonJerseyModule", ByteBuf.class, ByteBuf.class); 13 | } 14 | 15 | protected KaryonJerseyModule(String moduleName) { 16 | super(moduleName, ByteBuf.class, ByteBuf.class); 17 | } 18 | 19 | @Override 20 | protected void configure() { 21 | bindRouter().to(JerseyBasedRouter.class); 22 | super.configure(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /karyon2-jersey-blocking/src/main/java/netflix/karyon/jersey/blocking/NettyContainer.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.jersey.blocking; 2 | 3 | import com.sun.jersey.spi.container.WebApplication; 4 | 5 | /** 6 | * @author Nitesh Kant 7 | */ 8 | public class NettyContainer { 9 | 10 | private final WebApplication application; 11 | private final NettyToJerseyBridge nettyToJerseyBridge; 12 | 13 | public NettyContainer(WebApplication application) { 14 | this.application = application; 15 | nettyToJerseyBridge = new NettyToJerseyBridge(application); 16 | } 17 | 18 | NettyToJerseyBridge getNettyToJerseyBridge() { 19 | return nettyToJerseyBridge; 20 | } 21 | 22 | WebApplication getApplication() { 23 | return application; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /karyon2-jersey-blocking/src/main/java/netflix/karyon/jersey/blocking/NettyContainerProvider.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.jersey.blocking; 2 | 3 | import com.google.common.base.Preconditions; 4 | import com.sun.jersey.api.container.ContainerException; 5 | import com.sun.jersey.api.core.ResourceConfig; 6 | import com.sun.jersey.spi.container.ContainerProvider; 7 | import com.sun.jersey.spi.container.WebApplication; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | /** 12 | * @author Nitesh Kant 13 | */ 14 | public class NettyContainerProvider implements ContainerProvider { 15 | 16 | private static final Logger logger = LoggerFactory.getLogger(NettyContainerProvider.class); 17 | 18 | @Override 19 | public NettyContainer createContainer(Class type, ResourceConfig resourceConfig, 20 | WebApplication application) throws ContainerException { 21 | Preconditions.checkNotNull(type); 22 | Preconditions.checkNotNull(application); 23 | if (!type.equals(NettyContainer.class)) { 24 | logger.error( 25 | "Netty container provider can only create container of type {}. Invoked to create container of type {}", 26 | NettyContainer.class.getName(), type.getName()); 27 | } 28 | return new NettyContainer(application); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /karyon2-jersey-blocking/src/main/java/netflix/karyon/jersey/blocking/ServiceIteratorProviderImpl.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.jersey.blocking; 2 | 3 | import com.google.common.collect.Iterators; 4 | import com.sun.jersey.spi.container.ContainerProvider; 5 | import com.sun.jersey.spi.service.ServiceFinder; 6 | 7 | import java.util.Iterator; 8 | 9 | /** 10 | * @author Nitesh Kant 11 | */ 12 | class ServiceIteratorProviderImpl extends ServiceFinder.ServiceIteratorProvider { 13 | 14 | static { 15 | /** 16 | * This iterator provider override makes it possible to not mandate the presence of a jar with a META-INF/ based 17 | * Service provider discovery which is the default for jersey. 18 | */ 19 | ServiceFinder.setIteratorProvider(new ServiceIteratorProviderImpl()); 20 | } 21 | 22 | @SuppressWarnings("rawtypes") 23 | private static final Iterator nettyContainerProviderIter = 24 | Iterators.singletonIterator(new NettyContainerProvider()); 25 | 26 | private final ServiceFinder.DefaultServiceIteratorProvider defaultProvider; 27 | 28 | ServiceIteratorProviderImpl() { 29 | defaultProvider = new ServiceFinder.DefaultServiceIteratorProvider(); 30 | } 31 | 32 | public static void registerWithJersey() { 33 | // Static block does the register. 34 | } 35 | 36 | @Override 37 | @SuppressWarnings("unchecked") 38 | public Iterator createIterator(Class service, String serviceName, ClassLoader loader, 39 | boolean ignoreOnClassNotFound) { 40 | Iterator defaultIterator = defaultProvider.createIterator(service, serviceName, loader, ignoreOnClassNotFound); 41 | if (service.isAssignableFrom(NettyContainerProvider.class)) { 42 | return (Iterator) Iterators.concat(defaultIterator, nettyContainerProviderIter); 43 | } 44 | return defaultIterator; 45 | } 46 | 47 | @Override 48 | @SuppressWarnings("unchecked") 49 | public Iterator> createClassIterator(Class service, String serviceName, ClassLoader loader, 50 | boolean ignoreOnClassNotFound) { 51 | return defaultProvider.createClassIterator(service, serviceName, loader, ignoreOnClassNotFound); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /karyon2-jersey-blocking/src/main/resources/META-INF/services/com.sun.jersey.spi.container.ContainerProvider: -------------------------------------------------------------------------------- 1 | netflix.karyon.jersey.blocking.NettyContainerProvider 2 | 3 | -------------------------------------------------------------------------------- /karyon2-jersey-blocking/src/test/java/netflix/karyon/jersey/blocking/JerseyBlockingModule.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.jersey.blocking; 2 | 3 | import static com.netflix.config.ConfigurationManager.getConfigInstance; 4 | import io.netty.buffer.ByteBuf; 5 | import io.reactivex.netty.protocol.http.server.HttpServerRequest; 6 | import io.reactivex.netty.protocol.http.server.HttpServerResponse; 7 | import netflix.karyon.KaryonBootstrap; 8 | import rx.Observable; 9 | import netflix.karyon.transport.interceptor.DuplexInterceptor; 10 | 11 | import com.google.inject.AbstractModule; 12 | import com.google.inject.Singleton; 13 | import com.netflix.governator.annotations.Modules; 14 | 15 | @KaryonBootstrap( name = "jersey-blocking" ) 16 | @Singleton 17 | @Modules(include = { 18 | JerseyBlockingModule.TestModule.class, 19 | JerseyBlockingModule.KaryonRxRouterModuleImpl.class, 20 | }) 21 | public interface JerseyBlockingModule { 22 | class TestModule extends AbstractModule { 23 | 24 | @Override 25 | protected void configure() { 26 | getConfigInstance().addProperty("com.sun.jersey.config.property.packages", "netflix.karyon.jersey.blocking"); 27 | } 28 | } 29 | 30 | class KaryonRxRouterModuleImpl extends KaryonJerseyModule { 31 | @Override 32 | protected void configureServer() { 33 | server().port( 7001 ).threadPoolSize( 200 ); 34 | } 35 | } 36 | 37 | public class AccessInterceptor implements DuplexInterceptor, HttpServerResponse> { 38 | @Override 39 | public Observable in(HttpServerRequest request, HttpServerResponse response) { 40 | return Observable.empty(); 41 | } 42 | 43 | @Override 44 | public Observable out(HttpServerResponse response) { 45 | return Observable.empty(); 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /karyon2-jersey-blocking/src/test/java/netflix/karyon/jersey/blocking/JsonReadingResource.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.jersey.blocking; 2 | 3 | import javax.ws.rs.Consumes; 4 | import javax.ws.rs.POST; 5 | import javax.ws.rs.Path; 6 | import javax.ws.rs.Produces; 7 | import javax.ws.rs.core.MediaType; 8 | import javax.ws.rs.core.Response; 9 | 10 | import org.codehaus.jackson.JsonNode; 11 | import org.codehaus.jackson.map.ObjectMapper; 12 | 13 | @Path("/test") 14 | public class JsonReadingResource { 15 | private final ObjectMapper mapper = new ObjectMapper(); 16 | 17 | @SuppressWarnings("unused") 18 | @POST 19 | @Produces(MediaType.APPLICATION_JSON) 20 | @Consumes(MediaType.APPLICATION_JSON) 21 | public Response processJson( String payload ) { 22 | 23 | try { 24 | 25 | System.out.println( "processing payload size: '" + payload.length() + "'" ); 26 | 27 | JsonNode tree = mapper.readTree( payload ); 28 | 29 | return Response.ok().build(); 30 | } 31 | catch( Exception e ) { 32 | System.err.println( "ERROR:" + e.getMessage() ); 33 | 34 | return Response.serverError().build(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /karyon2-servo/README.md: -------------------------------------------------------------------------------- 1 | karyon-servo 2 | ====== 3 | 4 | This module provides integration with [Servo](https://github.com/Netflix/servo) 5 | 6 | #### KaryonServoModule 7 | 8 | Install this guice module in your application to enable servo. 9 | 10 | See the [karyon examples](../karyon-examples) for a sample. -------------------------------------------------------------------------------- /karyon2-servo/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Netflix, Inc. 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 | apply plugin: 'osgi' 17 | 18 | dependencies { 19 | compile project(':karyon2-governator') 20 | compile "io.reactivex:rxnetty-servo:${rxnetty_version}" 21 | } 22 | 23 | jar { 24 | manifest { 25 | name = 'karyon2-servo' 26 | instruction 'Bundle-Vendor', 'Netflix' 27 | instruction 'Bundle-DocURL', 'https://github.com/Netflix/karyon' 28 | instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /karyon2-servo/src/main/java/netflix/karyon/servo/KaryonServoModule.java: -------------------------------------------------------------------------------- 1 | package netflix.karyon.servo; 2 | 3 | import com.google.inject.AbstractModule; 4 | import com.netflix.governator.guice.BootstrapModule; 5 | import io.reactivex.netty.RxNetty; 6 | import io.reactivex.netty.servo.ServoEventsListenerFactory; 7 | import netflix.karyon.Karyon; 8 | 9 | /** 10 | * Register global RxNetty's Metric Listeners Factory to use Servo. 11 | * 12 | * @author Nitesh Kant 13 | */ 14 | public class KaryonServoModule extends AbstractModule { 15 | 16 | @Override 17 | protected void configure() { 18 | RxNetty.useMetricListenersFactory(new ServoEventsListenerFactory()); 19 | } 20 | 21 | public static BootstrapModule asBootstrapModule() { 22 | return Karyon.toBootstrapModule(KaryonServoModule.class); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /print_junit_reports.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | echo "Current directory is $(pwd)" 3 | echo "\n=== JUNIT REPORTS ===\n" 4 | for F in /home/travis/build/Netflix/karyon/karyon2-jersey-blocking/build/reports/tests/*.html 5 | do 6 | echo $F 7 | cat $F 8 | echo 9 | done 10 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Netflix, Inc. 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 | rootProject.name='karyon' 18 | include 'karyon2-core', \ 19 | 'karyon2-governator', \ 20 | 'karyon2-eureka', \ 21 | 'karyon2-archaius', \ 22 | 'karyon2-servo', \ 23 | 'karyon2-admin', \ 24 | 'karyon2-admin-web', \ 25 | 'karyon2-admin-plugins:karyon2-admin-eureka-plugin', \ 26 | 'karyon2-admin-plugins:karyon2-admin-healthcheck-plugin', \ 27 | 'karyon2-admin-plugins:karyon-admin-healthcheck-plugin', \ 28 | 'karyon2-jersey-blocking', \ 29 | 'karyon2-examples' 30 | --------------------------------------------------------------------------------