diff --git a/CHANGELOG.md b/CHANGELOG.md index a76c4695..020cda84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,37 +1,51 @@ # Changelog + All notable changes to this project will be documented in this file. ## [1.1.0] + - Added bill of materials for ranger, for clients who intend to use ranger. - Updated version to release version 1.1.0 ## [1.1-RC5] + Server to server replication implemented ## [1.1-RC4] + - Remove WaitStrategy in the Retryer used to check if ServiceRegistry is refreshed during ServiceRegistryUpdater startup ## [1.1-RC3] -- Execute updateRegistry operation in async inside ServiceFinderHub so that main thread reaches till waitTillHubIsReady instead of waiting for lock release and hubStartTimeoutMs is honoured as expected + +- Execute updateRegistry operation in async inside ServiceFinderHub so that main thread reaches till waitTillHubIsReady + instead of waiting for lock release and hubStartTimeoutMs is honoured as expected - Setting the read timeout and write timeout in OkHttpClient same as operation timeout given in HttpClientConfig - Added waitStrategy in waitTillServiceIsReady in ServiceFinderHub to save come cpu cycles in Retryer ## [1.1-RC2] + - Add feature to exclude services from service data source - Create one single `RangerHealthCheck` for all curatorFrameworks when giving multiple zookeeper connection strings -- Update `lastUpdatedTimeStamp` for service nodes in service registry for zk / http communication failures from any kind of node data source - zk/http/drove -- Pertaining to PR : https://github.com/appform-io/ranger/pull/22/, building of a ServiceFinderHub and a ServiceFinder are bounded. +- Update `lastUpdatedTimeStamp` for service nodes in service registry for zk / http communication failures from any kind + of node data source - zk/http/drove +- Pertaining to PR : https://github.com/appform-io/ranger/pull/22/, building of a ServiceFinderHub and a ServiceFinder + are bounded. ## [1.0-RC18] + - Version bump to release lexicographically higher version than 1.0-dw3-RC17 ## [1.0-RC17] + - Domain specific collision checker in id generator ## [1.0-RC16] -- Fixed hierarchical environment aware shard selector : If a service is deployed with environment : env.x.y.z then it should be able to discover other services present in environment - [env , env.x , env.x.y, env.x.y.z ] + +- Fixed hierarchical environment aware shard selector : If a service is deployed with environment : env.x.y.z then it + should be able to discover other services present in environment - [env , env.x , env.x.y, env.x.y.z ] ## [1.0-RC15] + - Moved discovery bundle from https://github.com/appform-io/dropwizard-service-discovery. - Updated to dropwizard version 2.1.10 : BOM update. - Upgraded to java version 17 with release in 11 @@ -41,13 +55,19 @@ Server to server replication implemented - Done sonar fixes after the java version upgrade ## [1.0-RC14] -- When the Collection of Services is empty the monitor should gracefully return [PR](https://github.com/appform-io/ranger/pull/27) + +- When the Collection of Services is empty the monitor should gracefully + return [PR](https://github.com/appform-io/ranger/pull/27) ## [1.0-RC13] + - Handling NodeDataSource refresh failures gracefully ## [1.0-RC12] + - Dynamic service registration ## [1.0-RC11] -- Introduced a portScheme on ServiceNode, so multiple types of protocols could be supported. Was assumed to be HTTP instead. \ No newline at end of file + +- Introduced a portScheme on ServiceNode, so multiple types of protocols could be supported. Was assumed to be HTTP + instead. \ No newline at end of file diff --git a/README.md b/README.md index a020d9a7..7556808e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Ranger Ranger is a high level service discovery framework built on Zookeeper. The framework brings the following to the table: + - Support of sharding of the service provider nodes - Support for monitoring of service provider nodes - Provides type-safe generic interface for integration with support for custom serializers and deserializers @@ -9,15 +10,21 @@ Ranger is a high level service discovery framework built on Zookeeper. The frame ## Why? -As request rates increase, load balancers, even the very expensive ones, become bottlenecks. We needed to move beyond and be able to talk to services without having to channel all traffic through a load-balancer. There is obviously curator discovery; but as much as we love curator, we needed more features on top of it. As such we built this library to handle app level sharding and healtchecks. Btw, it still uses curator for low level ZK interactions. +As request rates increase, load balancers, even the very expensive ones, become bottlenecks. We needed to move beyond +and be able to talk to services without having to channel all traffic through a load-balancer. There is obviously +curator discovery; but as much as we love curator, we needed more features on top of it. As such we built this library +to handle app level sharding and healtchecks. Btw, it still uses curator for low level ZK interactions. ## Usage + Ranger provides two types of discovery out of the box: + - Simple unsharded service discovery with service provider node healthchecks - Sharded service discovery with service provider node healthchecks We'll take these up, one by one. ### Bill of materials + You could use the ranger-bom using the following in your dependency management. ``` @@ -31,6 +38,7 @@ You could use the ranger-bom using the following in your dependency management. ``` ###Build instructions + - Clone the source: git clone github.com/appform-io/ranger @@ -40,7 +48,9 @@ You could use the ranger-bom using the following in your dependency management. mvn install ### Maven Dependency + Use the following maven dependency: + ``` io.appform.ranger @@ -49,30 +59,44 @@ Use the following maven dependency: ``` ## How it works + There are service providers and service clients. We will look at the interactions from both sides. ### Service Provider -Service providers register to the Ranger system by building and starting a ServiceProvider instance. During registering itself the provider must provide the following: -- _ShardInfo type_ - This is a type parameter to the ServiceProvider class. This can be any class that can be serialized and deserialized by the Serializer and Deserializer provided (see below). The hashCode() for this class is used to match and find the matching shard for a query. So be sure to implement this properly. A special version of this class _UnshardedClusterInfo_ is provided for unsharded discovery. + +Service providers register to the Ranger system by building and starting a ServiceProvider instance. During registering +itself the provider must provide the following: + +- _ShardInfo type_ - This is a type parameter to the ServiceProvider class. This can be any class that can be serialized + and deserialized by the Serializer and Deserializer provided (see below). The hashCode() for this class is used to + match and find the matching shard for a query. So be sure to implement this properly. A special version of this class + _UnshardedClusterInfo_ is provided for unsharded discovery. - _Zookeeper details_ - Can be any one of the following: - - _Connection String_ - Zookeeper connections string to connect to ZK cluster. - - CuratorFramework object - A prebuilt CuratorFramework object. + - _Connection String_ - Zookeeper connections string to connect to ZK cluster. + - CuratorFramework object - A prebuilt CuratorFramework object. - _Namespace_ - A namespace for the service. For example the team name this service belongs to. - _Service Name_ - Name of the service to be used by client for discovery. - _Host_ - Hostname for the service. - _Port_ - Port on which this service is running. - _Serializer_ - A serializer implementation that will be used to serialize and store the shard information on ZooKeeper - _Healthcheck_ - The healthcheck function is called every second and the status is updated on Zookeeper. -- _Monitors_ : The health state of your service is also decided by a list of monitors. Register a list of monitors. These monitors will be monitored at regular intervals and an aggregated status is updated on Zookeeper - - _Isolated Monitors_ - Each of these monitors will be running continuously on separate isolated threads. Each thread holds an independent state of the isolated monitor. The state of all Monitors will be aggregated an updated on Zookeeper at regular intervals. +- _Monitors_ : The health state of your service is also decided by a list of monitors. Register a list of monitors. + These monitors will be monitored at regular intervals and an aggregated status is updated on Zookeeper + - _Isolated Monitors_ - Each of these monitors will be running continuously on separate isolated threads. Each + thread holds an independent state of the isolated monitor. The state of all Monitors will be aggregated an updated + on Zookeeper at regular intervals. A node will be marked unhealthy iff: + - The service is stopped. - If any isolated monitor's state is _HealthcheckStatus.unhealthy_ -- If _Healthcheck.check()_ has not been updated for over a minute. This signifies that the process is probably zombified. +- If _Healthcheck.check()_ has not been updated for over a minute. This signifies that the process is probably + zombified. #### Registering a simple unsharded service + This is very simple. Use the following boilerplate code. + ``` ServiceProvider serviceProvider = ServiceProviderBuilders.unshardedServiceProviderBuilder() @@ -102,11 +126,15 @@ ServiceProvider serviceProvider .buildServiceDiscovery(); serviceProvider.start(); //Start the instance ``` + Stop the provider once you are done. (Generally this is when process ends) + ``` serviceProvider.stop() ``` + #### Registering a sharded service + Let's assume that the following is your shard info class: ``` @@ -186,13 +214,19 @@ serviceProvider.stop() ``` ### Monitors -In a distributed architecture, taking care of thousands of servers is a difficult task. Failures are bound to happen, and individual services could always face issues. It becomes very important that we automate handling such failures. Ranger allows you to do that, for your _ServiceProviders_. -As mentioned earlier, the health state of any _ServiceProvider_ is determined by a set of health monitors which are continuously running in the Service Provider. +In a distributed architecture, taking care of thousands of servers is a difficult task. Failures are bound to happen, +and individual services could always face issues. It becomes very important that we automate handling such failures. +Ranger allows you to do that, for your _ServiceProviders_. + +As mentioned earlier, the health state of any _ServiceProvider_ is determined by a set of health monitors which are +continuously running in the Service Provider. All monitors (and at least 1) need to be registered while building the _ServiceProvider_. -You may register any kind of _Monitor_, which could be monitoring any serivce/system level metric. For example, you could have monitors: -- that monitor the service's heap, to ensure that it doesn't go beyond a threashold +You may register any kind of _Monitor_, which could be monitoring any service/system level metric. For example, you +could have monitors: + +- that monitor the service's heap, to ensure that it doesn't go beyond a threshold - that check for any breach in max jetty threads - that monitors the systems disk space - that does a continuous ping test @@ -200,24 +234,34 @@ You may register any kind of _Monitor_, which could be monitoring any serivce/sy If any of the above are breached, the service will automatically be marked as unhealthy. -- _Isolated Monitors_ - Any extention of _IsolatedHealthMonitor_ may be used to register an isolated monitor. Each of these monitors will be running continuously on separate isolated threads. Each thread holds an independent state of the isolated monitor. The state of all Monitors will be aggregated an updated on Zookeeper at regular intervals. - - _PingCheckMonitor_ - This monitor can be used to ping a url at regular intervals. It could be a self localhost ping too. You can also add minimum failure counts, to ensure that there are no fluctuations - ``` - .withIsolatedHealthMonitor(new PingCheckMonitor(new TimeEntity(2, TimeUnit.SECONDS), httpRequest, 5000, 5, 3, "google.com", 80)); // put in the url here - ``` - - _RotationStatusMonitor_ - This monitor can be used check the rotation status of your server, which decides if the host can serve traffic at the moment or not. Removing the file, will automatically prevent this host from getting discovered. - ``` - ..withIsolatedHealthMonitor(new RotationStatusMonitor(TimeEntity.everySecond(), "/var/rotation.html")); // path of file to be checked - ``` -At regular intervals, all of the above monitors will be aggregated into a single Health state of the service, which +- _Isolated Monitors_ - Any extension of _IsolatedHealthMonitor_ may be used to register an isolated monitor. Each of + these monitors will be running continuously on separate isolated threads. Each thread holds an independent state of + the isolated monitor. The state of all Monitors will be aggregated an updated on Zookeeper at regular intervals. + - _PingCheckMonitor_ - This monitor can be used to ping a url at regular intervals. It could be a self localhost + ping too. You can also add minimum failure counts, to ensure that there are no fluctuations + ``` + .withIsolatedHealthMonitor(new PingCheckMonitor(new TimeEntity(2, TimeUnit.SECONDS), httpRequest, 5000, 5, 3, "google.com", 80)); // put in the url here + ``` + - _RotationStatusMonitor_ - This monitor can be used check the rotation status of your server, which decides if the + host can serve traffic at the moment or not. Removing the file, will automatically prevent this host from getting + discovered. + ``` + ..withIsolatedHealthMonitor(new RotationStatusMonitor(TimeEntity.everySecond(), "/var/rotation.html")); // path of file to be checked + ``` +At regular intervals, all of the above monitors will be aggregated into a single Health state of the service, which ### Service discovery + For service discovery, a _ServiceFinder_ object needs to be built and used. -- _ShardInfo type_ - This is a type parameter to the ServiceFinder class. This can be any class that can be serialized and deserialized by the Serializer and Deserializer provided (see below). The hashCode() for this class is used to match and find the matching shard for a query. So be sure to implement this properly. A special version of this class _UnshardedClusterInfo_ is provided for unsharded discovery. + +- _ShardInfo type_ - This is a type parameter to the ServiceFinder class. This can be any class that can be serialized + and deserialized by the Serializer and Deserializer provided (see below). The hashCode() for this class is used to + match and find the matching shard for a query. So be sure to implement this properly. A special version of this class + _UnshardedClusterInfo_ is provided for unsharded discovery. - _Zookeeper details_ - Can be any one of the following: - - _Connection String_ - Zookeeper connections string to connect to ZK cluster. - - CuratorFramework object - A prebuilt CuratorFramework object. + - _Connection String_ - Zookeeper connections string to connect to ZK cluster. + - CuratorFramework object - A prebuilt CuratorFramework object. - _Namespace_ - A namespace for the service. For example the team name this service belongs to. - _Service Name_ - Name of the service to be used by client for discovery. - _Host_ - Hostname for the service. @@ -227,6 +271,7 @@ For service discovery, a _ServiceFinder_ object needs to be built and used. Depending on whether you are looking to access a sharded service or an unsharded service, the code will differ a little. #### Finding an instance of an unsharded Service Provider + First build and start the finder. ``` @@ -260,11 +305,13 @@ ServiceNode node = serviceFinder.get(null); //null because you don't need to pas ``` Stop the finder once you are done. (Generally this is when process ends) + ``` serviceFinder.stop() ``` #### Finding an instance of a sharded Service Provider + This is similar to the above but for the type parameter you are using everywhere. ``` @@ -304,13 +351,17 @@ serviceFinder.stop() ``` ### Service Finder Hub -A service finder hub contains a collection of the above-mentioned service finders. A hub also makes creation of serviceFinders easy, for a service -that is dependent on multiple other services, don't have to now create multiple serviceFinders, instead create a hub, with the set of services and + +A service finder hub contains a collection of the above-mentioned service finders. A hub also makes creation of +serviceFinders easy, for a service +that is dependent on multiple other services, don't have to now create multiple serviceFinders, instead create a hub, +with the set of services and the service finders get created automatically. Could either be an http hub or a ZK hub. (Can add any hub in the future) -Hub clients for both ZK and http have been provided to initialize the same. A sample http hub client would look like the following. +Hub clients for both ZK and http have been provided to initialize the same. A sample http hub client would look like the +following. ``` RangerHubClient hubClient = UnshardedRangerZKHubClient.builder() @@ -346,11 +397,13 @@ Stop the hub client once you are done. (Generally this is when process ends) ``` hubClient.stop() ``` + ### Service Discovery Bundle -If you are using a dropwizard project, you could use the service discovery bundle directly instead of having to create your own service provider clients and bind them. +If you are using a dropwizard project, you could use the service discovery bundle directly instead of having to create +your own service provider clients and bind them. -#### Dependeny for the bundle +#### Dependency for the bundle ``` @@ -362,7 +415,6 @@ If you are using a dropwizard project, you could use the service discovery bundl #### How to initialize the bundle - You need to add an instance of type _ServiceDiscoveryConfiguration_ to your Dropwizard configuration file as follows: ``` @@ -426,6 +478,7 @@ public class App extends Application { } } ``` + That's it .. your service will register to zookeeper when it starts up. #### Sample Configuration @@ -448,9 +501,10 @@ Use GET /instances to see all instances that have been registered to your servic ### Service Discovery Bundle -If you are using a dropwizard project, you could use the service discovery bundle directly instead of having to create your own service provider clients and bind them. +If you are using a dropwizard project, you could use the service discovery bundle directly instead of having to create +your own service provider clients and bind them. -#### Dependeny for the bundle +#### Dependency for the bundle ``` @@ -462,7 +516,6 @@ If you are using a dropwizard project, you could use the service discovery bundl #### How to initialize the bundle - You need to add an instance of type _ServiceDiscoveryConfiguration_ to your Dropwizard configuration file as follows: ``` @@ -526,6 +579,7 @@ public class App extends Application { } } ``` + That's it .. your service will register to zookeeper when it starts up. #### Sample Configuration @@ -548,11 +602,15 @@ Use GET /instances to see all instances that have been registered to your servic ### Ranger Server -The earlier ranger's service finder construct operated on zookeeper as the datasource, the server has been introduced to support http data sources and to be -able to provide a serviceFinder interface atop multiple data sources. Eg: you could have one server running atop zk, one atop http - and can deploy another http -server fronting them both. Particularly useful when you have to aggregate amongst multiple service registries. A server bundle is provided to start a quick server (atop dropwizard) +The earlier ranger's service finder construct operated on zookeeper as the datasource, the server has been introduced to +support http data sources and to be +able to provide a serviceFinder interface atop multiple data sources. Eg: you could have one server running atop zk, one +atop http - and can deploy another http +server fronting them both. Particularly useful when you have to aggregate amongst multiple service registries. A server +bundle is provided to start a quick server (atop dropwizard) To use the http server bundle along with boostrap use. + ``` bootstrap.add(new RangerServerBundle { @Override @@ -587,7 +645,8 @@ To use the http server bundle along with boostrap use. }); ``` -It comes with a rangerResource that provides you with interfaces for getting the list of services across hubs and the nodes per service across hubs. +It comes with a rangerResource that provides you with interfaces for getting the list of services across hubs and the +nodes per service across hubs. Tech @@ -598,11 +657,13 @@ Ranger uses Apache Curator: * [Curator](http://curator.apache.org/) - Abstraction library for ZooKeeper operations # Contribution, Bugs and Feedback + For bugs, questions and discussions please use the [Github Issues](https://github.com/appform-io/ranger/issues). If you would like to contribute code you can do so through GitHub by forking the repository and sending a pull request. -When submitting code, please make every effort to follow existing conventions and style in order to keep the code as readable as possible. +When submitting code, please make every effort to follow existing conventions and style in order to keep the code as +readable as possible. Original Repo ------------- This repo is a fork of: [Ranger](https://github.com/flipkart-incubator/ranger) diff --git a/pom.xml b/pom.xml index f579478e..8a0272dc 100644 --- a/pom.xml +++ b/pom.xml @@ -41,10 +41,15 @@ ranger-drove-client ranger-server-common ranger-server-bundle + ranger-server-bundle-dw5 ranger-http-model + ranger-discovery-common ranger-discovery-bundle + ranger-discovery-bundle-dw5 ranger-hub-server-bundle + ranger-hub-server-bundle-dw5 ranger-server + ranger-server-dw5 ranger-bom @@ -74,7 +79,7 @@ The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt + https://www.apache.org/licenses/LICENSE-2.0.txt repo A business-friendly OSS license @@ -99,34 +104,56 @@ + UTF-8 - 33.3.0-jre - 5.5.0 - 1.7.32 - - 3.8.0 17 17 - 1.18.30 - 3.0.1u2 - 5.8.2 - 4.1.1 + + 33.5.0-jre + 5.9.0 + 1.7.32 + 1.18.42 + 3.0.1 2.0.0 + 5.1.0 + 1.5.18 + 4.2.0 + 2.20 + 1.1.10.8 + 3.9.4 - 4.9.3 - 3.3.1 + + 5.13.4 + 4.3.0 + 4.0.0-beta.15 4.2.0 + 2.6.0 - 2.1.12 - 1.2.12 - 4.2.0 - + + 3.14.0 + 3.4.2 0.8.13 + 3.2.8 + 1.7.0 + 3.12.0 + 3.3.1 + 3.5.4 + 1.4.0 + + org.xerial.snappy + snappy-java + ${snappy.version} + + + org.apache.zookeeper + zookeeper + ${zookeeper.version} + org.junit junit-bom @@ -135,11 +162,10 @@ import - io.dropwizard - dropwizard-bom - pom - import - ${dropwizard.version} + net.minidev + json-smart + ${json-smart.version} + test @@ -151,6 +177,24 @@ ${lombok.version} provided + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + provided + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version}.0 + provided + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version}.0 + provided + com.google.code.findbugs annotations @@ -166,10 +210,6 @@ slf4j-api ${slf4j.version} - - io.dropwizard - dropwizard-jackson - org.junit.jupiter junit-jupiter-api @@ -207,12 +247,12 @@ maven-surefire-plugin - 3.3.1 + ${maven.surefire.plugin.version} me.fabriciorby maven-surefire-junit5-tree-reporter - 1.3.0 + ${maven.surefire.junit5.tree.reporter.version} @@ -257,7 +297,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.0 + ${maven.source.plugin.version} attach-sources @@ -270,7 +310,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.3 + ${maven.javadoc.plugin.version} all,-missing @@ -286,7 +326,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.7.0 + ${nexus.staging.maven.plugin.version} true ossrh @@ -312,7 +352,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.6 + ${maven.gpg.plugin.version} sign-artifacts @@ -347,5 +387,4 @@ - diff --git a/ranger-bom/pom.xml b/ranger-bom/pom.xml index 32128985..2190c19d 100644 --- a/ranger-bom/pom.xml +++ b/ranger-bom/pom.xml @@ -1,229 +1,229 @@ - 4.0.0 - - io.appform.ranger - ranger - 2.0.0-SNAPSHOT - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + io.appform.ranger + ranger + 2.0.0-SNAPSHOT + + + ranger-bom + pom + Bill of Materials for Ranger - ranger-bom - pom - Bill of Materials for Ranger + + 17 + 17 + UTF-8 + 1.7.3 + - - 17 - 17 - UTF-8 - 1.7.0 - + + + + io.appform.ranger + ranger-client + ${project.version} + + + io.appform.ranger + ranger-core + ${project.version} + + + io.appform.ranger + ranger-discovery-bundle + ${project.version} + + + io.appform.ranger + ranger-drove + ${project.version} + + + io.appform.ranger + ranger-drove-client + ${project.version} + + + io.appform.ranger + ranger-http + ${project.version} + + + io.appform.ranger + ranger-http-client + ${project.version} + + + io.appform.ranger + ranger-http-model + ${project.version} + + + io.appform.ranger + ranger-hub-server-bundle + ${project.version} + + + io.appform.ranger + ranger-server + ${project.version} + + + io.appform.ranger + ranger-server-bundle + ${project.version} + + + io.appform.ranger + ranger-server-common + ${project.version} + + + io.appform.ranger + ranger-zk-client + ${project.version} + + + io.appform.ranger + ranger-zookeeper + ${project.version} + + + - - - io.appform.ranger - ranger-client - ${project.version} - - - io.appform.ranger - ranger-core - ${project.version} - - - io.appform.ranger - ranger-discovery-bundle - ${project.version} - - - io.appform.ranger - ranger-drove - ${project.version} - - - io.appform.ranger - ranger-drove-client - ${project.version} - - - io.appform.ranger - ranger-http - ${project.version} - - - io.appform.ranger - ranger-http-client - ${project.version} - - - io.appform.ranger - ranger-http-model - ${project.version} - - - io.appform.ranger - ranger-hub-server-bundle - ${project.version} - - - io.appform.ranger - ranger-server - ${project.version} - - - io.appform.ranger - ranger-server-bundle - ${project.version} - - - io.appform.ranger - ranger-server-common - ${project.version} - - - io.appform.ranger - ranger-zk-client - ${project.version} - - - io.appform.ranger - ranger-zookeeper - ${project.version} - + + io.appform.ranger + ranger-client + ${project.version} + + + io.appform.ranger + ranger-core + ${project.version} + + + io.appform.ranger + ranger-discovery-bundle + ${project.version} + + + io.appform.ranger + ranger-drove + ${project.version} + + + io.appform.ranger + ranger-drove-client + ${project.version} + + + io.appform.ranger + ranger-http + ${project.version} + + + io.appform.ranger + ranger-http-client + ${project.version} + + + io.appform.ranger + ranger-http-model + ${project.version} + + + io.appform.ranger + ranger-hub-server-bundle + ${project.version} + + + io.appform.ranger + ranger-server + ${project.version} + + + io.appform.ranger + ranger-server-bundle + ${project.version} + + + io.appform.ranger + ranger-server-common + ${project.version} + + + io.appform.ranger + ranger-zk-client + ${project.version} + + + io.appform.ranger + ranger-zookeeper + ${project.version} + - - - - - io.appform.ranger - ranger-client - ${project.version} - - - io.appform.ranger - ranger-core - ${project.version} - - - io.appform.ranger - ranger-discovery-bundle - ${project.version} - - - io.appform.ranger - ranger-drove - ${project.version} - - - io.appform.ranger - ranger-drove-client - ${project.version} - - - io.appform.ranger - ranger-http - ${project.version} - - - io.appform.ranger - ranger-http-client - ${project.version} - - - io.appform.ranger - ranger-http-model - ${project.version} - - - io.appform.ranger - ranger-hub-server-bundle - ${project.version} - - - io.appform.ranger - ranger-server - ${project.version} - - - io.appform.ranger - ranger-server-bundle - ${project.version} - - - io.appform.ranger - ranger-server-common - ${project.version} - - - io.appform.ranger - ranger-zk-client - ${project.version} - - - io.appform.ranger - ranger-zookeeper - ${project.version} - - - - - - org.jacoco - jacoco-maven-plugin - ${jacoco.version} - - - verify - - report-aggregate - - - - **/jacoco.exec - - ${project.reporting.outputDirectory}/jacoco-aggregate - - - - - - org.codehaus.mojo - flatten-maven-plugin - ${flatten.maven.plugin-version} - - true - target - - - - flatten - process-resources - - flatten - - - true - bom - - expand - remove - remove - remove - - - - - flatten.clean - clean - - clean - - - - - - + + + + org.jacoco + jacoco-maven-plugin + ${jacoco.version} + + + verify + + report-aggregate + + + + **/jacoco.exec + + ${project.reporting.outputDirectory}/jacoco-aggregate + + + + + + org.codehaus.mojo + flatten-maven-plugin + ${flatten.maven.plugin-version} + + true + target + + + + flatten + process-resources + + flatten + + + true + bom + + expand + remove + remove + remove + + + + + flatten.clean + clean + + clean + + + + + + diff --git a/ranger-client/pom.xml b/ranger-client/pom.xml index bc416f6a..7ea6bd8c 100644 --- a/ranger-client/pom.xml +++ b/ranger-client/pom.xml @@ -47,7 +47,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.2.0 + ${maven.jar.plugin.version} diff --git a/ranger-client/src/main/java/io/appform/ranger/client/AbstractRangerClient.java b/ranger-client/src/main/java/io/appform/ranger/client/AbstractRangerClient.java index 370e1aad..082eeecc 100644 --- a/ranger-client/src/main/java/io/appform/ranger/client/AbstractRangerClient.java +++ b/ranger-client/src/main/java/io/appform/ranger/client/AbstractRangerClient.java @@ -57,8 +57,8 @@ public Optional> getNode( ShardSelector shardSelector, ServiceNodeSelector nodeSelector) { return getServiceFinder().get(CriteriaUtils.getCriteria(alwaysUseInitialCriteria, initialCriteria, criteria), - shardSelector, - nodeSelector); + shardSelector, + nodeSelector); } @Override @@ -75,9 +75,9 @@ public List> getAllNodes(Predicate criteria) { public List> getAllNodes( Predicate criteria, ShardSelector shardSelector) { return getServiceFinder().getAll(CriteriaUtils.getCriteria(alwaysUseInitialCriteria, - initialCriteria, - criteria), - shardSelector); + initialCriteria, + criteria), + shardSelector); } } diff --git a/ranger-client/src/main/java/io/appform/ranger/client/AbstractRangerHubClient.java b/ranger-client/src/main/java/io/appform/ranger/client/AbstractRangerHubClient.java index 2ec971b0..edcc96c2 100644 --- a/ranger-client/src/main/java/io/appform/ranger/client/AbstractRangerHubClient.java +++ b/ranger-client/src/main/java/io/appform/ranger/client/AbstractRangerHubClient.java @@ -21,20 +21,31 @@ import io.appform.ranger.core.finderhub.ServiceDataSource; import io.appform.ranger.core.finderhub.ServiceFinderFactory; import io.appform.ranger.core.finderhub.ServiceFinderHub; -import io.appform.ranger.core.model.*; +import io.appform.ranger.core.model.Deserializer; +import io.appform.ranger.core.model.HubConstants; +import io.appform.ranger.core.model.Service; +import io.appform.ranger.core.model.ServiceNode; +import io.appform.ranger.core.model.ServiceNodeSelector; +import io.appform.ranger.core.model.ServiceRegistry; +import io.appform.ranger.core.model.ShardSelector; import io.appform.ranger.core.util.FinderUtils; import lombok.Getter; import lombok.experimental.SuperBuilder; import lombok.extern.slf4j.Slf4j; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; @Slf4j @Getter @SuperBuilder -public abstract class AbstractRangerHubClient, D extends Deserializer> implements RangerHubClient { +public abstract class AbstractRangerHubClient, D extends Deserializer> implements RangerHubClient { private final String namespace; private final ObjectMapper mapper; @@ -65,7 +76,7 @@ public void start() { if (this.nodeRefreshTimeMs < HubConstants.MINIMUM_REFRESH_TIME_MS) { log.warn("Node info update interval too low: {} ms. Has been upgraded to {} ms ", - this.nodeRefreshTimeMs, + this.nodeRefreshTimeMs, HubConstants.MINIMUM_REFRESH_TIME_MS); } this.nodeRefreshTimeMs = Math.max(HubConstants.MINIMUM_REFRESH_TIME_MS, this.nodeRefreshTimeMs); @@ -86,7 +97,7 @@ public void start() { this.excludedServices = Objects.requireNonNullElseGet(this.excludedServices, Set::of); - if(null == this.serviceDataSource){ + if (null == this.serviceDataSource) { this.serviceDataSource = getDefaultDataSource(); } @@ -120,7 +131,7 @@ public Optional> getNode(final Service service, final Predicate> getNode( final Service service, final Predicate criteria, - final ShardSelector shardSelector) { + final ShardSelector shardSelector) { return getNode(service, criteria, shardSelector, null); } @@ -128,23 +139,23 @@ public Optional> getNode( public Optional> getNode( final Service service, final Predicate criteria, - final ShardSelector shardSelector, + final ShardSelector shardSelector, final ServiceNodeSelector nodeSelector) { return this.getHub() .finder(service) .flatMap(trServiceFinder - -> trServiceFinder.get(CriteriaUtils.getCriteria(alwaysUseInitialCriteria, - initialCriteria, - criteria), - shardSelector, - nodeSelector)); + -> trServiceFinder.get(CriteriaUtils.getCriteria(alwaysUseInitialCriteria, + initialCriteria, + criteria), + shardSelector, + nodeSelector)); } @Override public List> getAllNodes( final Service service, final Predicate criteria - ) { + ) { return getAllNodes(service, criteria, null); } @@ -165,8 +176,7 @@ public List> getAllNodes( public Collection getRegisteredServices() { try { return FinderUtils.getEligibleServices(this.getHub().getServiceDataSource().services(), excludedServices); - } - catch (Exception e) { + } catch (Exception e) { log.error("Call to the hub failed with exception, {}", e.getMessage()); return Collections.emptySet(); } @@ -177,15 +187,14 @@ public Collection getRegisteredServices() { * Method will return asynchronously after adding service to ServiceDataSource. * To block till rangerHub is ready to discover service wait for future completion * - * @throws UnsupportedOperationException for any datasource which doesnt support - * dynamic addition of services - * @throws IllegalStateException if called before hub is started - * * @return CompletableFuture which waits for hub to be ready for discovering the new service + * @throws UnsupportedOperationException for any datasource which doesnt support + * dynamic addition of services + * @throws IllegalStateException if called before hub is started */ @Override public CompletableFuture addService(Service service) { - if(hub == null) { + if (hub == null) { throw new IllegalStateException("Hub not started yet. Call .start()"); } return hub.buildFinder(service); diff --git a/ranger-client/src/main/java/io/appform/ranger/client/RangerClient.java b/ranger-client/src/main/java/io/appform/ranger/client/RangerClient.java index b35b9427..06397f85 100644 --- a/ranger-client/src/main/java/io/appform/ranger/client/RangerClient.java +++ b/ranger-client/src/main/java/io/appform/ranger/client/RangerClient.java @@ -19,6 +19,7 @@ import io.appform.ranger.core.model.ServiceNodeSelector; import io.appform.ranger.core.model.ServiceRegistry; import io.appform.ranger.core.model.ShardSelector; + import java.util.List; import java.util.Optional; import java.util.function.Predicate; diff --git a/ranger-client/src/main/java/io/appform/ranger/client/RangerHubClient.java b/ranger-client/src/main/java/io/appform/ranger/client/RangerHubClient.java index 76963364..021da5fa 100644 --- a/ranger-client/src/main/java/io/appform/ranger/client/RangerHubClient.java +++ b/ranger-client/src/main/java/io/appform/ranger/client/RangerHubClient.java @@ -20,6 +20,7 @@ import io.appform.ranger.core.model.ServiceNodeSelector; import io.appform.ranger.core.model.ServiceRegistry; import io.appform.ranger.core.model.ShardSelector; + import java.util.Collection; import java.util.List; import java.util.Optional; diff --git a/ranger-client/src/main/java/io/appform/ranger/client/utils/CriteriaUtils.java b/ranger-client/src/main/java/io/appform/ranger/client/utils/CriteriaUtils.java index 4ff09190..166ccb14 100644 --- a/ranger-client/src/main/java/io/appform/ranger/client/utils/CriteriaUtils.java +++ b/ranger-client/src/main/java/io/appform/ranger/client/utils/CriteriaUtils.java @@ -15,9 +15,10 @@ */ package io.appform.ranger.client.utils; -import java.util.function.Predicate; import lombok.experimental.UtilityClass; +import java.util.function.Predicate; + @UtilityClass public class CriteriaUtils { @@ -35,7 +36,7 @@ public static Predicate getCriteria( Predicate initialCriteria, Predicate argCriteria) { return null != initialCriteria && null != argCriteria && useInitialCriteria - ? initialCriteria.and(argCriteria) - : argCriteria; + ? initialCriteria.and(argCriteria) + : argCriteria; } } diff --git a/ranger-client/src/test/java/io/appform/ranger/client/CriteriaUtilsTest.java b/ranger-client/src/test/java/io/appform/ranger/client/CriteriaUtilsTest.java index 46f762ea..5d86c3ce 100644 --- a/ranger-client/src/test/java/io/appform/ranger/client/CriteriaUtilsTest.java +++ b/ranger-client/src/test/java/io/appform/ranger/client/CriteriaUtilsTest.java @@ -25,12 +25,12 @@ class CriteriaUtilsTest { - private Predicate getCriteria(int shardId){ + private Predicate getCriteria(int shardId) { return testNodeData -> testNodeData.getShardId() == shardId; } @Test - void testGetCriteria(){ + void testGetCriteria() { val initialCriteria = getCriteria(1); val argCriteria = getCriteria(2); var mergedCriteria = CriteriaUtils.getCriteria(true, initialCriteria, argCriteria); diff --git a/ranger-client/src/test/java/io/appform/ranger/client/stubs/RangerTestHub.java b/ranger-client/src/test/java/io/appform/ranger/client/stubs/RangerTestHub.java index ac46feb3..849eaf69 100644 --- a/ranger-client/src/test/java/io/appform/ranger/client/stubs/RangerTestHub.java +++ b/ranger-client/src/test/java/io/appform/ranger/client/stubs/RangerTestHub.java @@ -19,7 +19,11 @@ import io.appform.ranger.client.AbstractRangerHubClient; import io.appform.ranger.client.utils.RangerHubTestUtils; import io.appform.ranger.core.finder.serviceregistry.ListBasedServiceRegistry; -import io.appform.ranger.core.finderhub.*; +import io.appform.ranger.core.finderhub.ServiceDataSource; +import io.appform.ranger.core.finderhub.ServiceFinderFactory; +import io.appform.ranger.core.finderhub.ServiceFinderHub; +import io.appform.ranger.core.finderhub.ServiceFinderHubBuilder; +import io.appform.ranger.core.finderhub.StaticDataSource; import io.appform.ranger.core.units.TestNodeData; import lombok.Builder; import lombok.Getter; @@ -38,15 +42,15 @@ protected ServiceFinderHub> return new ServiceFinderHubBuilder>() { @Override protected void preBuild() { - + // no-op } @Override protected void postBuild(ServiceFinderHub> serviceFinderHub) { - + // no-op } }.withServiceDataSource(getServiceDataSource()) - .withServiceFinderFactory(getFinderFactory()) + .withServiceFinderFactory(getFinderFactory()) .build(); } diff --git a/ranger-client/src/test/java/io/appform/ranger/client/stubs/TestServiceFinderFactory.java b/ranger-client/src/test/java/io/appform/ranger/client/stubs/TestServiceFinderFactory.java index 24e302c5..75be0a7b 100644 --- a/ranger-client/src/test/java/io/appform/ranger/client/stubs/TestServiceFinderFactory.java +++ b/ranger-client/src/test/java/io/appform/ranger/client/stubs/TestServiceFinderFactory.java @@ -23,7 +23,7 @@ import io.appform.ranger.core.units.TestNodeData; import lombok.val; -public class TestServiceFinderFactory implements ServiceFinderFactory> { +public class TestServiceFinderFactory implements ServiceFinderFactory> { @Override public ServiceFinder> buildFinder(Service service) { diff --git a/ranger-client/src/test/java/io/appform/ranger/client/stubs/TestSimpleUnshardedServiceFinder.java b/ranger-client/src/test/java/io/appform/ranger/client/stubs/TestSimpleUnshardedServiceFinder.java index 3cbb0258..7b8967da 100644 --- a/ranger-client/src/test/java/io/appform/ranger/client/stubs/TestSimpleUnshardedServiceFinder.java +++ b/ranger-client/src/test/java/io/appform/ranger/client/stubs/TestSimpleUnshardedServiceFinder.java @@ -29,7 +29,7 @@ import java.util.Optional; @Builder -public class TestSimpleUnshardedServiceFinder +public class TestSimpleUnshardedServiceFinder extends SimpleUnshardedServiceFinderBuilder, Deserializer> { @Override @@ -42,7 +42,7 @@ protected NodeDataSource> dataSource(Se return new TestDataSource(); } - static class TestDataSource implements NodeDataSource>{ + static class TestDataSource implements NodeDataSource> { @Override public Optional>> refresh(Deserializer deserializer) { @@ -58,17 +58,17 @@ public Optional>> refresh(Deserializer()) - .build(); + .namespace(service.getNamespace()) + .mapper(mapper) + .nodeRefreshTimeMs(1000) + .initialCriteria(new TestCriteria()) + .useDefaultDataSource(false) + .serviceDataSource(new StaticDataSource(Sets.newHashSet(RangerHubTestUtils.service))) + .deserializer(new TestDeserializer<>()) + .build(); } } diff --git a/ranger-core/pom.xml b/ranger-core/pom.xml index 88ffb76a..2e01d099 100644 --- a/ranger-core/pom.xml +++ b/ranger-core/pom.xml @@ -29,13 +29,13 @@ Core libraries for Ranger - 4.5.13 + 5.5 - org.apache.httpcomponents - httpclient + org.apache.httpcomponents.client5 + httpclient5 ${httpclient.version} @@ -45,7 +45,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.2.0 + ${maven.jar.plugin.version} diff --git a/ranger-core/src/main/java/io/appform/ranger/core/finder/BaseServiceFinderBuilder.java b/ranger-core/src/main/java/io/appform/ranger/core/finder/BaseServiceFinderBuilder.java index 23859a41..2dc4f2c5 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/finder/BaseServiceFinderBuilder.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/finder/BaseServiceFinderBuilder.java @@ -21,7 +21,12 @@ import io.appform.ranger.core.finder.nodeselector.RandomServiceNodeSelector; import io.appform.ranger.core.finder.serviceregistry.ServiceRegistryUpdater; import io.appform.ranger.core.finder.serviceregistry.signal.ScheduledRegistryUpdateSignal; -import io.appform.ranger.core.model.*; +import io.appform.ranger.core.model.Deserializer; +import io.appform.ranger.core.model.NodeDataSource; +import io.appform.ranger.core.model.Service; +import io.appform.ranger.core.model.ServiceNodeSelector; +import io.appform.ranger.core.model.ServiceRegistry; +import io.appform.ranger.core.model.ShardSelector; import io.appform.ranger.core.signals.Signal; import lombok.extern.slf4j.Slf4j; import lombok.val; @@ -55,77 +60,77 @@ public abstract class BaseServiceFinderBuilder public B withNamespace(final String namespace) { this.namespace = namespace; - return (B)this; + return (B) this; } public B withServiceName(final String serviceName) { this.serviceName = serviceName; - return (B)this; + return (B) this; } public B withDeserializer(D deserializer) { this.deserializer = deserializer; - return (B)this; + return (B) this; } public B withShardSelector(ShardSelector shardSelector) { this.shardSelector = shardSelector; - return (B)this; + return (B) this; } public B withNodeSelector(ServiceNodeSelector nodeSelector) { this.nodeSelector = null != nodeSelector ? nodeSelector : this.nodeSelector; - return (B)this; + return (B) this; } public B withNodeRefreshIntervalMs(int nodeRefreshIntervalMs) { this.nodeRefreshIntervalMs = nodeRefreshIntervalMs; - return (B)this; + return (B) this; } public B withDisableWatchers() { this.disablePushUpdaters = true; - return (B)this; + return (B) this; } public B withDisableWatchers(boolean disablePushUpdaters) { this.disablePushUpdaters = disablePushUpdaters; - return (B)this; + return (B) this; } public B withAdditionalSignalGenerator(Signal signalGenerator) { this.additionalRefreshSignals.add(signalGenerator); - return (B)this; + return (B) this; } public B withAdditionalSignalGenerators(Signal... signalGenerators) { this.additionalRefreshSignals.addAll(Arrays.asList(signalGenerators)); - return (B)this; + return (B) this; } public B withAdditionalSignalGenerators(List> signalGenerators) { this.additionalRefreshSignals.addAll(signalGenerators); - return (B)this; + return (B) this; } public B withStartSignalHandler(Consumer startSignalHandler) { this.startSignalHandlers.add(startSignalHandler); - return (B)this; + return (B) this; } public B withStartSignalHandlers(List> startSignalHandlers) { this.startSignalHandlers.addAll(startSignalHandlers); - return (B)this; + return (B) this; } public B withStopSignalHandler(Consumer stopSignalHandler) { this.stopSignalHandlers.add(stopSignalHandler); - return (B)this; + return (B) this; } public B withStopSignalHandlers(List> stopSignalHandlers) { this.stopSignalHandlers.addAll(stopSignalHandlers); - return (B)this; + return (B) this; } public abstract F build(); @@ -137,7 +142,7 @@ protected F buildFinder() { if (nodeRefreshIntervalMs < 1000) { log.warn("Node refresh interval for {} is too low: {} ms. Has been upgraded to 1000ms ", - serviceName, nodeRefreshIntervalMs); + serviceName, nodeRefreshIntervalMs); nodeRefreshIntervalMs = 1000; } val service = Service.builder().namespace(namespace).serviceName(serviceName).build(); diff --git a/ranger-core/src/main/java/io/appform/ranger/core/finder/ServiceFinder.java b/ranger-core/src/main/java/io/appform/ranger/core/finder/ServiceFinder.java index 2e34d543..b3842a1b 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/finder/ServiceFinder.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/finder/ServiceFinder.java @@ -39,10 +39,10 @@ public abstract class ServiceFinder> { private final ServiceNodeSelector nodeSelector; @Getter private final ExternalTriggeredSignal startSignal = new ExternalTriggeredSignal<>(() -> null, - Collections.emptyList()); + Collections.emptyList()); @Getter private final ExternalTriggeredSignal stopSignal = new ExternalTriggeredSignal<>(() -> null, - Collections.emptyList()); + Collections.emptyList()); protected ServiceFinder( R serviceRegistry, @@ -70,8 +70,8 @@ public Optional> get( val nodes = ObjectUtils.requireNonNullElse(shardSelector, this.shardSelector) .nodes(criteria, serviceRegistry); return nodes.isEmpty() - ? Optional.empty() - : Optional.ofNullable(ObjectUtils.requireNonNullElse(nodeSelector, this.nodeSelector).select(nodes)); + ? Optional.empty() + : Optional.ofNullable(ObjectUtils.requireNonNullElse(nodeSelector, this.nodeSelector).select(nodes)); } public List> getAll(Predicate criteria) { diff --git a/ranger-core/src/main/java/io/appform/ranger/core/finder/SimpleShardedServiceFinderBuilder.java b/ranger-core/src/main/java/io/appform/ranger/core/finder/SimpleShardedServiceFinderBuilder.java index 3689b73a..e6a71adf 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/finder/SimpleShardedServiceFinderBuilder.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/finder/SimpleShardedServiceFinderBuilder.java @@ -23,7 +23,7 @@ import io.appform.ranger.core.model.ServiceNodeSelector; import io.appform.ranger.core.model.ShardSelector; -public abstract class SimpleShardedServiceFinderBuilder, D extends Deserializer> +public abstract class SimpleShardedServiceFinderBuilder, D extends Deserializer> extends BaseServiceFinderBuilder, SimpleShardedServiceFinder, B, D> { @Override diff --git a/ranger-core/src/main/java/io/appform/ranger/core/finder/serviceregistry/ListBasedServiceRegistry.java b/ranger-core/src/main/java/io/appform/ranger/core/finder/serviceregistry/ListBasedServiceRegistry.java index 77c6b41f..367604a0 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/finder/serviceregistry/ListBasedServiceRegistry.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/finder/serviceregistry/ListBasedServiceRegistry.java @@ -29,7 +29,7 @@ @EqualsAndHashCode(callSuper = true) public class ListBasedServiceRegistry extends ServiceRegistry { private final AtomicReference>> nodes - = new AtomicReference<>(); + = new AtomicReference<>(); public ListBasedServiceRegistry(Service service) { super(service); diff --git a/ranger-core/src/main/java/io/appform/ranger/core/finder/serviceregistry/MapBasedServiceRegistry.java b/ranger-core/src/main/java/io/appform/ranger/core/finder/serviceregistry/MapBasedServiceRegistry.java index 4352cab6..91ae4777 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/finder/serviceregistry/MapBasedServiceRegistry.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/finder/serviceregistry/MapBasedServiceRegistry.java @@ -21,7 +21,6 @@ import io.appform.ranger.core.model.Service; import io.appform.ranger.core.model.ServiceNode; import io.appform.ranger.core.model.ServiceRegistry; - import lombok.EqualsAndHashCode; import lombok.val; diff --git a/ranger-core/src/main/java/io/appform/ranger/core/finder/serviceregistry/ServiceRegistryUpdater.java b/ranger-core/src/main/java/io/appform/ranger/core/finder/serviceregistry/ServiceRegistryUpdater.java index 70d43b7c..573de64b 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/finder/serviceregistry/ServiceRegistryUpdater.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/finder/serviceregistry/ServiceRegistryUpdater.java @@ -16,7 +16,6 @@ package io.appform.ranger.core.finder.serviceregistry; import com.github.rholder.retry.RetryerBuilder; -import com.github.rholder.retry.WaitStrategies; import com.google.common.base.Preconditions; import com.google.common.base.Stopwatch; import io.appform.ranger.core.healthcheck.HealthcheckStatus; @@ -26,7 +25,6 @@ import io.appform.ranger.core.signals.Signal; import io.appform.ranger.core.util.Exceptions; import io.appform.ranger.core.util.FinderUtils; -import java.util.concurrent.atomic.AtomicBoolean; import lombok.extern.slf4j.Slf4j; import lombok.val; @@ -35,6 +33,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -77,12 +76,11 @@ public void start() { .retryIfException() .build() .call(serviceRegistry::isRefreshed); - } - catch (Exception e) { + } catch (Exception e) { Exceptions.illegalState("Could not perform initial state for service: " + serviceName, e); } log.info("Initial node list updated for service: {} in {}ms", - serviceName, stopwatch.elapsed(TimeUnit.MILLISECONDS)); + serviceName, stopwatch.elapsed(TimeUnit.MILLISECONDS)); } public void stop() { @@ -97,8 +95,7 @@ public void checkForUpdate(T signalData) { checkLock.lock(); checkForUpdate.set(true); checkCondition.signalAll(); - } - finally { + } finally { checkLock.unlock(); } } @@ -112,16 +109,13 @@ private Void queryExecutor() { checkCondition.await(); } updateRegistry(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { log.info("Updater thread interrupted"); Thread.currentThread().interrupt(); return null; - } - catch (Exception e) { + } catch (Exception e) { log.error("Registry update failed for service: " + serviceRegistry.getService().name(), e); - } - finally { + } finally { checkForUpdate.set(false); checkLock.unlock(); } @@ -130,7 +124,7 @@ private Void queryExecutor() { private void updateRegistry() throws InterruptedException { log.debug("Checking for updates on data source for service: {}", - serviceRegistry.getService().getServiceName()); + serviceRegistry.getService().getServiceName()); var callFailed = false; if (nodeDataSource.isActive()) { //Source should implement circuit breaker to fail fast and reopen after some // time @@ -138,34 +132,32 @@ private void updateRegistry() throws InterruptedException { val nodeList = nodeDataSource.refresh(deserializer).orElse(null); if (null != nodeList) { log.debug("Updating nodeList of size: {} for [{}]", nodeList.size(), - serviceRegistry.getService().getServiceName()); + serviceRegistry.getService().getServiceName()); val livenessCheckMaxAge = nodeDataSource.healthcheckZombieCheckThresholdTime(serviceRegistry.getService()); //Remove all stale nodes before updating. This is done centrally to ensure some data sources //don't skip this check. Some control is still provided so that they can overload. serviceRegistry.updateNodes(FinderUtils.filterValidNodes(serviceRegistry.getService(), nodeList, livenessCheckMaxAge)); - } - else { + } else { log.warn("Empty list returned from node data source. We are in a weird state. Keeping old list for {}", serviceRegistry.getService().getServiceName()); } - } - catch (Exception e) { + } catch (Exception e) { log.error("Error updating data from registry. Error: [{}] {}", - e.getClass().getSimpleName(), - e.getMessage()); + e.getClass().getSimpleName(), + e.getMessage()); callFailed = true; } } if (!nodeDataSource.isActive() || callFailed) { val currTime = System.currentTimeMillis(); log.warn("Node data source seems to be down. Keeping old list for {}." + - " Will update timestamp to keep stale date relevant.", - serviceRegistry.getService().getServiceName()); + " Will update timestamp to keep stale date relevant.", + serviceRegistry.getService().getServiceName()); serviceRegistry.updateNodes(serviceRegistry.nodeList() - .stream() - .filter(node -> HealthcheckStatus.healthy == node.getHealthcheckStatus()) - .map(node -> node.setLastUpdatedTimeStamp(currTime)) - .toList()); + .stream() + .filter(node -> HealthcheckStatus.healthy == node.getHealthcheckStatus()) + .map(node -> node.setLastUpdatedTimeStamp(currTime)) + .toList()); } } diff --git a/ranger-core/src/main/java/io/appform/ranger/core/finder/shardselector/ListShardSelector.java b/ranger-core/src/main/java/io/appform/ranger/core/finder/shardselector/ListShardSelector.java index 6b7acf03..ca712c13 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/finder/shardselector/ListShardSelector.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/finder/shardselector/ListShardSelector.java @@ -21,7 +21,6 @@ import java.util.List; import java.util.function.Predicate; -import java.util.stream.Collectors; public class ListShardSelector implements ShardSelector> { diff --git a/ranger-core/src/main/java/io/appform/ranger/core/finder/shardselector/MatchingShardSelector.java b/ranger-core/src/main/java/io/appform/ranger/core/finder/shardselector/MatchingShardSelector.java index 86317c75..53581aa4 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/finder/shardselector/MatchingShardSelector.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/finder/shardselector/MatchingShardSelector.java @@ -23,18 +23,17 @@ import java.util.List; import java.util.Map; import java.util.function.Predicate; -import java.util.stream.Collectors; public class MatchingShardSelector implements ShardSelector> { @Override public List> nodes(Predicate criteria, MapBasedServiceRegistry serviceRegistry) { return null == criteria ? serviceRegistry.nodeList() : - serviceRegistry.nodes() - .entries() - .stream() - .filter(e -> criteria.test(e.getKey())) - .map(Map.Entry::getValue) - .toList(); + serviceRegistry.nodes() + .entries() + .stream() + .filter(e -> criteria.test(e.getKey())) + .map(Map.Entry::getValue) + .toList(); } } diff --git a/ranger-core/src/main/java/io/appform/ranger/core/finderhub/ServiceDataSource.java b/ranger-core/src/main/java/io/appform/ranger/core/finderhub/ServiceDataSource.java index 7d32d76d..07c48b27 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/finderhub/ServiceDataSource.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/finderhub/ServiceDataSource.java @@ -25,9 +25,12 @@ public interface ServiceDataSource { Collection services(); + default void add(Service service) { throw new UnsupportedOperationException("Service addition is unsupported"); } + void start(); + void stop(); } diff --git a/ranger-core/src/main/java/io/appform/ranger/core/finderhub/ServiceFinderHub.java b/ranger-core/src/main/java/io/appform/ranger/core/finderhub/ServiceFinderHub.java index 9feed7d9..20a269ef 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/finderhub/ServiceFinderHub.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/finderhub/ServiceFinderHub.java @@ -32,8 +32,21 @@ import lombok.extern.slf4j.Slf4j; import lombok.val; -import java.util.*; -import java.util.concurrent.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -85,7 +98,7 @@ public ServiceFinderHub( ServiceDataSource serviceDataSource, ServiceFinderFactory finderFactory) { this(serviceDataSource, finderFactory, - HubConstants.SERVICE_REFRESH_TIMEOUT_MS, HubConstants.HUB_START_TIMEOUT_MS, Set.of()); + HubConstants.SERVICE_REFRESH_TIMEOUT_MS, HubConstants.HUB_START_TIMEOUT_MS, Set.of()); } public ServiceFinderHub( @@ -99,9 +112,9 @@ public ServiceFinderHub( this.serviceRefreshTimeoutMs = serviceRefreshTimeoutMs == 0 ? HubConstants.SERVICE_REFRESH_TIMEOUT_MS : serviceRefreshTimeoutMs; this.hubStartTimeoutMs = hubStartTimeoutMs == 0 ? HubConstants.HUB_START_TIMEOUT_MS : hubStartTimeoutMs; this.refreshSignals.add(new ScheduledSignal<>("service-hub-updater", - () -> null, - Collections.emptyList(), - 10_000)); + () -> null, + Collections.emptyList(), + 10_000)); this.refresherPool = createRefresherPool(); this.excludedServices = Objects.requireNonNullElseGet(excludedServices, Set::of); } @@ -121,8 +134,7 @@ public CompletableFuture> buildFinder(final Service service) updateAvailable(); waitTillServiceIsReady(service); return finders.get().get(service); - } - catch (Exception e) { + } catch (Exception e) { log.warn("Exception whiling building finder", e); throw e; } @@ -145,8 +157,7 @@ public void stop() { if (null != monitorFuture) { try { monitorFuture.cancel(true); - } - catch (Exception e) { + } catch (Exception e) { log.warn("Error stopping service finder hub monitor: {}", e.getMessage()); } } @@ -162,13 +173,12 @@ public void updateAvailable() { updateLock.lock(); updateAvailable.set(true); updateCond.signalAll(); - } - finally { + } finally { updateLock.unlock(); } } - private ForkJoinPool createRefresherPool() { + private ForkJoinPool createRefresherPool() { return new ForkJoinPool( Math.max(20, Runtime.getRuntime().availableProcessors()), pool -> { @@ -188,13 +198,11 @@ private void monitor() { updateCond.await(); } executorService.submit(this::updateRegistry); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { log.info("Updater thread interrupted"); Thread.currentThread().interrupt(); break; - } - finally { + } finally { updateAvailable.set(false); updateLock.unlock(); } @@ -230,15 +238,12 @@ private void updateRegistry() { updatedFinders.putAll(newFinders); updatedFinders.putAll(matchingServices); finders.set(updatedFinders); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); log.error("Refresh interrupted."); - } - catch (Exception e) { + } catch (Exception e) { log.error("Error updating service list. Will maintain older list", e); - } - finally { + } finally { alreadyUpdating.set(false); } } @@ -246,10 +251,10 @@ private void updateRegistry() { private void waitTillHubIsReady() { val services = FinderUtils.getEligibleServices(serviceDataSource.services(), excludedServices); val timeToRefresh = Math.max(hubStartTimeoutMs, - (serviceRefreshTimeoutMs * services.size()) / refresherPool.getParallelism()); + (serviceRefreshTimeoutMs * services.size()) / refresherPool.getParallelism()); if (timeToRefresh != hubStartTimeoutMs) { log.warn("Max hub refresh time has been dynamically adjusted to {} ms from the provided {} ms as the " + - "provided time would have been insufficient to refresh {} services.", + "provided time would have been insufficient to refresh {} services.", timeToRefresh, hubStartTimeoutMs, services.size()); } val hubRefresher = CompletableFuture.allOf( @@ -260,16 +265,13 @@ private void waitTillHubIsReady() { })).toArray(CompletableFuture[]::new)); try { hubRefresher.get(timeToRefresh, TimeUnit.MILLISECONDS); - } - catch (InterruptedException ie) { + } catch (InterruptedException ie) { Thread.currentThread().interrupt(); Exceptions.illegalState("Refresh interrupted"); - } - catch (TimeoutException e) { + } catch (TimeoutException e) { Exceptions.illegalState("Couldn't perform service hub refresh at this time. " + - "Refresh exceeded the start up time specified"); - } - catch (Exception e) { + "Refresh exceeded the start up time specified"); + } catch (Exception e) { Exceptions.illegalState("Couldn't perform hub refresh at this time", e); } } @@ -285,8 +287,7 @@ private void waitTillServiceIsReady(Service service) { .map(ServiceFinder::getServiceRegistry) .map(ServiceRegistry::isRefreshed) .orElse(false)); - } - catch (Exception e) { + } catch (Exception e) { Exceptions .illegalState("Could not perform initial state for service: " + service.getServiceName(), e); } diff --git a/ranger-core/src/main/java/io/appform/ranger/core/finderhub/ServiceFinderHubBuilder.java b/ranger-core/src/main/java/io/appform/ranger/core/finderhub/ServiceFinderHubBuilder.java index 3ec7ae39..f8bfa778 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/finderhub/ServiceFinderHubBuilder.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/finderhub/ServiceFinderHubBuilder.java @@ -99,9 +99,9 @@ public ServiceFinderHub build() { val hub = new ServiceFinderHub<>(serviceDataSource, serviceFinderFactory, serviceRefreshTimeoutMs, hubStartTimeoutMs, excludedServices); final ScheduledSignal refreshSignal = new ScheduledSignal<>("service-hub-refresh-timer", - () -> null, - Collections.emptyList(), - refreshFrequencyMs); + () -> null, + Collections.emptyList(), + refreshFrequencyMs); hub.registerUpdateSignal(refreshSignal); extraRefreshSignals.forEach(hub::registerUpdateSignal); diff --git a/ranger-core/src/main/java/io/appform/ranger/core/healthcheck/HealthChecker.java b/ranger-core/src/main/java/io/appform/ranger/core/healthcheck/HealthChecker.java index be9a1f79..78e029bf 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/healthcheck/HealthChecker.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/healthcheck/HealthChecker.java @@ -39,7 +39,7 @@ public HealthChecker(List healthChecks, int staleUpdateThreshold) { @Override public HealthcheckResult get() { - if(refreshHealth()) { + if (refreshHealth()) { return HealthcheckResult.builder() .status(lastHealthcheckStatus) .updatedTime(lastUpdatedTime) @@ -53,8 +53,7 @@ private boolean refreshHealth() { for (Healthcheck healthcheck : healthChecks) { try { healthcheckStatus = healthcheck.check(); - } - catch (Exception e) { + } catch (Exception e) { log.error("Error running healthcheck. Setting node to unhealthy", e); healthcheckStatus = HealthcheckStatus.unhealthy; } @@ -75,8 +74,7 @@ private boolean refreshHealth() { lastUpdatedTime = currentTime; return true; } - } - finally { + } finally { lastHealthcheckStatus = healthcheckStatus; } return false; diff --git a/ranger-core/src/main/java/io/appform/ranger/core/healthcheck/HealthcheckStatus.java b/ranger-core/src/main/java/io/appform/ranger/core/healthcheck/HealthcheckStatus.java index 8ab79ef8..3e53462f 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/healthcheck/HealthcheckStatus.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/healthcheck/HealthcheckStatus.java @@ -15,6 +15,7 @@ */ package io.appform.ranger.core.healthcheck; +@SuppressWarnings("java:S115") public enum HealthcheckStatus { healthy, unhealthy diff --git a/ranger-core/src/main/java/io/appform/ranger/core/healthservice/ServiceHealthAggregator.java b/ranger-core/src/main/java/io/appform/ranger/core/healthservice/ServiceHealthAggregator.java index 2f349f2c..d2544585 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/healthservice/ServiceHealthAggregator.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/healthservice/ServiceHealthAggregator.java @@ -163,10 +163,10 @@ private boolean isIsolatedMonitorUnHealthy(IsolatedHealthMonitor implements Runnable, Monitor { private final long stalenessAllowedInMillis; /** - * @param name name of the monitor + * @param name name of the monitor * @param runInterval initial delay, time interval of how regularly the monitor is to be run, and timeunit - * to specify how often the {@link #monitor()} check needs to be executed + * to specify how often the {@link #monitor()} check needs to be executed */ protected IsolatedHealthMonitor(String name, TimeEntity runInterval) { this(name, runInterval, 60000); @@ -67,7 +67,7 @@ protected IsolatedHealthMonitor(String name, TimeEntity runInterval) { /** * @param name name of the monitor - * @param runInterval initial delay, time interval of how regularly the monitor is to be run, and timeunit + * @param runInterval initial delay, time interval of how regularly the monitor is to be run, and timeunit * to specify how often the {@link #monitor()} check needs to be executed * @param stalenessAllowedInMillis after how long (in milliseconds) should the monitor be regarded as stale (default: 60 seconds) */ @@ -114,7 +114,7 @@ public boolean isDisabled() { return disabled.get(); } - public boolean hasValidUpdatedTime(Date currentTime){ + public boolean hasValidUpdatedTime(Date currentTime) { return null != lastStatusUpdateTime && (currentTime.getTime() - lastStatusUpdateTime.getTime() <= stalenessAllowedInMillis); } } diff --git a/ranger-core/src/main/java/io/appform/ranger/core/healthservice/monitor/sample/CountMonitor.java b/ranger-core/src/main/java/io/appform/ranger/core/healthservice/monitor/sample/CountMonitor.java index dada1dde..4a39e894 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/healthservice/monitor/sample/CountMonitor.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/healthservice/monitor/sample/CountMonitor.java @@ -21,7 +21,7 @@ import lombok.val; /** - * A monitor that can be used as a counting monitor to check if any countable entity breaches a threashhold + * A monitor that can be used as a counting monitor to check if any countable entity breaches a threshold * Eg: * 1. this could be used to check the heap of your java service, if heap goes beyond a threshold, * after which, you would want your service to be marked as unhealthy diff --git a/ranger-core/src/main/java/io/appform/ranger/core/healthservice/monitor/sample/DiskSpaceMonitor.java b/ranger-core/src/main/java/io/appform/ranger/core/healthservice/monitor/sample/DiskSpaceMonitor.java index 2b1b6698..a1cd0af8 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/healthservice/monitor/sample/DiskSpaceMonitor.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/healthservice/monitor/sample/DiskSpaceMonitor.java @@ -29,23 +29,23 @@ public class DiskSpaceMonitor extends CountMonitor { private final String partition; /** - * @param partition partition to be monitored - * @param countThreshhold maximum freespace of partition, below which, the monitor will mark itself as unhealthy - * @param timeEntity how often the {@link #monitor()} check needs to be executed + * @param partition partition to be monitored + * @param countThreshold maximum free space of partition, below which, the monitor will mark itself as unhealthy + * @param timeEntity how often the {@link #monitor()} check needs to be executed */ - public DiskSpaceMonitor(String partition, Integer countThreshhold, TimeEntity timeEntity) { - super(DiskSpaceMonitor.class.getSimpleName(), CheckSign.GREATER_THAN, countThreshhold, timeEntity); + public DiskSpaceMonitor(String partition, Integer countThreshold, TimeEntity timeEntity) { + super(DiskSpaceMonitor.class.getSimpleName(), CheckSign.GREATER_THAN, countThreshold, timeEntity); this.partition = partition; } /** * @param partition partition to be monitored * @param name name of monitor - * @param threshhold maximum freespace of partition, below which, the monitor will mark itself as unhealthy + * @param threshold maximum free space of partition, below which, the monitor will mark itself as unhealthy * @param timeEntity how often the {@link #monitor()} check needs to be executed */ - public DiskSpaceMonitor(String partition, String name, Integer threshhold, TimeEntity timeEntity) { - super(name, CheckSign.GREATER_THAN, threshhold, timeEntity); + public DiskSpaceMonitor(String partition, String name, Integer threshold, TimeEntity timeEntity) { + super(name, CheckSign.GREATER_THAN, threshold, timeEntity); this.partition = partition; } diff --git a/ranger-core/src/main/java/io/appform/ranger/core/healthservice/monitor/sample/PingCheckMonitor.java b/ranger-core/src/main/java/io/appform/ranger/core/healthservice/monitor/sample/PingCheckMonitor.java index d6995530..f67ad473 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/healthservice/monitor/sample/PingCheckMonitor.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/healthservice/monitor/sample/PingCheckMonitor.java @@ -21,15 +21,20 @@ import io.appform.ranger.core.healthservice.monitor.RollingWindowHealthQueue; import lombok.extern.slf4j.Slf4j; import lombok.val; -import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; -import org.apache.http.HttpStatus; -import org.apache.http.conn.routing.HttpRoute; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.HttpStatus; -import java.util.concurrent.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; /** * A Ping checking monitor, which executes a {@link HttpRequest} at regular intervals @@ -38,8 +43,8 @@ @Slf4j @SuppressWarnings("unused") public class PingCheckMonitor extends IsolatedHealthMonitor { - - private final HttpRequest httpRequest; + + private final ClassicHttpRequest httpRequest; private final String host; private final ExecutorService executorService; private final Integer pingTimeoutInMilliseconds; @@ -58,7 +63,7 @@ public class PingCheckMonitor extends IsolatedHealthMonitor { */ public PingCheckMonitor( TimeEntity timeEntity, - HttpRequest httpRequest, + ClassicHttpRequest httpRequest, Integer pingTimeoutInMilliseconds, Integer pingWindowSize, Integer maxFailures, @@ -92,8 +97,7 @@ public HealthcheckStatus monitor() { log.error("Request thread interrupted"); Thread.currentThread().interrupt(); return getRollingWindowHealthcheckStatus(HealthcheckStatus.unhealthy); - } - catch (ExecutionException | TimeoutException e) { + } catch (ExecutionException | TimeoutException e) { log.error("Ping monitor failed:{} with HttpRequest:{} on host:{} port:{}", name, httpRequest, host, port); log.error("Error running ping monitor: ", e); return getRollingWindowHealthcheckStatus(HealthcheckStatus.unhealthy); @@ -114,8 +118,8 @@ private boolean healthPing() { try { log.debug("executing http HttpRequest: {}, host:{}, port:{}", httpRequest, host, port); val response = httpClient.execute(new HttpHost(host, port), httpRequest); - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { - log.error("Error while executing Ping Test. HttpRequest: {}, host:{}, port:{}, reason:{}", httpRequest, host, port, response.getStatusLine().getReasonPhrase()); + if (response.getCode() != HttpStatus.SC_OK) { + log.error("Error while executing Ping Test. HttpRequest: {}, host:{}, port:{}, reason:{}", httpRequest, host, port, response.getReasonPhrase()); response.close(); return false; } diff --git a/ranger-core/src/main/java/io/appform/ranger/core/model/PortSchemes.java b/ranger-core/src/main/java/io/appform/ranger/core/model/PortSchemes.java index 70b31870..85537cfe 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/model/PortSchemes.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/model/PortSchemes.java @@ -21,7 +21,7 @@ @UtilityClass public class PortSchemes { - public static final String HTTP = "http"; - public static final String HTTPS = "https"; - public static final String TCP = "tcp"; + public static final String HTTP = "http"; + public static final String HTTPS = "https"; + public static final String TCP = "tcp"; } diff --git a/ranger-core/src/main/java/io/appform/ranger/core/model/ServiceRegistry.java b/ranger-core/src/main/java/io/appform/ranger/core/model/ServiceRegistry.java index f34530ac..8bc42a94 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/model/ServiceRegistry.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/model/ServiceRegistry.java @@ -15,10 +15,10 @@ */ package io.appform.ranger.core.model; -import java.util.concurrent.atomic.AtomicBoolean; +import lombok.Getter; import java.util.List; -import lombok.Getter; +import java.util.concurrent.atomic.AtomicBoolean; public abstract class ServiceRegistry { @Getter diff --git a/ranger-core/src/main/java/io/appform/ranger/core/serviceprovider/BaseServiceProviderBuilder.java b/ranger-core/src/main/java/io/appform/ranger/core/serviceprovider/BaseServiceProviderBuilder.java index b472998e..14ac6b80 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/serviceprovider/BaseServiceProviderBuilder.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/serviceprovider/BaseServiceProviderBuilder.java @@ -71,47 +71,47 @@ public BaseServiceProviderBuilder withNamespace(final String namespace) public B withServiceName(final String serviceName) { this.serviceName = serviceName; - return (B)this; + return (B) this; } public B withSerializer(S serializer) { this.serializer = serializer; - return (B)this; + return (B) this; } public B withHostname(final String hostname) { this.hostname = hostname; - return (B)this; + return (B) this; } public B withPort(int port) { this.port = port; - return (B)this; + return (B) this; } - public B withPortScheme(String portScheme){ + public B withPortScheme(String portScheme) { this.portScheme = portScheme; - return (B)this; + return (B) this; } public B withNodeData(T nodeData) { this.nodeData = nodeData; - return (B)this; + return (B) this; } public B withHealthcheck(Healthcheck healthcheck) { this.healthchecks.add(healthcheck); - return (B)this; + return (B) this; } public B withHealthUpdateIntervalMs(int healthUpdateIntervalMs) { this.healthUpdateIntervalMs = healthUpdateIntervalMs; - return (B)this; + return (B) this; } public B withStaleUpdateThresholdMs(int staleUpdateThresholdMs) { this.staleUpdateThresholdMs = staleUpdateThresholdMs; - return (B)this; + return (B) this; } /** @@ -125,42 +125,42 @@ public B withStaleUpdateThresholdMs(int staleUpdateThresholdMs) { */ public B withIsolatedHealthMonitor(IsolatedHealthMonitor monitor) { this.isolatedMonitors.add(monitor); - return (B)this; + return (B) this; } public B withNodeDataSource(NodeDataSink nodeDataSource) { this.nodeDataSource = nodeDataSource; - return (B)this; + return (B) this; } public B withStartSignalHandler(Consumer startSignalHandler) { this.startSignalHandlers.add(startSignalHandler); - return (B)this; + return (B) this; } public B withStartSignalHandlers(List> startSignalHandlers) { this.startSignalHandlers.addAll(startSignalHandlers); - return (B)this; + return (B) this; } public B withStopSignalHandler(Consumer stopSignalHandler) { this.stopSignalHandlers.add(stopSignalHandler); - return (B)this; + return (B) this; } public B withStopSignalHandlers(List> stopSignalHandlers) { this.stopSignalHandlers.addAll(stopSignalHandlers); - return (B)this; + return (B) this; } public B withAdditionalRefreshSignal(Signal additionalRefreshSignal) { this.additionalRefreshSignals.add(additionalRefreshSignal); - return (B)this; + return (B) this; } public B withAdditionalRefreshSignals(List> additionalRefreshSignals) { this.additionalRefreshSignals.addAll(additionalRefreshSignals); - return (B)this; + return (B) this; } protected final ServiceProvider buildProvider() { @@ -173,13 +173,13 @@ protected final ServiceProvider buildProvider() { if (healthUpdateIntervalMs < 1000 || healthUpdateIntervalMs > 20000) { log.warn("Health update interval for {} should be between 1000ms and 20000ms. Current value: {} ms. " + - "Being set to 1000ms", serviceName, healthUpdateIntervalMs); + "Being set to 1000ms", serviceName, healthUpdateIntervalMs); healthUpdateIntervalMs = 1000; } if (staleUpdateThresholdMs < 5000 || staleUpdateThresholdMs > 20000) { log.warn("Stale update threshold for {} should be between 5000ms and 20000ms. Current value: {} ms. " + - "Being set to 5000ms", serviceName, staleUpdateThresholdMs); + "Being set to 5000ms", serviceName, staleUpdateThresholdMs); staleUpdateThresholdMs = 5000; } @@ -206,15 +206,15 @@ protected final ServiceProvider buildProvider() { .addAll(additionalRefreshSignals) .build(); val serviceNode = ServiceNode.builder() - .host(hostname) - .port(port) - .portScheme(portScheme) - .nodeData(nodeData) - .build(); + .host(hostname) + .port(port) + .portScheme(portScheme) + .nodeData(nodeData) + .build(); val serviceProvider = new ServiceProvider<>(service, serviceNode, - serializer, - usableNodeDataSource, - signalGenerators); + serializer, + usableNodeDataSource, + signalGenerators); val startSignal = serviceProvider.getStartSignal(); startSignal @@ -232,7 +232,7 @@ protected final ServiceProvider buildProvider() { return serviceProvider; } - public abstract ServiceProvider build(); + public abstract ServiceProvider build(); - protected abstract NodeDataSink dataSink(final Service service); + protected abstract NodeDataSink dataSink(final Service service); } diff --git a/ranger-core/src/main/java/io/appform/ranger/core/serviceprovider/ServiceProvider.java b/ranger-core/src/main/java/io/appform/ranger/core/serviceprovider/ServiceProvider.java index 08f7db50..f9cbb628 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/serviceprovider/ServiceProvider.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/serviceprovider/ServiceProvider.java @@ -65,7 +65,7 @@ public void stop() { } private void handleHealthUpdate(HealthcheckResult result) { - if(null == result) { + if (null == result) { log.debug("No update to health state of node. Skipping data source update."); return; } diff --git a/ranger-core/src/main/java/io/appform/ranger/core/signals/ExternalTriggeredSignal.java b/ranger-core/src/main/java/io/appform/ranger/core/signals/ExternalTriggeredSignal.java index 811aa815..168930b3 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/signals/ExternalTriggeredSignal.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/signals/ExternalTriggeredSignal.java @@ -24,7 +24,7 @@ */ public class ExternalTriggeredSignal extends Signal { - public ExternalTriggeredSignal( + public ExternalTriggeredSignal( Supplier signalDataGenerator, List> consumers) { super(signalDataGenerator, consumers); diff --git a/ranger-core/src/main/java/io/appform/ranger/core/signals/ScheduledSignal.java b/ranger-core/src/main/java/io/appform/ranger/core/signals/ScheduledSignal.java index a35342fb..e2530175 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/signals/ScheduledSignal.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/signals/ScheduledSignal.java @@ -67,7 +67,7 @@ public final void start() { try { onSignalReceived(); } catch (Exception e) { - log.error("Error delivering signal for:" + name , e); + log.error("Error delivering signal for:" + name, e); } }, 0, refreshIntervalMillis, TimeUnit.MILLISECONDS); log.info("Started scheduled signal generator: {}", name); @@ -75,7 +75,7 @@ public final void start() { @Override public final void stop() { - if(null != scheduledFuture) { + if (null != scheduledFuture) { scheduledFuture.cancel(true); } log.info("Stopped scheduled signal generator: {}", name); diff --git a/ranger-core/src/main/java/io/appform/ranger/core/signals/Signal.java b/ranger-core/src/main/java/io/appform/ranger/core/signals/Signal.java index bebae27f..cedd8a14 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/signals/Signal.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/signals/Signal.java @@ -32,7 +32,7 @@ public abstract class Signal { protected Signal(Supplier signalDataGenerator, List> consumers) { this.signalDataGenerator = signalDataGenerator; - if(null != consumers) { + if (null != consumers) { this.consumers.addAll(consumers); } } @@ -53,5 +53,6 @@ public Signal registerConsumers(List> consumers) { } public abstract void start(); + public abstract void stop(); } diff --git a/ranger-core/src/main/java/io/appform/ranger/core/util/FinderUtils.java b/ranger-core/src/main/java/io/appform/ranger/core/util/FinderUtils.java index 412486b4..b047a29c 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/util/FinderUtils.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/util/FinderUtils.java @@ -41,7 +41,7 @@ public static Set getEligibleServices(final Collection service } - public static List> filterValidNodes( + public static List> filterValidNodes( final Service service, final Collection> serviceNodes, long healthcheckZombieCheckThresholdTime) { @@ -54,16 +54,16 @@ public static boolean isValidNode( Service service, long healthcheckZombieCheckThresholdTime, ServiceNode serviceNode) { - if(null == serviceNode) return false; + if (null == serviceNode) return false; - if(HealthcheckStatus.healthy != serviceNode.getHealthcheckStatus()) { + if (HealthcheckStatus.healthy != serviceNode.getHealthcheckStatus()) { log.debug("Unhealthy node [{}:{}] found for [{}]", - serviceNode.getHost(), serviceNode.getPort(), service.getServiceName()); + serviceNode.getHost(), serviceNode.getPort(), service.getServiceName()); return false; } - if(serviceNode.getLastUpdatedTimeStamp() < healthcheckZombieCheckThresholdTime) { + if (serviceNode.getLastUpdatedTimeStamp() < healthcheckZombieCheckThresholdTime) { log.warn("Zombie node [{}:{}] found for [{}]", - serviceNode.getHost(), serviceNode.getPort(), service.getServiceName()); + serviceNode.getHost(), serviceNode.getPort(), service.getServiceName()); return false; } return true; diff --git a/ranger-core/src/main/java/io/appform/ranger/core/util/ObjectUtils.java b/ranger-core/src/main/java/io/appform/ranger/core/util/ObjectUtils.java index 91c74d2a..8eae6cc8 100644 --- a/ranger-core/src/main/java/io/appform/ranger/core/util/ObjectUtils.java +++ b/ranger-core/src/main/java/io/appform/ranger/core/util/ObjectUtils.java @@ -21,7 +21,7 @@ import java.util.Objects; /** - * Utility calss . To be removed when we move to J11 + * Utility class . To be removed when we move to J11 */ @UtilityClass public class ObjectUtils { diff --git a/ranger-core/src/test/java/io/appform/ranger/core/finder/UnshardedClusterFinderTest.java b/ranger-core/src/test/java/io/appform/ranger/core/finder/UnshardedClusterFinderTest.java index 0c815536..1778de35 100644 --- a/ranger-core/src/test/java/io/appform/ranger/core/finder/UnshardedClusterFinderTest.java +++ b/ranger-core/src/test/java/io/appform/ranger/core/finder/UnshardedClusterFinderTest.java @@ -36,8 +36,9 @@ public ServiceNode select(List> serviceN return serviceNodes.isEmpty() ? null : serviceNodes.get(0); } } + @Test - void unshardedClusterFinder(){ + void unshardedClusterFinder() { val unshardedRegistry = RegistryTestUtils.getUnshardedRegistry(); val shardSelector = new ListShardSelector(); val simpleUnshardedServiceFinder = new SimpleUnshardedServiceFinder<>( diff --git a/ranger-core/src/test/java/io/appform/ranger/core/finder/nodeselector/RoundRobinServiceNodeSelectorTest.java b/ranger-core/src/test/java/io/appform/ranger/core/finder/nodeselector/RoundRobinServiceNodeSelectorTest.java index e6cd0e37..9782fb45 100644 --- a/ranger-core/src/test/java/io/appform/ranger/core/finder/nodeselector/RoundRobinServiceNodeSelectorTest.java +++ b/ranger-core/src/test/java/io/appform/ranger/core/finder/nodeselector/RoundRobinServiceNodeSelectorTest.java @@ -25,7 +25,7 @@ class RoundRobinServiceNodeSelectorTest { @Test - void testRandomNodeSelector(){ + void testRandomNodeSelector() { val roundRobinSelector = new RoundRobinServiceNodeSelector(); val serviceNodes = new ArrayList>(); serviceNodes.add(ServiceNode.builder().host("localhost-1").port(9000).nodeData(TestNodeData.builder().shardId(1).build()).build()); diff --git a/ranger-core/src/test/java/io/appform/ranger/core/finder/serviceregistry/MapBasedServiceRegistryTest.java b/ranger-core/src/test/java/io/appform/ranger/core/finder/serviceregistry/MapBasedServiceRegistryTest.java index 925de9be..7078f15f 100644 --- a/ranger-core/src/test/java/io/appform/ranger/core/finder/serviceregistry/MapBasedServiceRegistryTest.java +++ b/ranger-core/src/test/java/io/appform/ranger/core/finder/serviceregistry/MapBasedServiceRegistryTest.java @@ -26,7 +26,7 @@ class MapBasedServiceRegistryTest { @Test - void testMapBasedServiceRegistryWithMatchingShardSelector(){ + void testMapBasedServiceRegistryWithMatchingShardSelector() { val serviceRegistry = RegistryTestUtils.getServiceRegistry(); Assertions.assertTrue(null != serviceRegistry.nodes() && !serviceRegistry.nodes().isEmpty()); val matchingShardSelector = new MatchingShardSelector(); diff --git a/ranger-core/src/test/java/io/appform/ranger/core/finder/shardselector/ListShardSelectorTest.java b/ranger-core/src/test/java/io/appform/ranger/core/finder/shardselector/ListShardSelectorTest.java index 900ae100..ade08886 100644 --- a/ranger-core/src/test/java/io/appform/ranger/core/finder/shardselector/ListShardSelectorTest.java +++ b/ranger-core/src/test/java/io/appform/ranger/core/finder/shardselector/ListShardSelectorTest.java @@ -25,7 +25,7 @@ class ListShardSelectorTest { @Test - void testListShardSelector(){ + void testListShardSelector() { val serviceRegistry = RegistryTestUtils.getUnshardedRegistry(); val shardSelector = new ListShardSelector(); val nodes = shardSelector.nodes(RangerTestUtils.getCriteria(1), serviceRegistry); diff --git a/ranger-core/src/test/java/io/appform/ranger/core/finder/shardselector/MatchingShardSelectorTest.java b/ranger-core/src/test/java/io/appform/ranger/core/finder/shardselector/MatchingShardSelectorTest.java index c2d4704b..4c76f8ff 100644 --- a/ranger-core/src/test/java/io/appform/ranger/core/finder/shardselector/MatchingShardSelectorTest.java +++ b/ranger-core/src/test/java/io/appform/ranger/core/finder/shardselector/MatchingShardSelectorTest.java @@ -25,7 +25,7 @@ class MatchingShardSelectorTest { @Test - void testMatchingShardSelector(){ + void testMatchingShardSelector() { val serviceRegistry = RegistryTestUtils.getServiceRegistry(); val shardSelector = new MatchingShardSelector(); val nodes = shardSelector.nodes( diff --git a/ranger-core/src/test/java/io/appform/ranger/core/finder/shardselector/NoopShardSelectorTest.java b/ranger-core/src/test/java/io/appform/ranger/core/finder/shardselector/NoopShardSelectorTest.java index 73012cd0..205e9ab2 100644 --- a/ranger-core/src/test/java/io/appform/ranger/core/finder/shardselector/NoopShardSelectorTest.java +++ b/ranger-core/src/test/java/io/appform/ranger/core/finder/shardselector/NoopShardSelectorTest.java @@ -26,7 +26,7 @@ class NoopShardSelectorTest { @Test - void testNoOpShardSelector(){ + void testNoOpShardSelector() { val serviceRegistry = RegistryTestUtils.getUnshardedRegistry(); val shardSelector = new NoopShardSelector(); val nodes = shardSelector.nodes(RangerTestUtils.getCriteria(1), serviceRegistry); diff --git a/ranger-core/src/test/java/io/appform/ranger/core/finderhub/ServiceFinderHubTest.java b/ranger-core/src/test/java/io/appform/ranger/core/finderhub/ServiceFinderHubTest.java index 3d1d1d36..1d3a99a5 100644 --- a/ranger-core/src/test/java/io/appform/ranger/core/finderhub/ServiceFinderHubTest.java +++ b/ranger-core/src/test/java/io/appform/ranger/core/finderhub/ServiceFinderHubTest.java @@ -24,7 +24,12 @@ import io.appform.ranger.core.finder.serviceregistry.MapBasedServiceRegistry; import io.appform.ranger.core.finder.shardselector.MatchingShardSelector; import io.appform.ranger.core.healthcheck.HealthcheckStatus; -import io.appform.ranger.core.model.*; +import io.appform.ranger.core.model.Deserializer; +import io.appform.ranger.core.model.NodeDataSource; +import io.appform.ranger.core.model.Service; +import io.appform.ranger.core.model.ServiceNode; +import io.appform.ranger.core.model.ServiceNodeSelector; +import io.appform.ranger.core.model.ShardSelector; import io.appform.ranger.core.units.TestNodeData; import io.appform.ranger.core.utils.RangerTestUtils; import lombok.val; @@ -88,18 +93,20 @@ void testTimeoutOnHubStartup() { @Test void testDelayedServiceAddition() { val delayedHub = new ServiceFinderHub<>(new DynamicDataSource(Lists.newArrayList(new Service("NS", "SERVICE"))), - service -> new TestServiceFinderBuilder() + service -> new TestServiceFinderBuilder() .withNamespace(service.getNamespace()) .withServiceName(service.getServiceName()) - .withDeserializer(new Deserializer() {}) + .withDeserializer(new Deserializer() { + }) .withSleepDuration(5) .build(), 1_000, 5_000, Set.of()); Assertions.assertThrows(IllegalStateException.class, delayedHub::start); val serviceFinderHub = new ServiceFinderHub<>(new DynamicDataSource(Lists.newArrayList(new Service("NS", "SERVICE"))), - service -> new TestServiceFinderBuilder() + service -> new TestServiceFinderBuilder() .withNamespace(service.getNamespace()) .withServiceName(service.getServiceName()) - .withDeserializer(new Deserializer() {}) + .withDeserializer(new Deserializer() { + }) .withSleepDuration(1) .build(), 5_000, 5_000, Set.of()); serviceFinderHub.start(); @@ -124,14 +131,15 @@ void testDynamicServiceAdditionWithNonDynamicDataSource() { } } - public class TestServiceFinderFactory implements ServiceFinderFactory> { + public class TestServiceFinderFactory implements ServiceFinderFactory> { @Override public ServiceFinder> buildFinder(Service service) { val finder = new TestServiceFinderBuilder() .withNamespace(service.getNamespace()) .withServiceName(service.getServiceName()) - .withDeserializer(new Deserializer() {}) + .withDeserializer(new Deserializer() { + }) .withSleepDuration(60) .build(); @@ -140,18 +148,19 @@ public ServiceFinder> buildF } } -private static class TestServiceFinderHubBuilder extends ServiceFinderHubBuilder> { + private static class TestServiceFinderHubBuilder extends ServiceFinderHubBuilder> { - @Override - protected void preBuild() { + @Override + protected void preBuild() { + // no-op + } + @Override + protected void postBuild(ServiceFinderHub> serviceFinderHub) { + // no-op + } } - @Override - protected void postBuild(ServiceFinderHub> serviceFinderHub) { - - } -} private static class TestServiceFinderBuilder extends BaseServiceFinderBuilder, ServiceFinder>, TestServiceFinderBuilder, Deserializer> { private int finderSleepDurationSeconds = 0; @@ -192,17 +201,17 @@ public Optional>> refresh(Deserializer extends Serializer { byte[] serialize(final ServiceNode node); } - static class TestSerializerImpl implements TestSerializer{ + static class TestSerializerImpl implements TestSerializer { private final ObjectMapper objectMapper; - public TestSerializerImpl(){ + public TestSerializerImpl() { objectMapper = new ObjectMapper(); } @Override public byte[] serialize(ServiceNode node) { - try{ + try { return objectMapper.writeValueAsBytes(node); - }catch (JsonProcessingException jpe){ + } catch (JsonProcessingException jpe) { return null; } } @@ -55,7 +55,8 @@ public byte[] serialize(ServiceNode node) { static class TestNodeDataSink> implements NodeDataSink { - public TestNodeDataSink(){ + public TestNodeDataSink() { + //no-op } @Override @@ -65,17 +66,17 @@ public void updateState(S serializer, ServiceNode serviceNode) { @Override public void start() { - + // no-op } @Override public void ensureConnected() { - + // no-op } @Override public void stop() { - + // no-op } @Override @@ -110,7 +111,7 @@ void testInvalidServiceProvider() { @Test void testInvalidServiceProviderNoHealthCheck() { - Assertions.assertThrowsExactly(IllegalArgumentException.class, () -> new TestServiceProviderBuilder<>() + Assertions.assertThrowsExactly(IllegalArgumentException.class, () -> new TestServiceProviderBuilder<>() .withServiceName("test-service") .withNamespace("test") .withHostname("localhost-1") diff --git a/ranger-core/src/test/java/io/appform/ranger/core/utils/RangerTestUtils.java b/ranger-core/src/test/java/io/appform/ranger/core/utils/RangerTestUtils.java index ecf2b075..e25e3099 100644 --- a/ranger-core/src/test/java/io/appform/ranger/core/utils/RangerTestUtils.java +++ b/ranger-core/src/test/java/io/appform/ranger/core/utils/RangerTestUtils.java @@ -33,16 +33,16 @@ @UtilityClass public class RangerTestUtils { - static String TEST_NAMESPACE = "test"; - static String TEST_SERVICE = "test-service"; + static final String TEST_NAMESPACE = "test"; + static final String TEST_SERVICE = "test-service"; //Visible outside the class scope public static Service service = Service.builder().namespace(TEST_NAMESPACE).serviceName(TEST_SERVICE).build(); - public static Predicate getCriteria(final int shardId){ + public static Predicate getCriteria(final int shardId) { return nodeData -> nodeData.getShardId() == shardId; } - public static Service getService(String namespace, String serviceName){ + public static Service getService(String namespace, String serviceName) { return Service.builder() .serviceName(serviceName) .namespace(namespace) @@ -73,7 +73,7 @@ public static void sleepUntil(int numSeconds, Callable conditionEvaluat /* Only applicable for initial node population using finder. Works when you intend to start the finder with nodes in 'em. */ - public static > void sleepUntilFinderStarts(ServiceFinder finder){ + public static > void sleepUntilFinderStarts(ServiceFinder finder) { await().pollDelay(Duration.ofSeconds(3)).until(() -> finder.getServiceRegistry().isRefreshed()); } } diff --git a/ranger-core/src/test/java/io/appform/ranger/core/utils/RegistryTestUtils.java b/ranger-core/src/test/java/io/appform/ranger/core/utils/RegistryTestUtils.java index 80887488..8a83cca3 100644 --- a/ranger-core/src/test/java/io/appform/ranger/core/utils/RegistryTestUtils.java +++ b/ranger-core/src/test/java/io/appform/ranger/core/utils/RegistryTestUtils.java @@ -15,7 +15,6 @@ */ package io.appform.ranger.core.utils; -import com.google.common.collect.ImmutableList; import io.appform.ranger.core.finder.serviceregistry.ListBasedServiceRegistry; import io.appform.ranger.core.finder.serviceregistry.MapBasedServiceRegistry; import io.appform.ranger.core.model.ServiceNode; @@ -23,12 +22,14 @@ import lombok.experimental.UtilityClass; import lombok.val; +import java.util.List; + @UtilityClass public class RegistryTestUtils { - public static MapBasedServiceRegistry getServiceRegistry(){ + public static MapBasedServiceRegistry getServiceRegistry() { val serviceRegistry = new MapBasedServiceRegistry(RangerTestUtils.service); - val serviceNodes = ImmutableList.of( + val serviceNodes = List.of( ServiceNode.builder().host("localhost-1").port(9000).nodeData(TestNodeData.builder().shardId(1).build()).build(), ServiceNode.builder().host("localhost-2").port(9001).nodeData(TestNodeData.builder().shardId(2).build()).build(), ServiceNode.builder().host("localhost-3").port(9002).nodeData(TestNodeData.builder().shardId(3).build()).build() @@ -37,9 +38,9 @@ public static MapBasedServiceRegistry getServiceRegistry(){ return serviceRegistry; } - public static ListBasedServiceRegistry getUnshardedRegistry(){ + public static ListBasedServiceRegistry getUnshardedRegistry() { val serviceRegistry = new ListBasedServiceRegistry(RangerTestUtils.service); - val serviceNodes = ImmutableList.of( + val serviceNodes = List.of( ServiceNode.builder().host("localhost-1").port(9000).nodeData(TestNodeData.builder().shardId(1).build()).build(), ServiceNode.builder().host("localhost-2").port(9001).nodeData(TestNodeData.builder().shardId(2).build()).build(), ServiceNode.builder().host("localhost-3").port(9002).nodeData(TestNodeData.builder().shardId(3).build()).build() diff --git a/ranger-core/src/test/resources/logback.xml b/ranger-core/src/test/resources/logback.xml index 50ab1e2f..ea426e61 100644 --- a/ranger-core/src/test/resources/logback.xml +++ b/ranger-core/src/test/resources/logback.xml @@ -23,13 +23,13 @@ - + - + - - + + \ No newline at end of file diff --git a/ranger-discovery-bundle-dw5/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerate.json b/ranger-discovery-bundle-dw5/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerate.json new file mode 100644 index 00000000..1a38dbac --- /dev/null +++ b/ranger-discovery-bundle-dw5/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerate.json @@ -0,0 +1,8 @@ +{ + "name": "io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerate", + "mode": "Throughput", + "iterations": 4, + "threads": 1, + "forks": 3, + "mean_ops": 983207.6911013111 +} \ No newline at end of file diff --git a/ranger-discovery-bundle-dw5/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerateBase36.json b/ranger-discovery-bundle-dw5/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerateBase36.json new file mode 100644 index 00000000..69a6de05 --- /dev/null +++ b/ranger-discovery-bundle-dw5/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerateBase36.json @@ -0,0 +1,8 @@ +{ + "name": "io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerateBase36", + "mode": "Throughput", + "iterations": 4, + "threads": 1, + "forks": 3, + "mean_ops": 915820.4865429945 +} \ No newline at end of file diff --git a/ranger-discovery-bundle-dw5/pom.xml b/ranger-discovery-bundle-dw5/pom.xml new file mode 100644 index 00000000..bee877cb --- /dev/null +++ b/ranger-discovery-bundle-dw5/pom.xml @@ -0,0 +1,98 @@ + + + + + + ranger + io.appform.ranger + 2.0.0-SNAPSHOT + + 4.0.0 + + ranger-discovery-bundle-dw5 + Dropwizard 5.x bundle for Ranger discovery + + + 1.8.1 + 5.0.0 + + + + + + io.dropwizard + dropwizard-bom + ${dropwizard.version} + pom + import + + + + + + + io.dropwizard + dropwizard-core + provided + + + io.dropwizard + dropwizard-jackson + provided + + + org.apache.curator + curator-test + ${curator.version} + test + + + org.mockito + mockito-core + ${mockito.version} + test + + + io.appform.ranger + ranger-discovery-common + ${project.version} + + + io.appform.ranger + ranger-zk-client + ${project.version} + + + io.appform.ranger + ranger-server-common + ${project.version} + + + io.appform.ranger + ranger-id + ${project.version} + + + com.alibaba + dns-cache-manipulator + ${dns.cache.manipulator.version} + test + + + diff --git a/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/Constants.java b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/Constants.java new file mode 100644 index 00000000..147207c0 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/Constants.java @@ -0,0 +1,36 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle; + +import com.google.common.collect.ImmutableSet; +import lombok.experimental.UtilityClass; + +import java.util.Set; + +/** + * Constants + */ +@UtilityClass +public class Constants { + public static final String DEFAULT_NAMESPACE = "default"; + public static final String DEFAULT_HOST = "__DEFAULT_SERVICE_HOST"; + + public static final int DEFAULT_PORT = -1; + public static final int DEFAULT_DW_CHECK_INTERVAL = 15; + public static final Set LOCAL_ADDRESSES = ImmutableSet.of("127.0.0.1", "127.0.1.1", "localhost"); + +} diff --git a/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/InfoResource.java b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/InfoResource.java new file mode 100644 index 00000000..c7059716 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/InfoResource.java @@ -0,0 +1,45 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle; + +import io.appform.ranger.client.RangerClient; +import io.appform.ranger.common.server.ShardInfo; +import io.appform.ranger.core.finder.serviceregistry.MapBasedServiceRegistry; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + + +/** + * Given information about the cluster. + */ +@Produces(MediaType.APPLICATION_JSON) +@Path("/instances") +public class InfoResource { + private final RangerClient> serviceDiscoveryClient; + + public InfoResource(RangerClient> serviceDiscoveryClient) { + this.serviceDiscoveryClient = serviceDiscoveryClient; + } + + @GET + public Response get() { + return Response.ok(serviceDiscoveryClient.getAllNodes()).build(); + } +} diff --git a/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundle.java b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundle.java new file mode 100644 index 00000000..4b2b0c26 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundle.java @@ -0,0 +1,334 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import io.appform.ranger.client.RangerClient; +import io.appform.ranger.client.zk.SimpleRangerZKClient; +import io.appform.ranger.common.server.ShardInfo; +import io.appform.ranger.core.finder.serviceregistry.MapBasedServiceRegistry; +import io.appform.ranger.core.healthcheck.Healthcheck; +import io.appform.ranger.core.healthcheck.HealthcheckStatus; +import io.appform.ranger.core.healthservice.TimeEntity; +import io.appform.ranger.core.healthservice.monitor.IsolatedHealthMonitor; +import io.appform.ranger.core.model.ServiceNode; +import io.appform.ranger.core.model.ShardSelector; +import io.appform.ranger.core.serviceprovider.ServiceProvider; +import io.appform.ranger.discovery.bundle.monitors.DropwizardServerStartupCheck; +import io.appform.ranger.discovery.bundle.resolvers.DefaultPortSchemeResolver; +import io.appform.ranger.discovery.bundle.resolvers.PortSchemeResolver; +import io.appform.ranger.discovery.bundle.rotationstatus.BIRTask; +import io.appform.ranger.discovery.bundle.rotationstatus.OORTask; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.healthchecks.InitialDelayChecker; +import io.appform.ranger.discovery.common.healthchecks.InternalHealthChecker; +import io.appform.ranger.discovery.common.healthchecks.RotationCheck; +import io.appform.ranger.discovery.common.monitors.DropwizardHealthMonitor; +import io.appform.ranger.discovery.common.resolvers.DefaultNodeInfoResolver; +import io.appform.ranger.discovery.common.resolvers.NodeInfoResolver; +import io.appform.ranger.discovery.common.rotationstatus.DropwizardServerStatus; +import io.appform.ranger.discovery.common.rotationstatus.RotationStatus; +import io.appform.ranger.discovery.common.selectors.HierarchicalEnvironmentAwareShardSelector; +import io.appform.ranger.discovery.common.util.ConfigurationUtils; +import io.appform.ranger.id.IdGenerator; +import io.appform.ranger.id.NodeIdManager; +import io.appform.ranger.id.constraints.IdValidationConstraint; +import io.appform.ranger.zookeeper.ServiceProviderBuilders; +import io.appform.ranger.zookeeper.serde.ZkNodeDataSerializer; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.ConfiguredBundle; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.lifecycle.Managed; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.retry.RetryForever; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static io.appform.ranger.discovery.bundle.Constants.LOCAL_ADDRESSES; + + +/** + * A dropwizard bundle for service discovery. + */ +@SuppressWarnings("unused") +@Slf4j +public abstract class ServiceDiscoveryBundle implements ConfiguredBundle { + + private final List healthchecks = Lists.newArrayList(); + private final List globalIdConstraints; + private ServiceDiscoveryConfiguration serviceDiscoveryConfiguration; + private ServiceProvider> serviceProvider; + + @Getter + private CuratorFramework curator; + @Getter + private RangerClient> serviceDiscoveryClient; + @Getter + @VisibleForTesting + private RotationStatus rotationStatus; + @Getter + @VisibleForTesting + private DropwizardServerStatus serverStatus; + + protected ServiceDiscoveryBundle() { + globalIdConstraints = Collections.emptyList(); + } + + protected ServiceDiscoveryBundle(List globalIdConstraints) { + this.globalIdConstraints = globalIdConstraints != null + ? globalIdConstraints + : Collections.emptyList(); + } + + @Override + public void initialize(Bootstrap bootstrap) { + + } + + @Override + public void run(T configuration, + Environment environment) throws Exception { + val portSchemeResolver = createPortSchemeResolver(); + Preconditions.checkNotNull(portSchemeResolver, "Port scheme resolver can't be null"); + val portScheme = portSchemeResolver.resolve(configuration); + serviceDiscoveryConfiguration = getRangerConfiguration(configuration); + val objectMapper = environment.getObjectMapper(); + val namespace = serviceDiscoveryConfiguration.getNamespace(); + val serviceName = getServiceName(configuration); + val hostname = getHost(); + val port = getPort(configuration); + val initialCriteria = getInitialCriteria(configuration); + val useInitialCriteria = alwaysMergeWithInitialCriteria(configuration); + val shardSelector = getShardSelector(configuration); + rotationStatus = new RotationStatus(serviceDiscoveryConfiguration.isInitialRotationStatus()); + serverStatus = new DropwizardServerStatus(false); + curator = CuratorFrameworkFactory.builder() + .connectString(serviceDiscoveryConfiguration.getZookeeper()) + .namespace(namespace) + .retryPolicy(new RetryForever(serviceDiscoveryConfiguration.getConnectionRetryIntervalMillis())) + .build(); + serviceProvider = buildServiceProvider(environment, objectMapper, namespace, serviceName, hostname, port, + portScheme); + serviceDiscoveryClient = buildDiscoveryClient(environment, namespace, serviceName, initialCriteria, + useInitialCriteria, shardSelector); + environment.lifecycle() + .manage(new ServiceDiscoveryManager(serviceName)); + environment.jersey() + .register(new InfoResource(serviceDiscoveryClient)); + environment.admin() + .addTask(new OORTask(rotationStatus)); + environment.admin() + .addTask(new BIRTask(rotationStatus)); + } + + protected ShardSelector> getShardSelector(T configuration) { + return new HierarchicalEnvironmentAwareShardSelector(getRangerConfiguration(configuration).getEnvironment()); + } + + protected abstract ServiceDiscoveryConfiguration getRangerConfiguration(T configuration); + + protected abstract String getServiceName(T configuration); + + protected NodeInfoResolver createNodeInfoResolver() { + return new DefaultNodeInfoResolver(); + } + + protected PortSchemeResolver createPortSchemeResolver() { + return new DefaultPortSchemeResolver<>(); + } + + /** + * Override the following if you require. + **/ + protected Predicate getInitialCriteria(T configuration) { + return shardInfo -> true; + } + + protected boolean alwaysMergeWithInitialCriteria(T configuration) { + return false; + } + + protected List> getHealthMonitors() { + return Collections.emptyList(); + } + + @SuppressWarnings("unused") + protected int getPort(T configuration) { + Preconditions.checkArgument(Constants.DEFAULT_PORT != serviceDiscoveryConfiguration.getPublishedPort() + && 0 != serviceDiscoveryConfiguration.getPublishedPort(), + "Looks like publishedPost has not been set and getPort() has not been overridden. This is wrong. \n" + + "Either set publishedPort in config or override getPort() to return the port on which the service is running"); + return serviceDiscoveryConfiguration.getPublishedPort(); + } + + protected String getHost() throws UnknownHostException { + val host = ConfigurationUtils.resolveNonEmptyPublishedHost(serviceDiscoveryConfiguration.getPublishedHost()); + + val publishedHostAddress = InetAddress.getByName(host) + .getHostAddress(); + + val zkHostAddresses = ConfigurationUtils.resolveZookeeperHosts(serviceDiscoveryConfiguration.getZookeeper()) + .stream() + .map(zkHost -> { + try { + return InetAddress.getByName(zkHost) + .getHostAddress(); + } catch (UnknownHostException e) { + throw new IllegalArgumentException( + String.format("Couldn't resolve host address for zkHost : %s", zkHost), e); + } + }) + .collect(Collectors.toSet()); + + Preconditions.checkArgument( + !LOCAL_ADDRESSES.contains(publishedHostAddress) || LOCAL_ADDRESSES.containsAll(zkHostAddresses), + "Not allowed to publish localhost address to remote zookeeper"); + + return host; + } + + public void registerHealthcheck(Healthcheck healthcheck) { + this.healthchecks.add(healthcheck); + } + + public void registerHealthchecks(List healthchecks) { + this.healthchecks.addAll(healthchecks); + } + + + private RangerClient> buildDiscoveryClient(Environment environment, + String namespace, + String serviceName, + Predicate initialCriteria, + boolean mergeWithInitialCriteria, + ShardSelector> shardSelector) { + return SimpleRangerZKClient.builder() + .curatorFramework(curator) + .namespace(namespace) + .serviceName(serviceName) + .mapper(environment.getObjectMapper()) + .nodeRefreshIntervalMs(serviceDiscoveryConfiguration.getRefreshTimeMs()) + .disableWatchers(serviceDiscoveryConfiguration.isDisableWatchers()) + .deserializer(data -> { + try { + return environment.getObjectMapper() + .readValue(data, new TypeReference>() { + }); + } catch (IOException e) { + log.warn("Error parsing node data with value {} for service: {}", new String(data), serviceName); + } + return null; + }) + .initialCriteria(initialCriteria) + .alwaysUseInitialCriteria(mergeWithInitialCriteria) + .shardSelector(shardSelector) + .build(); + } + + private ServiceProvider> buildServiceProvider(Environment environment, + ObjectMapper objectMapper, + String namespace, + String serviceName, + String hostname, + int port, + String portScheme) { + val nodeInfoResolver = createNodeInfoResolver(); + val nodeInfo = nodeInfoResolver.resolve(serviceDiscoveryConfiguration); + val initialDelayForMonitor = serviceDiscoveryConfiguration.getInitialDelaySeconds() > 1 + ? serviceDiscoveryConfiguration.getInitialDelaySeconds() - 1 + : 0; + val dwMonitoringInterval = serviceDiscoveryConfiguration.getDropwizardCheckInterval() == 0 + ? Constants.DEFAULT_DW_CHECK_INTERVAL + : serviceDiscoveryConfiguration.getDropwizardCheckInterval(); + val dwMonitoringStaleness = Math.max(serviceDiscoveryConfiguration.getDropwizardCheckStaleness(), + dwMonitoringInterval + 1); + val serviceProviderBuilder = ServiceProviderBuilders.shardedServiceProviderBuilder() + .withCuratorFramework(curator) + .withNamespace(namespace) + .withServiceName(serviceName) + .withSerializer(data -> { + try { + return objectMapper.writeValueAsBytes(data); + } catch (Exception e) { + log.warn("Could not parse node data", e); + } + return null; + }) + .withPortScheme(portScheme) + .withNodeData(nodeInfo) + .withHostname(hostname) + .withPort(port) + .withHealthcheck(new InternalHealthChecker(healthchecks)) + .withHealthcheck(new RotationCheck(rotationStatus)) + .withHealthcheck(new InitialDelayChecker(serviceDiscoveryConfiguration.getInitialDelaySeconds())) + .withHealthcheck(new DropwizardServerStartupCheck(environment, serverStatus)) + .withIsolatedHealthMonitor(new DropwizardHealthMonitor( + new TimeEntity(initialDelayForMonitor, dwMonitoringInterval, TimeUnit.SECONDS), + dwMonitoringStaleness * 1_000L, environment.healthChecks())) + .withHealthUpdateIntervalMs(serviceDiscoveryConfiguration.getRefreshTimeMs()) + .withStaleUpdateThresholdMs(10000); + + val healthMonitors = getHealthMonitors(); + if (healthMonitors != null && !healthMonitors.isEmpty()) { + healthMonitors.forEach(serviceProviderBuilder::withIsolatedHealthMonitor); + } + return serviceProviderBuilder.build(); + } + + @AllArgsConstructor + private class ServiceDiscoveryManager implements Managed { + + private final String serviceName; + + @Override + public void start() { + log.debug("Starting the discovery manager"); + curator.start(); + serviceProvider.start(); + serviceDiscoveryClient.start(); + val nodeIdManager = new NodeIdManager(curator, serviceName); + IdGenerator.initialize(nodeIdManager.fixNodeId(), globalIdConstraints, Collections.emptyMap()); + log.debug("Discovery manager has been successfully started."); + } + + @Override + public void stop() { + serviceDiscoveryClient.stop(); + serviceProvider.stop(); + curator.close(); + IdGenerator.cleanUp(); + } + } + +} diff --git a/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/monitors/DropwizardServerStartupCheck.java b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/monitors/DropwizardServerStartupCheck.java new file mode 100644 index 00000000..bccb36c9 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/monitors/DropwizardServerStartupCheck.java @@ -0,0 +1,46 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle.monitors; + +import io.appform.ranger.core.healthcheck.Healthcheck; +import io.appform.ranger.core.healthcheck.HealthcheckStatus; +import io.appform.ranger.discovery.common.rotationstatus.DropwizardServerStatus; +import io.dropwizard.core.setup.Environment; +import lombok.extern.slf4j.Slf4j; + +/** + * This healthcheck listens to server started event to mark service healthy on ranger. + */ +@Slf4j +public class DropwizardServerStartupCheck implements Healthcheck { + + private final DropwizardServerStatus serverStatus; + + public DropwizardServerStartupCheck(Environment environment, + DropwizardServerStatus serverStatus) { + this.serverStatus = serverStatus; + environment.lifecycle().addServerLifecycleListener(server -> { + log.info("Dropwizard server started. Marking healthcheck as healthy"); + serverStatus.markStarted(); + }); + } + + @Override + public HealthcheckStatus check() { + return serverStatus.started() ? HealthcheckStatus.healthy : HealthcheckStatus.unhealthy; + } +} diff --git a/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/resolvers/DefaultPortSchemeResolver.java b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/resolvers/DefaultPortSchemeResolver.java new file mode 100644 index 00000000..b908c3b9 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/resolvers/DefaultPortSchemeResolver.java @@ -0,0 +1,62 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.discovery.bundle.resolvers; + +import io.appform.ranger.core.model.PortSchemes; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.server.DefaultServerFactory; +import io.dropwizard.core.server.ServerFactory; +import io.dropwizard.core.server.SimpleServerFactory; +import io.dropwizard.jetty.ConnectorFactory; +import io.dropwizard.jetty.HttpsConnectorFactory; +import lombok.val; + +import java.util.Optional; + +/** + * DefaultPortSchemeResolver.java + * To derive PortScheme from the ServerFactory from Dropwizard startup config + */ +public class DefaultPortSchemeResolver implements PortSchemeResolver { + + /** + * Returns a PortScheme basis the configuration. The default in case of a new + * Connector found (Possibly on version upgrades, if we have forgotten mutate it, + * is HTTP) + * + * @param configuration {@link Configuration} the dropwizard startup config + * @return {@link String} The relevant portScheme with HTTP as default + */ + @Override + public String resolve(T configuration) { + val connectionFactory = getConnectorFactory(configuration.getServerFactory()); + return connectionFactory.filter(HttpsConnectorFactory.class::isInstance) + .map(factory -> PortSchemes.HTTPS) + .orElse(PortSchemes.HTTP); + } + + private Optional getConnectorFactory(ServerFactory serverFactory) { + if (serverFactory instanceof DefaultServerFactory defaultFactory) { + return defaultFactory.getApplicationConnectors() + .stream() + .findFirst(); + } else if (serverFactory instanceof SimpleServerFactory defaultFactory) { + return Optional.ofNullable(defaultFactory.getConnector()); + } else { + return Optional.empty(); + } + } +} diff --git a/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/resolvers/PortSchemeResolver.java b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/resolvers/PortSchemeResolver.java new file mode 100644 index 00000000..adfedb69 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/resolvers/PortSchemeResolver.java @@ -0,0 +1,29 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.discovery.bundle.resolvers; + +import io.appform.ranger.discovery.common.resolvers.CriteriaResolver; +import io.dropwizard.core.Configuration; + + +/** + * NodeInfoResolver.java + * Interface to help build a portScheme basis the server {@link Configuration} + */ +@FunctionalInterface +public interface PortSchemeResolver extends CriteriaResolver { + +} diff --git a/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/BIRTask.java b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/BIRTask.java new file mode 100644 index 00000000..44619deb --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/BIRTask.java @@ -0,0 +1,45 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle.rotationstatus; + + +import io.appform.ranger.discovery.common.rotationstatus.RotationStatus; +import io.dropwizard.servlets.tasks.Task; +import lombok.extern.slf4j.Slf4j; + +import java.io.PrintWriter; +import java.util.List; +import java.util.Map; + +/** + * Admin task to take node bir in ranger + */ +@Slf4j +public class BIRTask extends Task { + private final RotationStatus rotationStatus; + + public BIRTask(RotationStatus rotationStatus) { + super("ranger-bir"); + this.rotationStatus = rotationStatus; + } + + @Override + public void execute(Map> map, PrintWriter printWriter) { + rotationStatus.bir(); + log.info("Taking node back into rotation on ranger"); + } +} diff --git a/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/OORTask.java b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/OORTask.java new file mode 100644 index 00000000..1913bf52 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/OORTask.java @@ -0,0 +1,44 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle.rotationstatus; + +import io.appform.ranger.discovery.common.rotationstatus.RotationStatus; +import io.dropwizard.servlets.tasks.Task; +import lombok.extern.slf4j.Slf4j; + +import java.io.PrintWriter; +import java.util.List; +import java.util.Map; + +/** + * Admin task to take node oor in ranger + */ +@Slf4j +public class OORTask extends Task { + private final RotationStatus rotationStatus; + + public OORTask(RotationStatus rotationStatus) { + super("ranger-oor"); + this.rotationStatus = rotationStatus; + } + + @Override + public void execute(Map> map, PrintWriter printWriter) { + rotationStatus.oor(); + log.info("Taking node out of rotation on ranger"); + } +} diff --git a/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleCustomHostPortTest.java b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleCustomHostPortTest.java new file mode 100644 index 00000000..9b0aa475 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleCustomHostPortTest.java @@ -0,0 +1,151 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle; + +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.health.HealthCheckRegistry; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Lists; +import io.appform.ranger.core.healthcheck.HealthcheckStatus; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.server.DefaultServerFactory; +import io.dropwizard.core.setup.AdminEnvironment; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.jersey.DropwizardResourceConfig; +import io.dropwizard.jersey.setup.JerseyEnvironment; +import io.dropwizard.jetty.ConnectorFactory; +import io.dropwizard.jetty.HttpConnectorFactory; +import io.dropwizard.lifecycle.setup.LifecycleEnvironment; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.apache.curator.test.TestingCluster; +import org.eclipse.jetty.util.component.LifeCycle; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static io.appform.ranger.discovery.bundle.TestUtils.assertNodeAbsence; +import static io.appform.ranger.discovery.bundle.TestUtils.assertNodePresence; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +@Slf4j +class ServiceDiscoveryBundleCustomHostPortTest { + + private final HealthCheckRegistry healthChecks = mock(HealthCheckRegistry.class); + private final JerseyEnvironment jerseyEnvironment = mock(JerseyEnvironment.class); + private final MetricRegistry metricRegistry = mock(MetricRegistry.class); + private final LifecycleEnvironment lifecycleEnvironment = new LifecycleEnvironment(metricRegistry); + private final Environment environment = mock(Environment.class); + private final Bootstrap bootstrap = mock(Bootstrap.class); + private final Configuration configuration = mock(Configuration.class); + private final DefaultServerFactory serverFactory = mock(DefaultServerFactory.class); + private final ConnectorFactory connectorFactory = mock(HttpConnectorFactory.class); + private final TestingCluster testingCluster = new TestingCluster(1); + private ServiceDiscoveryConfiguration serviceDiscoveryConfiguration; + private final ServiceDiscoveryBundle bundle = new ServiceDiscoveryBundle() { + @Override + protected ServiceDiscoveryConfiguration getRangerConfiguration(Configuration configuration) { + return serviceDiscoveryConfiguration; + } + + @Override + protected String getServiceName(Configuration configuration) { + return "TestService"; + } + + @Override + protected int getPort(Configuration configuration) { + return 21000; + } + + @Override + protected String getHost() { + return "CustomHost"; + } + + }; + private HealthcheckStatus status = HealthcheckStatus.healthy; + + @BeforeEach + void setup() throws Exception { + when(serverFactory.getApplicationConnectors()).thenReturn(Lists.newArrayList(connectorFactory)); + when(configuration.getServerFactory()).thenReturn(serverFactory); + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.getObjectMapper()).thenReturn(new ObjectMapper()); + AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment) + .addTask(any()); + when(environment.admin()).thenReturn(adminEnvironment); + + testingCluster.start(); + + serviceDiscoveryConfiguration = ServiceDiscoveryConfiguration.builder() + .zookeeper(testingCluster.getConnectString()) + .namespace("test") + .environment("testing") + .connectionRetryIntervalMillis(5000) + .publishedHost("TestHost") + .publishedPort(8021) + .initialRotationStatus(true) + .build(); + bundle.initialize(bootstrap); + bundle.run(configuration, environment); + bundle.getServerStatus() + .markStarted(); + for (LifeCycle lifeCycle : lifecycleEnvironment.getManagedObjects()) { + lifeCycle.start(); + } + bundle.registerHealthcheck(() -> status); + + } + + @AfterEach + void tearDown() throws Exception { + for (LifeCycle lifeCycle : lifecycleEnvironment.getManagedObjects()) { + lifeCycle.stop(); + } + testingCluster.stop(); + } + + @Test + void testDiscovery() { + assertNodePresence(bundle); + val info = bundle.getServiceDiscoveryClient() + .getNode() + .orElse(null); + + Assertions.assertNotNull(info); + Assertions.assertNotNull(info.getNodeData()); + Assertions.assertEquals("testing", info.getNodeData() + .getEnvironment()); + Assertions.assertEquals("CustomHost", info.getHost()); + Assertions.assertEquals(21000, info.getPort()); + status = HealthcheckStatus.unhealthy; + + assertNodeAbsence(bundle); + } +} \ No newline at end of file diff --git a/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwMonitorTest.java b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwMonitorTest.java new file mode 100644 index 00000000..a6cf7efa --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwMonitorTest.java @@ -0,0 +1,168 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle; + +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.health.HealthCheck; +import com.codahale.metrics.health.HealthCheckRegistry; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Lists; +import io.appform.ranger.core.healthcheck.HealthcheckStatus; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.server.DefaultServerFactory; +import io.dropwizard.core.setup.AdminEnvironment; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.jersey.DropwizardResourceConfig; +import io.dropwizard.jersey.setup.JerseyEnvironment; +import io.dropwizard.jetty.ConnectorFactory; +import io.dropwizard.jetty.HttpConnectorFactory; +import io.dropwizard.lifecycle.setup.LifecycleEnvironment; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.apache.curator.test.TestingCluster; +import org.eclipse.jetty.util.component.LifeCycle; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.atomic.AtomicInteger; + +import static io.appform.ranger.discovery.bundle.TestUtils.assertNodeAbsence; +import static io.appform.ranger.discovery.bundle.TestUtils.assertNodePresence; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +@Slf4j +class ServiceDiscoveryBundleDwMonitorTest { + + private final HealthCheckRegistry healthChecks = new HealthCheckRegistry(); + private final JerseyEnvironment jerseyEnvironment = mock(JerseyEnvironment.class); + private final MetricRegistry metricRegistry = mock(MetricRegistry.class); + private final LifecycleEnvironment lifecycleEnvironment = new LifecycleEnvironment(metricRegistry); + private final Environment environment = mock(Environment.class); + private final Bootstrap bootstrap = mock(Bootstrap.class); + private final Configuration configuration = mock(Configuration.class); + private final DefaultServerFactory serverFactory = mock(DefaultServerFactory.class); + private final ConnectorFactory connectorFactory = mock(HttpConnectorFactory.class); + private final TestingCluster testingCluster = new TestingCluster(1); + private final HealthcheckStatus status = HealthcheckStatus.healthy; + private ServiceDiscoveryConfiguration serviceDiscoveryConfiguration; + private final ServiceDiscoveryBundle bundle = new ServiceDiscoveryBundle() { + @Override + protected ServiceDiscoveryConfiguration getRangerConfiguration(Configuration configuration) { + return serviceDiscoveryConfiguration; + } + + @Override + protected String getServiceName(Configuration configuration) { + return "TestService"; + } + + @Override + protected int getPort(Configuration configuration) { + return 21000; + } + + @Override + protected String getHost() { + return "CustomHost"; + } + + }; + + @BeforeEach + void setup() throws Exception { + healthChecks.register("twice-healthy-only", new HealthCheck() { + private final AtomicInteger counter = new AtomicInteger(5); + + @Override + protected Result check() { + val result = (counter.decrementAndGet() < 0) + ? Result.unhealthy("unhealthy") + : Result.healthy(); + log.info("Marking node as {}", result.isHealthy()); + return result; + } + }); + + when(serverFactory.getApplicationConnectors()).thenReturn(Lists.newArrayList(connectorFactory)); + when(configuration.getServerFactory()).thenReturn(serverFactory); + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.getObjectMapper()).thenReturn(new ObjectMapper()); + AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment) + .addTask(any()); + when(environment.admin()).thenReturn(adminEnvironment); + + testingCluster.start(); + + serviceDiscoveryConfiguration = ServiceDiscoveryConfiguration.builder() + .zookeeper(testingCluster.getConnectString()) + .namespace("test") + .environment("testing") + .connectionRetryIntervalMillis(5000) + .publishedHost("TestHost") + .publishedPort(8021) + .initialRotationStatus(true) + .dropwizardCheckInterval(2) + .dropwizardCheckStaleness(2) + .build(); + bundle.initialize(bootstrap); + bundle.run(configuration, environment); + bundle.getServerStatus() + .markStarted(); + for (LifeCycle lifeCycle : lifecycleEnvironment.getManagedObjects()) { + lifeCycle.start(); + } + bundle.registerHealthcheck(() -> status); + } + + @AfterEach + void tearDown() throws Exception { + for (LifeCycle lifeCycle : lifecycleEnvironment.getManagedObjects()) { + lifeCycle.stop(); + } + testingCluster.stop(); + } + + @Test + void testDiscovery() { + assertNodePresence(bundle); + val info = bundle.getServiceDiscoveryClient() + .getNode() + .orElse(null); + Assertions.assertNotNull(info); + Assertions.assertNotNull(info.getNodeData()); + Assertions.assertEquals("testing", info.getNodeData() + .getEnvironment()); + Assertions.assertEquals("CustomHost", info.getHost()); + Assertions.assertEquals(21000, info.getPort()); + + /* after 5 turns, the healthcheck will return unhealthy, and since dropwizardCheckInterval + is 5 seconds, within 2*5=10 seconds, nodes should be absent */ + assertNodeAbsence(bundle); + } +} \ No newline at end of file diff --git a/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwStalenessMonitorTest.java b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwStalenessMonitorTest.java new file mode 100644 index 00000000..b4120c1c --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwStalenessMonitorTest.java @@ -0,0 +1,171 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle; + +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.health.HealthCheck; +import com.codahale.metrics.health.HealthCheckRegistry; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Lists; +import io.appform.ranger.core.healthcheck.HealthcheckStatus; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.server.DefaultServerFactory; +import io.dropwizard.core.setup.AdminEnvironment; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.jersey.DropwizardResourceConfig; +import io.dropwizard.jersey.setup.JerseyEnvironment; +import io.dropwizard.jetty.ConnectorFactory; +import io.dropwizard.jetty.HttpConnectorFactory; +import io.dropwizard.lifecycle.setup.LifecycleEnvironment; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.apache.curator.test.TestingCluster; +import org.eclipse.jetty.util.component.LifeCycle; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.atomic.AtomicBoolean; + +import static io.appform.ranger.discovery.bundle.TestUtils.assertNodeAbsence; +import static io.appform.ranger.discovery.bundle.TestUtils.assertNodePresence; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +@Slf4j +class ServiceDiscoveryBundleDwStalenessMonitorTest { + + private final HealthCheckRegistry healthChecks = new HealthCheckRegistry(); + private final JerseyEnvironment jerseyEnvironment = mock(JerseyEnvironment.class); + private final MetricRegistry metricRegistry = mock(MetricRegistry.class); + private final LifecycleEnvironment lifecycleEnvironment = new LifecycleEnvironment(metricRegistry); + private final Environment environment = mock(Environment.class); + private final Bootstrap bootstrap = mock(Bootstrap.class); + private final Configuration configuration = mock(Configuration.class); + private final DefaultServerFactory serverFactory = mock(DefaultServerFactory.class); + private final ConnectorFactory connectorFactory = mock(HttpConnectorFactory.class); + private final TestingCluster testingCluster = new TestingCluster(1); + private final AtomicBoolean healthySucceeded = new AtomicBoolean(false); + private ServiceDiscoveryConfiguration serviceDiscoveryConfiguration; + private final ServiceDiscoveryBundle bundle = new ServiceDiscoveryBundle() { + @Override + protected ServiceDiscoveryConfiguration getRangerConfiguration(Configuration configuration) { + return serviceDiscoveryConfiguration; + } + + @Override + protected String getServiceName(Configuration configuration) { + return "TestService"; + } + + @Override + protected int getPort(Configuration configuration) { + return 21000; + } + + @Override + protected String getHost() { + return "CustomHost"; + } + + }; + + @BeforeEach + void setup() throws Exception { + healthChecks.register("healthy-once-but-then-sleep5", new HealthCheck() { + + @Override + protected Result check() { + if (healthySucceeded.get()) { + return Result.unhealthy("Forced unhealthy as healthy check has succeeded"); + } + return Result.healthy(); + } + }); + + when(serverFactory.getApplicationConnectors()).thenReturn(Lists.newArrayList(connectorFactory)); + when(configuration.getServerFactory()).thenReturn(serverFactory); + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.getObjectMapper()).thenReturn(new ObjectMapper()); + AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment) + .addTask(any()); + when(environment.admin()).thenReturn(adminEnvironment); + + testingCluster.start(); + + serviceDiscoveryConfiguration = ServiceDiscoveryConfiguration.builder() + .zookeeper(testingCluster.getConnectString()) + .namespace("test") + .environment("testing") + .connectionRetryIntervalMillis(5000) + .publishedHost("TestHost") + .publishedPort(8021) + .initialRotationStatus(true) + .dropwizardCheckInterval(6) + .dropwizardCheckStaleness(6) + .build(); + bundle.initialize(bootstrap); + bundle.run(configuration, environment); + bundle.getServerStatus() + .markStarted(); + for (LifeCycle lifeCycle : lifecycleEnvironment.getManagedObjects()) { + lifeCycle.start(); + } + bundle.registerHealthcheck(() -> HealthcheckStatus.healthy); + } + + @AfterEach + void tearDown() throws Exception { + for (LifeCycle lifeCycle : lifecycleEnvironment.getManagedObjects()) { + lifeCycle.stop(); + } + testingCluster.stop(); + } + + @Test + void testDiscovery() { + assertNodePresence(bundle); + val info = bundle.getServiceDiscoveryClient() + .getNode() + .orElse(null); + Assertions.assertNotNull(info); + Assertions.assertNotNull(info.getNodeData()); + Assertions.assertEquals("testing", info.getNodeData() + .getEnvironment()); + Assertions.assertEquals("CustomHost", info.getHost()); + Assertions.assertEquals(21000, info.getPort()); + healthySucceeded.set(true); + + /* once the first check has succeeded it should get unhealthy and hence no node */ + assertNodeAbsence(bundle); + healthySucceeded.set(false); + + /* again mark healthy and check */ + + assertNodePresence(bundle); + } +} \ No newline at end of file diff --git a/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleHierarchicalSelectorTest.java b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleHierarchicalSelectorTest.java new file mode 100644 index 00000000..cb535185 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleHierarchicalSelectorTest.java @@ -0,0 +1,161 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle; + +import com.alibaba.dcm.DnsCacheManipulator; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.health.HealthCheckRegistry; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Lists; +import io.appform.ranger.core.healthcheck.HealthcheckStatus; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.util.ConfigurationUtils; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.server.DefaultServerFactory; +import io.dropwizard.core.setup.AdminEnvironment; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.jersey.DropwizardResourceConfig; +import io.dropwizard.jersey.setup.JerseyEnvironment; +import io.dropwizard.jetty.ConnectorFactory; +import io.dropwizard.jetty.HttpConnectorFactory; +import io.dropwizard.lifecycle.setup.LifecycleEnvironment; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.apache.curator.test.TestingCluster; +import org.eclipse.jetty.util.component.LifeCycle; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static io.appform.ranger.discovery.bundle.TestUtils.assertNodeAbsence; +import static io.appform.ranger.discovery.bundle.TestUtils.assertNodePresence; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +@Slf4j +class ServiceDiscoveryBundleHierarchicalSelectorTest { + + private final HealthCheckRegistry healthChecks = mock(HealthCheckRegistry.class); + private final JerseyEnvironment jerseyEnvironment = mock(JerseyEnvironment.class); + private final MetricRegistry metricRegistry = mock(MetricRegistry.class); + private final LifecycleEnvironment lifecycleEnvironment = new LifecycleEnvironment(metricRegistry); + private final Environment environment = mock(Environment.class); + private final Bootstrap bootstrap = mock(Bootstrap.class); + private final Configuration configuration = mock(Configuration.class); + private final DefaultServerFactory serverFactory = mock(DefaultServerFactory.class); + private final ConnectorFactory connectorFactory = mock(HttpConnectorFactory.class); + private final TestingCluster testingCluster = new TestingCluster(1); + private ServiceDiscoveryConfiguration serviceDiscoveryConfiguration; + private final ServiceDiscoveryBundle bundle = new ServiceDiscoveryBundle() { + @Override + protected ServiceDiscoveryConfiguration getRangerConfiguration(TestConfig configuration) { + return serviceDiscoveryConfiguration; + } + + @Override + protected String getServiceName(TestConfig configuration) { + return "TestService"; + } + }; + private HealthcheckStatus status = HealthcheckStatus.healthy; + + @BeforeEach + void setup() throws Exception { + when(serverFactory.getApplicationConnectors()).thenReturn(Lists.newArrayList(connectorFactory)); + when(configuration.getServerFactory()).thenReturn(serverFactory); + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.getObjectMapper()).thenReturn(new ObjectMapper()); + AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment) + .addTask(any()); + when(environment.admin()).thenReturn(adminEnvironment); + + testingCluster.start(); + + DnsCacheManipulator.setDnsCache("TestHost", "127.0.0.1"); + + serviceDiscoveryConfiguration = ServiceDiscoveryConfiguration.builder() + .zookeeper(testingCluster.getConnectString()) + .namespace("test") + .environment("x.y") + .connectionRetryIntervalMillis(5000) + .publishedHost("TestHost") + .publishedPort(8021) + .initialRotationStatus(true) + .build(); + ConfigurationUtils.resolveZookeeperHosts(serviceDiscoveryConfiguration.getZookeeper()) + .forEach(zkHost -> { + DnsCacheManipulator.setDnsCache(zkHost, "127.0.0.1"); + }); + val testConfig = new TestConfig(serviceDiscoveryConfiguration); + testConfig.setServerFactory(serverFactory); + bundle.initialize(bootstrap); + bundle.run(testConfig, environment); + bundle.getServerStatus() + .markStarted(); + for (LifeCycle lifeCycle : lifecycleEnvironment.getManagedObjects()) { + lifeCycle.start(); + } + bundle.registerHealthcheck(() -> status); + } + + @AfterEach + void tearDown() throws Exception { + for (LifeCycle lifeCycle : lifecycleEnvironment.getManagedObjects()) { + lifeCycle.stop(); + } + testingCluster.stop(); + } + + @Test + void testDiscovery() { + assertNodePresence(bundle); + val info = bundle.getServiceDiscoveryClient() + .getNode() + .orElse(null); + Assertions.assertNotNull(info); + Assertions.assertNotNull(info.getNodeData()); + Assertions.assertEquals("x.y", info.getNodeData() + .getEnvironment()); + Assertions.assertEquals("TestHost", info.getHost()); + Assertions.assertEquals(8021, info.getPort()); + + status = HealthcheckStatus.unhealthy; + + assertNodeAbsence(bundle); + } + + private static final class TestConfig extends Configuration { + + @Getter + private final ServiceDiscoveryConfiguration configuration; + + private TestConfig(ServiceDiscoveryConfiguration configuration) { + this.configuration = configuration; + } + + } +} \ No newline at end of file diff --git a/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleLocalHostPortTest.java b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleLocalHostPortTest.java new file mode 100644 index 00000000..20218ad1 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleLocalHostPortTest.java @@ -0,0 +1,295 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle; + +import com.alibaba.dcm.DnsCacheManipulator; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.health.HealthCheckRegistry; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.util.ConfigurationUtils; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.setup.AdminEnvironment; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.jersey.DropwizardResourceConfig; +import io.dropwizard.jersey.setup.JerseyEnvironment; +import io.dropwizard.lifecycle.setup.LifecycleEnvironment; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.UUID; + +import static io.appform.ranger.discovery.bundle.Constants.LOCAL_ADDRESSES; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +@Slf4j +class ServiceDiscoveryBundleLocalHostPortTest { + + private final HealthCheckRegistry healthChecks = mock(HealthCheckRegistry.class); + private final JerseyEnvironment jerseyEnvironment = mock(JerseyEnvironment.class); + private final MetricRegistry metricRegistry = mock(MetricRegistry.class); + private final LifecycleEnvironment lifecycleEnvironment = new LifecycleEnvironment(metricRegistry); + private final Environment environment = mock(Environment.class); + private final Bootstrap bootstrap = mock(Bootstrap.class); + private final Configuration configuration = mock(Configuration.class); + + private final ServiceDiscoveryBundle bundle = new ServiceDiscoveryBundle() { + @Override + protected ServiceDiscoveryConfiguration getRangerConfiguration(Configuration configuration) { + return serviceDiscoveryConfiguration; + } + + @Override + protected String getServiceName(Configuration configuration) { + return "TestService"; + } + + + }; + + @AfterEach + void afterMethod() { + DnsCacheManipulator.clearDnsCache(); + } + + private ServiceDiscoveryConfiguration serviceDiscoveryConfiguration; + + + @Test + void shouldFailLocalhostPublish() { + DnsCacheManipulator.setDnsCache("myzookeeper", "19.10.1.1"); + DnsCacheManipulator.setDnsCache("myfavzookeeper", "127.0.0.1"); + DnsCacheManipulator.setDnsCache("custom-host", "127.0.0.1"); + + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.getObjectMapper()).thenReturn(new ObjectMapper()); + AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment) + .addTask(any()); + when(environment.admin()).thenReturn(adminEnvironment); + + serviceDiscoveryConfiguration = ServiceDiscoveryConfiguration.builder() + .zookeeper("myzookeeper:2181,myfavzookeeper:2181") + .namespace("test") + .environment("testing") + .connectionRetryIntervalMillis(5000) + .publishedHost("custom-host") + .publishedPort(8021) + .initialRotationStatus(true) + .build(); + bundle.initialize(bootstrap); + assertLocalHostNotAllowed(); + + } + + @Test + void shouldThrowExceptionForInvalidZkHost() { + DnsCacheManipulator.setDnsCache("custom-host", "127.0.0.1"); + + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.getObjectMapper()).thenReturn(new ObjectMapper()); + AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment) + .addTask(any()); + when(environment.admin()).thenReturn(adminEnvironment); + + serviceDiscoveryConfiguration = ServiceDiscoveryConfiguration.builder() + .zookeeper(String.format("%s:2181", UUID.randomUUID())) + .namespace("test") + .environment("testing") + .connectionRetryIntervalMillis(5000) + .publishedHost("custom-host") + .publishedPort(8021) + .initialRotationStatus(true) + .build(); + bundle.initialize(bootstrap); + + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> { + bundle.run(configuration, environment); + + }); + + assertTrue(thrown.getMessage() + .contains("Couldn't resolve host address for zkHost")); + + } + + @Test + void testPublishWithEmptyZkHost() throws UnknownHostException { + DnsCacheManipulator.setDnsCache("myzookeeper", "19.10.1.1"); + DnsCacheManipulator.setDnsCache("myfavzookeeper", "127.0.0.1"); + DnsCacheManipulator.setDnsCache("custom-host", "127.0.0.1"); + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.getObjectMapper()).thenReturn(new ObjectMapper()); + AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment) + .addTask(any()); + when(environment.admin()).thenReturn(adminEnvironment); + + serviceDiscoveryConfiguration = ServiceDiscoveryConfiguration.builder() + .zookeeper("myzookeeper:2181,myfavzookeeper:2181") + .namespace("test") + .environment("testing") + .connectionRetryIntervalMillis(5000) + .publishedHost("") + .publishedPort(8021) + .initialRotationStatus(true) + .build(); + bundle.initialize(bootstrap); + + val publishedHost = ConfigurationUtils.resolveNonEmptyPublishedHost( + serviceDiscoveryConfiguration.getPublishedHost()); + val publishedHostAddress = InetAddress.getByName(publishedHost).getHostAddress(); + if (LOCAL_ADDRESSES.contains(publishedHostAddress) || LOCAL_ADDRESSES.contains(publishedHost)) { + assertLocalHostNotAllowed(); + } else { + assertDoesNotThrow(); + } + } + + @Test + void testPublishWithNullZkHost() throws UnknownHostException { + DnsCacheManipulator.setDnsCache("myzookeeper", "19.10.1.1"); + DnsCacheManipulator.setDnsCache("myfavzookeeper", "127.0.0.1"); + DnsCacheManipulator.setDnsCache("custom-host", "127.0.0.1"); + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.getObjectMapper()).thenReturn(new ObjectMapper()); + AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment) + .addTask(any()); + when(environment.admin()).thenReturn(adminEnvironment); + + serviceDiscoveryConfiguration = ServiceDiscoveryConfiguration.builder() + .zookeeper("myzookeeper:2181,myfavzookeeper:2181") + .namespace("test") + .environment("testing") + .connectionRetryIntervalMillis(5000) + .publishedPort(8021) + .initialRotationStatus(true) + .build(); + bundle.initialize(bootstrap); + + val publishedHost = ConfigurationUtils.resolveNonEmptyPublishedHost( + serviceDiscoveryConfiguration.getPublishedHost()); + val publishedHostAddress = InetAddress.getByName(publishedHost).getHostAddress(); + if (LOCAL_ADDRESSES.contains(publishedHostAddress) || LOCAL_ADDRESSES.contains(publishedHost)) { + assertLocalHostNotAllowed(); + } else { + assertDoesNotThrow(); + } + } + + @Test + void shouldPublishingToLocalZk() { + DnsCacheManipulator.setDnsCache("myfavzookeeper", "127.0.0.1"); + DnsCacheManipulator.setDnsCache("custom-host", "127.0.0.1"); + + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.getObjectMapper()).thenReturn(new ObjectMapper()); + AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment) + .addTask(any()); + when(environment.admin()).thenReturn(adminEnvironment); + + serviceDiscoveryConfiguration = ServiceDiscoveryConfiguration.builder() + .zookeeper("localhost:2181,myfavzookeeper:2181") + .namespace("test") + .environment("testing") + .connectionRetryIntervalMillis(5000) + .publishedHost("localhost") + .publishedPort(8021) + .initialRotationStatus(true) + .build(); + bundle.initialize(bootstrap); + + assertDoesNotThrow(); + + } + + @Test + void shouldPublishToRemoteZk() { + DnsCacheManipulator.setDnsCache("myfavzookeeper", "17.4.0.1"); + DnsCacheManipulator.setDnsCache("custom-host", "17.1.2.1"); + + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.getObjectMapper()).thenReturn(new ObjectMapper()); + AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment) + .addTask(any()); + when(environment.admin()).thenReturn(adminEnvironment); + + serviceDiscoveryConfiguration = ServiceDiscoveryConfiguration.builder() + .zookeeper("myfavzookeeper:2181") + .namespace("test") + .environment("testing") + .connectionRetryIntervalMillis(5000) + .publishedHost("custom-host") + .publishedPort(8021) + .initialRotationStatus(true) + .build(); + bundle.initialize(bootstrap); + + assertDoesNotThrow(); + } + + private void assertLocalHostNotAllowed() { + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> { + bundle.run(configuration, environment); + + }); + assertTrue(thrown.getMessage() + .contains("Not allowed to publish localhost address to remote zookeeper")); + } + + + private void assertDoesNotThrow() { + Assertions.assertDoesNotThrow(() -> { + bundle.run(configuration, environment); + }); + } + +} \ No newline at end of file diff --git a/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleRotationTest.java b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleRotationTest.java new file mode 100644 index 00000000..6c12d90c --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleRotationTest.java @@ -0,0 +1,158 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle; + +import com.alibaba.dcm.DnsCacheManipulator; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.health.HealthCheckRegistry; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Lists; +import io.appform.ranger.discovery.bundle.rotationstatus.BIRTask; +import io.appform.ranger.discovery.bundle.rotationstatus.OORTask; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.rotationstatus.RotationStatus; +import io.appform.ranger.discovery.common.util.ConfigurationUtils; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.server.DefaultServerFactory; +import io.dropwizard.core.setup.AdminEnvironment; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.jersey.DropwizardResourceConfig; +import io.dropwizard.jersey.setup.JerseyEnvironment; +import io.dropwizard.jetty.ConnectorFactory; +import io.dropwizard.jetty.HttpConnectorFactory; +import io.dropwizard.lifecycle.setup.LifecycleEnvironment; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.apache.curator.test.TestingCluster; +import org.eclipse.jetty.util.component.LifeCycle; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Collections; + +import static io.appform.ranger.discovery.bundle.TestUtils.assertNodeAbsence; +import static io.appform.ranger.discovery.bundle.TestUtils.assertNodePresence; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +@Slf4j +class ServiceDiscoveryBundleRotationTest { + + private final HealthCheckRegistry healthChecks = mock(HealthCheckRegistry.class); + private final JerseyEnvironment jerseyEnvironment = mock(JerseyEnvironment.class); + private final MetricRegistry metricRegistry = mock(MetricRegistry.class); + private final LifecycleEnvironment lifecycleEnvironment = new LifecycleEnvironment(metricRegistry); + private final Environment environment = mock(Environment.class); + private final Bootstrap bootstrap = mock(Bootstrap.class); + private final Configuration configuration = mock(Configuration.class); + private final DefaultServerFactory serverFactory = mock(DefaultServerFactory.class); + private final ConnectorFactory connectorFactory = mock(HttpConnectorFactory.class); + private final TestingCluster testingCluster = new TestingCluster(1); + private ServiceDiscoveryConfiguration serviceDiscoveryConfiguration; + private final ServiceDiscoveryBundle bundle = new ServiceDiscoveryBundle() { + @Override + protected ServiceDiscoveryConfiguration getRangerConfiguration(Configuration configuration) { + return serviceDiscoveryConfiguration; + } + + @Override + protected String getServiceName(Configuration configuration) { + return "TestService"; + } + + }; + private RotationStatus rotationStatus; + + @BeforeEach + void setup() throws Exception { + when(serverFactory.getApplicationConnectors()).thenReturn(Lists.newArrayList(connectorFactory)); + when(configuration.getServerFactory()).thenReturn(serverFactory); + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.getObjectMapper()).thenReturn(new ObjectMapper()); + AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment) + .addTask(any()); + when(environment.admin()).thenReturn(adminEnvironment); + + testingCluster.start(); + + serviceDiscoveryConfiguration = ServiceDiscoveryConfiguration.builder() + .zookeeper(testingCluster.getConnectString()) + .namespace("test") + .environment("testing") + .connectionRetryIntervalMillis(5000) + .publishedHost("TestHost") + .publishedPort(8021) + .initialRotationStatus(true) + .build(); + + DnsCacheManipulator.setDnsCache("TestHost", "127.0.0.1"); + ConfigurationUtils.resolveZookeeperHosts(serviceDiscoveryConfiguration.getZookeeper()) + .forEach(zkHost -> { + DnsCacheManipulator.setDnsCache(zkHost, "127.0.0.1"); + }); + bundle.initialize(bootstrap); + bundle.run(configuration, environment); + rotationStatus = bundle.getRotationStatus(); + bundle.getServerStatus() + .markStarted(); + for (LifeCycle lifeCycle : lifecycleEnvironment.getManagedObjects()) { + lifeCycle.start(); + } + } + + @AfterEach + void tearDown() throws Exception { + for (LifeCycle lifeCycle : lifecycleEnvironment.getManagedObjects()) { + lifeCycle.stop(); + } + testingCluster.stop(); + } + + @Test + void testDiscovery() { + assertNodePresence(bundle); + val info = bundle.getServiceDiscoveryClient() + .getNode() + .orElse(null); + Assertions.assertNotNull(info); + Assertions.assertNotNull(info.getNodeData()); + Assertions.assertEquals("testing", info.getNodeData() + .getEnvironment()); + Assertions.assertEquals("TestHost", info.getHost()); + Assertions.assertEquals(8021, info.getPort()); + + val oorTask = new OORTask(rotationStatus); + oorTask.execute(Collections.emptyMap(), null); + + assertNodeAbsence(bundle); + + val birTask = new BIRTask(rotationStatus); + birTask.execute(Collections.emptyMap(), null); + + assertNodePresence(bundle); + } +} \ No newline at end of file diff --git a/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleTest.java b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleTest.java new file mode 100644 index 00000000..b33e0332 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleTest.java @@ -0,0 +1,157 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle; + +import com.alibaba.dcm.DnsCacheManipulator; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.health.HealthCheckRegistry; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Lists; +import io.appform.ranger.core.healthcheck.HealthcheckStatus; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.resolvers.DefaultNodeInfoResolver; +import io.appform.ranger.discovery.common.resolvers.NodeInfoResolver; +import io.appform.ranger.discovery.common.util.ConfigurationUtils; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.server.DefaultServerFactory; +import io.dropwizard.core.setup.AdminEnvironment; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.jersey.DropwizardResourceConfig; +import io.dropwizard.jersey.setup.JerseyEnvironment; +import io.dropwizard.jetty.ConnectorFactory; +import io.dropwizard.jetty.HttpConnectorFactory; +import io.dropwizard.lifecycle.setup.LifecycleEnvironment; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.apache.curator.test.TestingCluster; +import org.eclipse.jetty.util.component.LifeCycle; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static io.appform.ranger.discovery.bundle.TestUtils.assertNodeAbsence; +import static io.appform.ranger.discovery.bundle.TestUtils.assertNodePresence; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +@Slf4j +class ServiceDiscoveryBundleTest { + + private final HealthCheckRegistry healthChecks = mock(HealthCheckRegistry.class); + private final JerseyEnvironment jerseyEnvironment = mock(JerseyEnvironment.class); + private final MetricRegistry metricRegistry = mock(MetricRegistry.class); + private final LifecycleEnvironment lifecycleEnvironment = new LifecycleEnvironment(metricRegistry); + private final Environment environment = mock(Environment.class); + private final Bootstrap bootstrap = mock(Bootstrap.class); + private final Configuration configuration = mock(Configuration.class); + private final DefaultServerFactory serverFactory = mock(DefaultServerFactory.class); + private final ConnectorFactory connectorFactory = mock(HttpConnectorFactory.class); + private final TestingCluster testingCluster = new TestingCluster(1); + private ServiceDiscoveryConfiguration serviceDiscoveryConfiguration; + private final ServiceDiscoveryBundle bundle = new ServiceDiscoveryBundle() { + @Override + protected ServiceDiscoveryConfiguration getRangerConfiguration(Configuration configuration) { + return serviceDiscoveryConfiguration; + } + + @Override + protected String getServiceName(Configuration configuration) { + return "TestService"; + } + + @Override + protected NodeInfoResolver createNodeInfoResolver() { + return new DefaultNodeInfoResolver(); + } + }; + private HealthcheckStatus status = HealthcheckStatus.healthy; + + @BeforeEach + void setup() throws Exception { + when(serverFactory.getApplicationConnectors()).thenReturn(Lists.newArrayList(connectorFactory)); + when(configuration.getServerFactory()).thenReturn(serverFactory); + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.getObjectMapper()).thenReturn(new ObjectMapper()); + AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment) + .addTask(any()); + when(environment.admin()).thenReturn(adminEnvironment); + + testingCluster.start(); + + serviceDiscoveryConfiguration = ServiceDiscoveryConfiguration.builder() + .zookeeper(testingCluster.getConnectString()) + .namespace("test") + .environment("testing") + .connectionRetryIntervalMillis(5000) + .publishedHost("TestHost") + .publishedPort(8021) + .initialRotationStatus(true) + .build(); + + DnsCacheManipulator.setDnsCache("TestHost", "127.0.0.1"); + ConfigurationUtils.resolveZookeeperHosts(serviceDiscoveryConfiguration.getZookeeper()) + .forEach(zkHost -> { + DnsCacheManipulator.setDnsCache(zkHost, "127.0.0.1"); + }); + + bundle.initialize(bootstrap); + bundle.run(configuration, environment); + bundle.getServerStatus() + .markStarted(); + for (LifeCycle lifeCycle : lifecycleEnvironment.getManagedObjects()) { + lifeCycle.start(); + } + bundle.registerHealthcheck(() -> status); + } + + @AfterEach + void tearDown() throws Exception { + for (LifeCycle lifeCycle : lifecycleEnvironment.getManagedObjects()) { + lifeCycle.stop(); + } + testingCluster.stop(); + } + + @Test + void testDiscovery() { + assertNodePresence(bundle); + val info = bundle.getServiceDiscoveryClient() + .getNode() + .orElse(null); + Assertions.assertNotNull(info); + Assertions.assertNotNull(info.getNodeData()); + Assertions.assertEquals("testing", info.getNodeData() + .getEnvironment()); + Assertions.assertEquals("TestHost", info.getHost()); + Assertions.assertEquals(8021, info.getPort()); + Assertions.assertNull(info.getNodeData() + .getRegion()); + + status = HealthcheckStatus.unhealthy; + + assertNodeAbsence(bundle); + } +} \ No newline at end of file diff --git a/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/TestUtils.java b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/TestUtils.java new file mode 100644 index 00000000..22dd6879 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/TestUtils.java @@ -0,0 +1,51 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.bundle; + +import io.dropwizard.core.Configuration; +import lombok.experimental.UtilityClass; +import org.awaitility.Awaitility; + +import java.time.Duration; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + + +/** + * + */ +@UtilityClass +public class TestUtils { + public static void assertNodePresence(ServiceDiscoveryBundle bundle) { + Awaitility.await() + .pollInterval(Duration.ofSeconds(1)) + .atMost(Duration.ofSeconds(30)) + .untilAsserted(() -> assertNotNull(bundle.getServiceDiscoveryClient() + .getNode() + .orElse(null))); + } + + public static void assertNodeAbsence(ServiceDiscoveryBundle bundle) { + Awaitility.await() + .pollInterval(Duration.ofSeconds(1)) + .atMost(Duration.ofSeconds(30)) + .untilAsserted(() -> assertNull(bundle.getServiceDiscoveryClient() + .getNode() + .orElse(null))); + } +} diff --git a/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/resolvers/DefaultNodeInfoResolverTest.java b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/resolvers/DefaultNodeInfoResolverTest.java new file mode 100644 index 00000000..9691ee54 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/resolvers/DefaultNodeInfoResolverTest.java @@ -0,0 +1,44 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.discovery.bundle.resolvers; + +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.resolvers.DefaultNodeInfoResolver; +import lombok.val; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class DefaultNodeInfoResolverTest { + + @Test + void testNodeInfoResolver() { + val configuration = ServiceDiscoveryConfiguration.builder() + .zookeeper("connectionString") + .namespace("test") + .environment("testing") + .connectionRetryIntervalMillis(5000) + .publishedHost("TestHost") + .publishedPort(8021) + .initialRotationStatus(true) + .build(); + val resolver = new DefaultNodeInfoResolver(); + val nodeInfo = resolver.resolve(configuration); + Assertions.assertNotNull(nodeInfo); + Assertions.assertEquals("testing", configuration.getEnvironment()); + Assertions.assertNull(nodeInfo.getRegion()); + Assertions.assertNull(nodeInfo.getTags()); + } +} diff --git a/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/resolvers/DefaultPortSchemeResolverTest.java b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/resolvers/DefaultPortSchemeResolverTest.java new file mode 100644 index 00000000..a2efd010 --- /dev/null +++ b/ranger-discovery-bundle-dw5/src/test/java/io/appform/ranger/discovery/bundle/resolvers/DefaultPortSchemeResolverTest.java @@ -0,0 +1,64 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.discovery.bundle.resolvers; + +import com.google.common.collect.Lists; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.server.DefaultServerFactory; +import io.dropwizard.core.server.SimpleServerFactory; +import io.dropwizard.jetty.HttpConnectorFactory; +import io.dropwizard.jetty.HttpsConnectorFactory; +import lombok.val; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class DefaultPortSchemeResolverTest { + + @Test + void testPortSchemeDefaultServerFactory() { + val server = mock(DefaultServerFactory.class); + val connectorFactory = mock(HttpConnectorFactory.class); + when(server.getApplicationConnectors()).thenReturn(Lists.newArrayList(connectorFactory)); + val resolver = new DefaultPortSchemeResolver<>(); + val configuration = mock(Configuration.class); + when(configuration.getServerFactory()).thenReturn(server); + Assertions.assertEquals("http", resolver.resolve(configuration)); + } + + @Test + void testPortSchemeSimpleServerFactory() { + val server = mock(SimpleServerFactory.class); + val connectorFactory = mock(HttpsConnectorFactory.class); + when(server.getConnector()).thenReturn(connectorFactory); + val resolver = new DefaultPortSchemeResolver<>(); + val configuration = mock(Configuration.class); + when(configuration.getServerFactory()).thenReturn(server); + Assertions.assertEquals("https", resolver.resolve(configuration)); + } + + @Test + void testPortSchemeDefault() { + val server = mock(SimpleServerFactory.class); + when(server.getConnector()).thenReturn(null); + val resolver = new DefaultPortSchemeResolver<>(); + val configuration = mock(Configuration.class); + when(configuration.getServerFactory()).thenReturn(server); + Assertions.assertEquals("http", resolver.resolve(configuration)); + } +} diff --git a/ranger-discovery-bundle/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerate.json b/ranger-discovery-bundle/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerate.json index a31c4695..1a38dbac 100644 --- a/ranger-discovery-bundle/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerate.json +++ b/ranger-discovery-bundle/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerate.json @@ -1,8 +1,8 @@ { - "name" : "io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerate", - "mode" : "Throughput", - "iterations" : 4, - "threads" : 1, - "forks" : 3, - "mean_ops" : 983207.6911013111 + "name": "io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerate", + "mode": "Throughput", + "iterations": 4, + "threads": 1, + "forks": 3, + "mean_ops": 983207.6911013111 } \ No newline at end of file diff --git a/ranger-discovery-bundle/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerateBase36.json b/ranger-discovery-bundle/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerateBase36.json index 823a53ce..69a6de05 100644 --- a/ranger-discovery-bundle/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerateBase36.json +++ b/ranger-discovery-bundle/perf/results/io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerateBase36.json @@ -1,8 +1,8 @@ { - "name" : "io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerateBase36", - "mode" : "Throughput", - "iterations" : 4, - "threads" : 1, - "forks" : 3, - "mean_ops" : 915820.4865429945 + "name": "io.appform.ranger.discovery.bundle.id.IdGeneratorPerfTest.testGenerateBase36", + "mode": "Throughput", + "iterations": 4, + "threads": 1, + "forks": 3, + "mean_ops": 915820.4865429945 } \ No newline at end of file diff --git a/ranger-discovery-bundle/pom.xml b/ranger-discovery-bundle/pom.xml index e4816237..be3a7d9c 100644 --- a/ranger-discovery-bundle/pom.xml +++ b/ranger-discovery-bundle/pom.xml @@ -26,34 +26,41 @@ 4.0.0 ranger-discovery-bundle - Dropwizard bundle for Ranger dicovery + Dropwizard bundle for Ranger discovery 1.8.1 + 2.1.12 - + + + + io.dropwizard + dropwizard-bom + ${dropwizard.version} + pom + import + + + + io.dropwizard dropwizard-core provided + + io.dropwizard + dropwizard-jackson + provided + org.apache.curator curator-test ${curator.version} test - - - log4j - log4j - - - io.netty - * - - org.mockito @@ -61,6 +68,11 @@ ${mockito.version} test + + io.appform.ranger + ranger-discovery-common + ${project.version} + io.appform.ranger ranger-zk-client @@ -71,17 +83,16 @@ ranger-server-common ${project.version} + + io.appform.ranger + ranger-id + ${project.version} + com.alibaba dns-cache-manipulator ${dns.cache.manipulator.version} test - - io.appform.ranger - ranger-id - ${project.version} - - diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/Constants.java b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/Constants.java index 43c2a1f4..147207c0 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/Constants.java +++ b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/Constants.java @@ -31,12 +31,6 @@ public class Constants { public static final int DEFAULT_PORT = -1; public static final int DEFAULT_DW_CHECK_INTERVAL = 15; - public static final int DEFAULT_RETRY_CONN_INTERVAL = 5000; - - public static final String ZOOKEEPER_HOST_DELIMITER = ","; - public static final String HOST_PORT_DELIMITER = ":"; - public static final String PATH_DELIMITER = "/"; - public static final Set LOCAL_ADDRESSES = ImmutableSet.of("127.0.0.1", "127.0.1.1", "localhost"); } diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundle.java b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundle.java index 721a7774..710b48f1 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundle.java +++ b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundle.java @@ -32,21 +32,22 @@ import io.appform.ranger.core.model.ServiceNode; import io.appform.ranger.core.model.ShardSelector; import io.appform.ranger.core.serviceprovider.ServiceProvider; -import io.appform.ranger.discovery.bundle.healthchecks.InitialDelayChecker; -import io.appform.ranger.discovery.bundle.healthchecks.InternalHealthChecker; -import io.appform.ranger.discovery.bundle.healthchecks.RotationCheck; -import io.appform.ranger.discovery.bundle.monitors.DropwizardHealthMonitor; import io.appform.ranger.discovery.bundle.monitors.DropwizardServerStartupCheck; -import io.appform.ranger.discovery.bundle.resolvers.DefaultNodeInfoResolver; import io.appform.ranger.discovery.bundle.resolvers.DefaultPortSchemeResolver; -import io.appform.ranger.discovery.bundle.resolvers.NodeInfoResolver; import io.appform.ranger.discovery.bundle.resolvers.PortSchemeResolver; import io.appform.ranger.discovery.bundle.rotationstatus.BIRTask; -import io.appform.ranger.discovery.bundle.rotationstatus.DropwizardServerStatus; import io.appform.ranger.discovery.bundle.rotationstatus.OORTask; -import io.appform.ranger.discovery.bundle.rotationstatus.RotationStatus; -import io.appform.ranger.discovery.bundle.selectors.HierarchicalEnvironmentAwareShardSelector; -import io.appform.ranger.discovery.bundle.util.ConfigurationUtils; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.healthchecks.InitialDelayChecker; +import io.appform.ranger.discovery.common.healthchecks.InternalHealthChecker; +import io.appform.ranger.discovery.common.healthchecks.RotationCheck; +import io.appform.ranger.discovery.common.monitors.DropwizardHealthMonitor; +import io.appform.ranger.discovery.common.resolvers.DefaultNodeInfoResolver; +import io.appform.ranger.discovery.common.resolvers.NodeInfoResolver; +import io.appform.ranger.discovery.common.rotationstatus.DropwizardServerStatus; +import io.appform.ranger.discovery.common.rotationstatus.RotationStatus; +import io.appform.ranger.discovery.common.selectors.HierarchicalEnvironmentAwareShardSelector; +import io.appform.ranger.discovery.common.util.ConfigurationUtils; import io.appform.ranger.id.IdGenerator; import io.appform.ranger.id.NodeIdManager; import io.appform.ranger.id.constraints.IdValidationConstraint; @@ -106,8 +107,8 @@ protected ServiceDiscoveryBundle() { protected ServiceDiscoveryBundle(List globalIdConstraints) { this.globalIdConstraints = globalIdConstraints != null - ? globalIdConstraints - : Collections.emptyList(); + ? globalIdConstraints + : Collections.emptyList(); } @Override @@ -265,11 +266,11 @@ private ServiceProvider> buildService val nodeInfoResolver = createNodeInfoResolver(); val nodeInfo = nodeInfoResolver.resolve(serviceDiscoveryConfiguration); val initialDelayForMonitor = serviceDiscoveryConfiguration.getInitialDelaySeconds() > 1 - ? serviceDiscoveryConfiguration.getInitialDelaySeconds() - 1 - : 0; + ? serviceDiscoveryConfiguration.getInitialDelaySeconds() - 1 + : 0; val dwMonitoringInterval = serviceDiscoveryConfiguration.getDropwizardCheckInterval() == 0 - ? Constants.DEFAULT_DW_CHECK_INTERVAL - : serviceDiscoveryConfiguration.getDropwizardCheckInterval(); + ? Constants.DEFAULT_DW_CHECK_INTERVAL + : serviceDiscoveryConfiguration.getDropwizardCheckInterval(); val dwMonitoringStaleness = Math.max(serviceDiscoveryConfiguration.getDropwizardCheckStaleness(), dwMonitoringInterval + 1); val serviceProviderBuilder = ServiceProviderBuilders.shardedServiceProviderBuilder() @@ -294,7 +295,7 @@ private ServiceProvider> buildService .withHealthcheck(new DropwizardServerStartupCheck(environment, serverStatus)) .withIsolatedHealthMonitor(new DropwizardHealthMonitor( new TimeEntity(initialDelayForMonitor, dwMonitoringInterval, TimeUnit.SECONDS), - dwMonitoringStaleness * 1_000L, environment)) + dwMonitoringStaleness * 1_000L, environment.healthChecks())) .withHealthUpdateIntervalMs(serviceDiscoveryConfiguration.getRefreshTimeMs()) .withStaleUpdateThresholdMs(10000); diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/monitors/DropwizardServerStartupCheck.java b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/monitors/DropwizardServerStartupCheck.java index f5d57f9f..02de8ade 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/monitors/DropwizardServerStartupCheck.java +++ b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/monitors/DropwizardServerStartupCheck.java @@ -18,7 +18,7 @@ import io.appform.ranger.core.healthcheck.Healthcheck; import io.appform.ranger.core.healthcheck.HealthcheckStatus; -import io.appform.ranger.discovery.bundle.rotationstatus.DropwizardServerStatus; +import io.appform.ranger.discovery.common.rotationstatus.DropwizardServerStatus; import io.dropwizard.setup.Environment; import lombok.extern.slf4j.Slf4j; @@ -31,7 +31,7 @@ public class DropwizardServerStartupCheck implements Healthcheck { private final DropwizardServerStatus serverStatus; public DropwizardServerStartupCheck(Environment environment, - DropwizardServerStatus serverStatus) { + DropwizardServerStatus serverStatus) { this.serverStatus = serverStatus; environment.lifecycle().addServerLifecycleListener(server -> { log.info("Dropwizard server started. Marking healthcheck as healthy"); diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/DefaultPortSchemeResolver.java b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/DefaultPortSchemeResolver.java index e81ed139..245e0990 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/DefaultPortSchemeResolver.java +++ b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/DefaultPortSchemeResolver.java @@ -49,13 +49,11 @@ public String resolve(T configuration) { } private Optional getConnectorFactory(ServerFactory serverFactory) { - if (serverFactory instanceof DefaultServerFactory) { - val defaultFactory = (DefaultServerFactory) serverFactory; + if (serverFactory instanceof DefaultServerFactory defaultFactory) { return defaultFactory.getApplicationConnectors() .stream() .findFirst(); - } else if (serverFactory instanceof SimpleServerFactory) { - val defaultFactory = (SimpleServerFactory) serverFactory; + } else if (serverFactory instanceof SimpleServerFactory defaultFactory) { return Optional.ofNullable(defaultFactory.getConnector()); } else { return Optional.empty(); diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/PortSchemeResolver.java b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/PortSchemeResolver.java index 863a6957..3f786c0f 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/PortSchemeResolver.java +++ b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/PortSchemeResolver.java @@ -15,6 +15,7 @@ */ package io.appform.ranger.discovery.bundle.resolvers; +import io.appform.ranger.discovery.common.resolvers.CriteriaResolver; import io.dropwizard.Configuration; /** diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/BIRTask.java b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/BIRTask.java index 6a1cc365..44619deb 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/BIRTask.java +++ b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/BIRTask.java @@ -17,6 +17,7 @@ package io.appform.ranger.discovery.bundle.rotationstatus; +import io.appform.ranger.discovery.common.rotationstatus.RotationStatus; import io.dropwizard.servlets.tasks.Task; import lombok.extern.slf4j.Slf4j; @@ -30,6 +31,7 @@ @Slf4j public class BIRTask extends Task { private final RotationStatus rotationStatus; + public BIRTask(RotationStatus rotationStatus) { super("ranger-bir"); this.rotationStatus = rotationStatus; diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/OORTask.java b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/OORTask.java index 11827da7..1913bf52 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/OORTask.java +++ b/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/OORTask.java @@ -16,6 +16,7 @@ package io.appform.ranger.discovery.bundle.rotationstatus; +import io.appform.ranger.discovery.common.rotationstatus.RotationStatus; import io.dropwizard.servlets.tasks.Task; import lombok.extern.slf4j.Slf4j; @@ -29,6 +30,7 @@ @Slf4j public class OORTask extends Task { private final RotationStatus rotationStatus; + public OORTask(RotationStatus rotationStatus) { super("ranger-oor"); this.rotationStatus = rotationStatus; diff --git a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleCustomHostPortTest.java b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleCustomHostPortTest.java index 83440be4..9778033e 100644 --- a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleCustomHostPortTest.java +++ b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleCustomHostPortTest.java @@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; import io.appform.ranger.core.healthcheck.HealthcheckStatus; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; import io.dropwizard.Configuration; import io.dropwizard.jersey.DropwizardResourceConfig; import io.dropwizard.jersey.setup.JerseyEnvironment; @@ -46,7 +47,9 @@ import static io.appform.ranger.discovery.bundle.TestUtils.assertNodeAbsence; import static io.appform.ranger.discovery.bundle.TestUtils.assertNodePresence; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @Slf4j diff --git a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwMonitorTest.java b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwMonitorTest.java index adf73745..df68b960 100644 --- a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwMonitorTest.java +++ b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwMonitorTest.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; import io.appform.ranger.core.healthcheck.HealthcheckStatus; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; import io.dropwizard.Configuration; import io.dropwizard.jersey.DropwizardResourceConfig; import io.dropwizard.jersey.setup.JerseyEnvironment; @@ -49,7 +50,9 @@ import static io.appform.ranger.discovery.bundle.TestUtils.assertNodeAbsence; import static io.appform.ranger.discovery.bundle.TestUtils.assertNodePresence; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @Slf4j @@ -103,8 +106,8 @@ void setup() throws Exception { @Override protected Result check() { val result = (counter.decrementAndGet() < 0) - ? Result.unhealthy("unhealthy") - : Result.healthy(); + ? Result.unhealthy("unhealthy") + : Result.healthy(); log.info("Marking node as {}", result.isHealthy()); return result; } diff --git a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwStalenessMonitorTest.java b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwStalenessMonitorTest.java index ef485c31..bed77f5d 100644 --- a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwStalenessMonitorTest.java +++ b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleDwStalenessMonitorTest.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; import io.appform.ranger.core.healthcheck.HealthcheckStatus; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; import io.dropwizard.Configuration; import io.dropwizard.jersey.DropwizardResourceConfig; import io.dropwizard.jersey.setup.JerseyEnvironment; @@ -49,7 +50,9 @@ import static io.appform.ranger.discovery.bundle.TestUtils.assertNodeAbsence; import static io.appform.ranger.discovery.bundle.TestUtils.assertNodePresence; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @Slf4j @@ -102,7 +105,7 @@ void setup() throws Exception { @Override protected Result check() { if (healthySucceeded.get()) { - return Result.unhealthy("Forced unhealthy as healthy check has succeded"); + return Result.unhealthy("Forced unhealthy as healthy check has succeeded"); } return Result.healthy(); } diff --git a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleHierarchicalSelectorTest.java b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleHierarchicalSelectorTest.java index 7f7d7cfc..c8115c93 100644 --- a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleHierarchicalSelectorTest.java +++ b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleHierarchicalSelectorTest.java @@ -24,7 +24,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; import io.appform.ranger.core.healthcheck.HealthcheckStatus; -import io.appform.ranger.discovery.bundle.util.ConfigurationUtils; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.util.ConfigurationUtils; import io.dropwizard.Configuration; import io.dropwizard.jersey.DropwizardResourceConfig; import io.dropwizard.jersey.setup.JerseyEnvironment; @@ -49,7 +50,9 @@ import static io.appform.ranger.discovery.bundle.TestUtils.assertNodeAbsence; import static io.appform.ranger.discovery.bundle.TestUtils.assertNodePresence; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @Slf4j diff --git a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleLocalHostPortTest.java b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleLocalHostPortTest.java index 0cc51373..9b12fd5c 100644 --- a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleLocalHostPortTest.java +++ b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleLocalHostPortTest.java @@ -20,7 +20,8 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.health.HealthCheckRegistry; import com.fasterxml.jackson.databind.ObjectMapper; -import io.appform.ranger.discovery.bundle.util.ConfigurationUtils; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.util.ConfigurationUtils; import io.dropwizard.Configuration; import io.dropwizard.jersey.DropwizardResourceConfig; import io.dropwizard.jersey.setup.JerseyEnvironment; @@ -42,7 +43,9 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @Slf4j @@ -71,7 +74,7 @@ protected String getServiceName(Configuration configuration) { }; @AfterEach - public void afterMethod() { + void afterMethod() { DnsCacheManipulator.clearDnsCache(); } @@ -139,7 +142,7 @@ void shouldThrowExceptionForInvalidZkHost() { }); assertTrue(thrown.getMessage() - .contains("Couldn't resolve host address for zkHost")); + .contains("Couldn't resolve host address for zkHost")); } @@ -279,7 +282,7 @@ private void assertLocalHostNotAllowed() { }); assertTrue(thrown.getMessage() - .contains("Not allowed to publish localhost address to remote zookeeper")); + .contains("Not allowed to publish localhost address to remote zookeeper")); } diff --git a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleRotationTest.java b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleRotationTest.java index 509795b2..7fbd2d7d 100644 --- a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleRotationTest.java +++ b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleRotationTest.java @@ -25,8 +25,9 @@ import com.google.common.collect.Lists; import io.appform.ranger.discovery.bundle.rotationstatus.BIRTask; import io.appform.ranger.discovery.bundle.rotationstatus.OORTask; -import io.appform.ranger.discovery.bundle.rotationstatus.RotationStatus; -import io.appform.ranger.discovery.bundle.util.ConfigurationUtils; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.rotationstatus.RotationStatus; +import io.appform.ranger.discovery.common.util.ConfigurationUtils; import io.dropwizard.Configuration; import io.dropwizard.jersey.DropwizardResourceConfig; import io.dropwizard.jersey.setup.JerseyEnvironment; @@ -52,7 +53,9 @@ import static io.appform.ranger.discovery.bundle.TestUtils.assertNodeAbsence; import static io.appform.ranger.discovery.bundle.TestUtils.assertNodePresence; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @Slf4j diff --git a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleTest.java b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleTest.java index 7f0bdde8..2a8b85aa 100644 --- a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleTest.java +++ b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryBundleTest.java @@ -24,9 +24,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; import io.appform.ranger.core.healthcheck.HealthcheckStatus; -import io.appform.ranger.discovery.bundle.resolvers.DefaultNodeInfoResolver; -import io.appform.ranger.discovery.bundle.resolvers.NodeInfoResolver; -import io.appform.ranger.discovery.bundle.util.ConfigurationUtils; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.resolvers.DefaultNodeInfoResolver; +import io.appform.ranger.discovery.common.resolvers.NodeInfoResolver; +import io.appform.ranger.discovery.common.util.ConfigurationUtils; import io.dropwizard.Configuration; import io.dropwizard.jersey.DropwizardResourceConfig; import io.dropwizard.jersey.setup.JerseyEnvironment; @@ -50,7 +51,9 @@ import static io.appform.ranger.discovery.bundle.TestUtils.assertNodeAbsence; import static io.appform.ranger.discovery.bundle.TestUtils.assertNodePresence; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @Slf4j diff --git a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/TestUtils.java b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/TestUtils.java index 6bcc0505..b56da311 100644 --- a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/TestUtils.java +++ b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/TestUtils.java @@ -31,20 +31,21 @@ */ @UtilityClass public class TestUtils { - public static void assertNodePresence(ServiceDiscoveryBundle bundle) { + public static void assertNodePresence(ServiceDiscoveryBundle bundle) { Awaitility.await() .pollInterval(Duration.ofSeconds(1)) .atMost(Duration.ofSeconds(30)) .untilAsserted(() -> assertNotNull(bundle.getServiceDiscoveryClient() - .getNode() - .orElse(null))); + .getNode() + .orElse(null))); } - public static void assertNodeAbsence(ServiceDiscoveryBundle bundle) { + + public static void assertNodeAbsence(ServiceDiscoveryBundle bundle) { Awaitility.await() .pollInterval(Duration.ofSeconds(1)) .atMost(Duration.ofSeconds(30)) .untilAsserted(() -> assertNull(bundle.getServiceDiscoveryClient() - .getNode() - .orElse(null))); + .getNode() + .orElse(null))); } } diff --git a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/resolvers/DefaultNodeInfoResolverTest.java b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/resolvers/DefaultNodeInfoResolverTest.java index f093dc61..9691ee54 100644 --- a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/resolvers/DefaultNodeInfoResolverTest.java +++ b/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/resolvers/DefaultNodeInfoResolverTest.java @@ -15,7 +15,8 @@ */ package io.appform.ranger.discovery.bundle.resolvers; -import io.appform.ranger.discovery.bundle.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.resolvers.DefaultNodeInfoResolver; import lombok.val; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/ranger-discovery-common/pom.xml b/ranger-discovery-common/pom.xml new file mode 100644 index 00000000..8fc3d867 --- /dev/null +++ b/ranger-discovery-common/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + io.appform.ranger + ranger + 2.0.0-SNAPSHOT + + + ranger-discovery-common + + + 17 + 17 + UTF-8 + 3.2.4 + 3.0.2 + + + + io.appform.ranger + ranger-core + ${project.version} + + + io.appform.ranger + ranger-server-common + ${project.version} + + + jakarta.validation + jakarta.validation-api + ${jakarta.validation-api.version} + + + io.appform.ranger + ranger-zk-client + ${project.version} + + + dev.failsafe + failsafe + ${failsafe.version} + + + io.dropwizard.metrics + metrics-healthchecks + ${metrics.version} + + + org.mockito + mockito-core + ${mockito.version} + test + + + \ No newline at end of file diff --git a/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/Constants.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/Constants.java new file mode 100644 index 00000000..85174cba --- /dev/null +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/Constants.java @@ -0,0 +1,36 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.discovery.common; + +import lombok.experimental.UtilityClass; + +/** + * Constants + */ +@UtilityClass +public class Constants { + public static final String DEFAULT_NAMESPACE = "default"; + public static final String DEFAULT_HOST = "__DEFAULT_SERVICE_HOST"; + public static final int DEFAULT_PORT = -1; + public static final int DEFAULT_DW_CHECK_INTERVAL = 15; + public static final int DEFAULT_RETRY_CONN_INTERVAL = 5000; + + public static final String ZOOKEEPER_HOST_DELIMITER = ","; + public static final String HOST_PORT_DELIMITER = ":"; + public static final String PATH_DELIMITER = "/"; + +} diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryConfiguration.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/ServiceDiscoveryConfiguration.java similarity index 80% rename from ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryConfiguration.java rename to ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/ServiceDiscoveryConfiguration.java index 6e6a4fa0..d8e3f91e 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/ServiceDiscoveryConfiguration.java +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/ServiceDiscoveryConfiguration.java @@ -14,19 +14,19 @@ * limitations under the License. */ -package io.appform.ranger.discovery.bundle; +package io.appform.ranger.discovery.common; import com.google.common.base.Strings; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.ToString; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; import java.util.Set; /** @@ -95,26 +95,26 @@ public ServiceDiscoveryConfiguration(String namespace, int dropwizardCheckStaleness, Set tags) { this.namespace = Strings.isNullOrEmpty(namespace) - ? Constants.DEFAULT_NAMESPACE - : namespace; + ? Constants.DEFAULT_NAMESPACE + : namespace; this.environment = environment; this.zookeeper = zookeeper; this.connectionRetryIntervalMillis = connectionRetryIntervalMillis == 0 - ? Constants.DEFAULT_RETRY_CONN_INTERVAL - : connectionRetryIntervalMillis; + ? Constants.DEFAULT_RETRY_CONN_INTERVAL + : connectionRetryIntervalMillis; this.publishedHost = Strings.isNullOrEmpty(publishedHost) - ? Constants.DEFAULT_HOST - : publishedHost; + ? Constants.DEFAULT_HOST + : publishedHost; this.publishedPort = publishedPort == 0 - ? Constants.DEFAULT_PORT - : publishedPort; + ? Constants.DEFAULT_PORT + : publishedPort; this.refreshTimeMs = refreshTimeMs; this.disableWatchers = disableWatchers; this.initialDelaySeconds = initialDelaySeconds; this.initialRotationStatus = initialRotationStatus; this.dropwizardCheckInterval = dropwizardCheckInterval == 0 - ? Constants.DEFAULT_DW_CHECK_INTERVAL - : dropwizardCheckInterval; + ? Constants.DEFAULT_DW_CHECK_INTERVAL + : dropwizardCheckInterval; this.dropwizardCheckStaleness = dropwizardCheckStaleness; this.tags = tags; } diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/healthchecks/InitialDelayChecker.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/healthchecks/InitialDelayChecker.java similarity index 89% rename from ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/healthchecks/InitialDelayChecker.java rename to ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/healthchecks/InitialDelayChecker.java index ddd81648..4e779d3a 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/healthchecks/InitialDelayChecker.java +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/healthchecks/InitialDelayChecker.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.appform.ranger.discovery.bundle.healthchecks; +package io.appform.ranger.discovery.common.healthchecks; import io.appform.ranger.core.healthcheck.Healthcheck; import io.appform.ranger.core.healthcheck.HealthcheckStatus; @@ -35,7 +35,7 @@ public InitialDelayChecker(long initialDelaySeconds) { @Override public HealthcheckStatus check() { return System.currentTimeMillis() > validRegistrationTime - ? HealthcheckStatus.healthy - : HealthcheckStatus.unhealthy; + ? HealthcheckStatus.healthy + : HealthcheckStatus.unhealthy; } } diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/healthchecks/InternalHealthChecker.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/healthchecks/InternalHealthChecker.java similarity index 95% rename from ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/healthchecks/InternalHealthChecker.java rename to ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/healthchecks/InternalHealthChecker.java index e91af9bb..5395e43c 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/healthchecks/InternalHealthChecker.java +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/healthchecks/InternalHealthChecker.java @@ -14,7 +14,8 @@ * limitations under the License. */ -package io.appform.ranger.discovery.bundle.healthchecks; +package io.appform.ranger.discovery.common.healthchecks; + import io.appform.ranger.core.healthcheck.Healthcheck; import io.appform.ranger.core.healthcheck.HealthcheckStatus; diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/healthchecks/RotationCheck.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/healthchecks/RotationCheck.java similarity index 84% rename from ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/healthchecks/RotationCheck.java rename to ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/healthchecks/RotationCheck.java index e22d4b86..12e4d966 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/healthchecks/RotationCheck.java +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/healthchecks/RotationCheck.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package io.appform.ranger.discovery.bundle.healthchecks; +package io.appform.ranger.discovery.common.healthchecks; import io.appform.ranger.core.healthcheck.Healthcheck; import io.appform.ranger.core.healthcheck.HealthcheckStatus; -import io.appform.ranger.discovery.bundle.rotationstatus.RotationStatus; +import io.appform.ranger.discovery.common.rotationstatus.RotationStatus; /** * This allows the node to be taken offline in the cluster but still keep running @@ -34,7 +34,7 @@ public RotationCheck(RotationStatus rotationStatus) { @Override public HealthcheckStatus check() { return (rotationStatus.status()) - ? HealthcheckStatus.healthy - : HealthcheckStatus.unhealthy; + ? HealthcheckStatus.healthy + : HealthcheckStatus.unhealthy; } } diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/monitors/DropwizardHealthMonitor.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/monitors/DropwizardHealthMonitor.java similarity index 75% rename from ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/monitors/DropwizardHealthMonitor.java rename to ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/monitors/DropwizardHealthMonitor.java index 29fd6ae2..6539e238 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/monitors/DropwizardHealthMonitor.java +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/monitors/DropwizardHealthMonitor.java @@ -14,38 +14,38 @@ * limitations under the License. */ -package io.appform.ranger.discovery.bundle.monitors; +package io.appform.ranger.discovery.common.monitors; import com.codahale.metrics.health.HealthCheck; +import com.codahale.metrics.health.HealthCheckRegistry; import io.appform.ranger.core.healthcheck.HealthcheckStatus; import io.appform.ranger.core.healthservice.TimeEntity; import io.appform.ranger.core.healthservice.monitor.IsolatedHealthMonitor; -import io.dropwizard.setup.Environment; /** * This monitor calls dropwizard healthchecks every few secs. */ public class DropwizardHealthMonitor extends IsolatedHealthMonitor { - private final Environment environment; + private final HealthCheckRegistry healthCheckRegistry; public DropwizardHealthMonitor( TimeEntity runInterval, long stalenessAllowedInMillis, - Environment environment) { + HealthCheckRegistry healthCheckRegistry) { super("dropwizard-health-monitor", runInterval, stalenessAllowedInMillis); - this.environment = environment; + this.healthCheckRegistry = healthCheckRegistry; } @Override public HealthcheckStatus monitor() { - return (null != environment.healthChecks() - && environment.healthChecks() + return (null != healthCheckRegistry + && healthCheckRegistry .runHealthChecks() .values() .stream() .allMatch(HealthCheck.Result::isHealthy)) - ? HealthcheckStatus.healthy - : HealthcheckStatus.unhealthy; + ? HealthcheckStatus.healthy + : HealthcheckStatus.unhealthy; } } diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/CriteriaResolver.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/resolvers/CriteriaResolver.java similarity index 94% rename from ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/CriteriaResolver.java rename to ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/resolvers/CriteriaResolver.java index f76ff6c0..3e72245a 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/CriteriaResolver.java +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/resolvers/CriteriaResolver.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.appform.ranger.discovery.bundle.resolvers; +package io.appform.ranger.discovery.common.resolvers; /** * CriteriaResolver.java diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/DefaultNodeInfoResolver.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/resolvers/DefaultNodeInfoResolver.java similarity index 92% rename from ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/DefaultNodeInfoResolver.java rename to ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/resolvers/DefaultNodeInfoResolver.java index 4df9d139..63867ed3 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/DefaultNodeInfoResolver.java +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/resolvers/DefaultNodeInfoResolver.java @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.appform.ranger.discovery.bundle.resolvers; +package io.appform.ranger.discovery.common.resolvers; import io.appform.ranger.common.server.ShardInfo; -import io.appform.ranger.discovery.bundle.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import lombok.val; diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/NodeInfoResolver.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/resolvers/NodeInfoResolver.java similarity index 89% rename from ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/NodeInfoResolver.java rename to ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/resolvers/NodeInfoResolver.java index acc9820a..8954dc36 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/resolvers/NodeInfoResolver.java +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/resolvers/NodeInfoResolver.java @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.appform.ranger.discovery.bundle.resolvers; +package io.appform.ranger.discovery.common.resolvers; import io.appform.ranger.common.server.ShardInfo; -import io.appform.ranger.discovery.bundle.ServiceDiscoveryConfiguration; +import io.appform.ranger.discovery.common.ServiceDiscoveryConfiguration; /** * NodeInfoResolver.java diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/DropwizardServerStatus.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/rotationstatus/DropwizardServerStatus.java similarity index 95% rename from ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/DropwizardServerStatus.java rename to ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/rotationstatus/DropwizardServerStatus.java index 4980e829..9a2ea6c2 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/DropwizardServerStatus.java +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/rotationstatus/DropwizardServerStatus.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.appform.ranger.discovery.bundle.rotationstatus; +package io.appform.ranger.discovery.common.rotationstatus; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/RotationStatus.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/rotationstatus/RotationStatus.java similarity index 94% rename from ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/RotationStatus.java rename to ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/rotationstatus/RotationStatus.java index 0ac9e052..755edb6e 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/rotationstatus/RotationStatus.java +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/rotationstatus/RotationStatus.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.appform.ranger.discovery.bundle.rotationstatus; +package io.appform.ranger.discovery.common.rotationstatus; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/selectors/HierarchicalEnvironmentAwareShardSelector.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/selectors/HierarchicalEnvironmentAwareShardSelector.java similarity index 94% rename from ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/selectors/HierarchicalEnvironmentAwareShardSelector.java rename to ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/selectors/HierarchicalEnvironmentAwareShardSelector.java index 743518aa..2cbe7f2d 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/selectors/HierarchicalEnvironmentAwareShardSelector.java +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/selectors/HierarchicalEnvironmentAwareShardSelector.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.appform.ranger.discovery.bundle.selectors; +package io.appform.ranger.discovery.common.selectors; import com.google.common.base.Strings; import io.appform.ranger.common.server.ShardInfo; @@ -57,8 +57,8 @@ public List> nodes( val serviceNodes = serviceRegistry.nodes(); val serviceName = serviceRegistry.getService().getServiceName(); val evalPredicate = null != criteria - ? criteria - : DEFAULT_PREDICATE; + ? criteria + : DEFAULT_PREDICATE; for (val env : new IterableEnvironment(environment, separator)) { val eligibleNodes = serviceNodes.entries() .stream() @@ -113,8 +113,8 @@ public IterableEnvironment next() { val shardInfo = new IterableEnvironment(remainingEnvironment, separator); val sepIndex = remainingEnvironment.lastIndexOf(this.separator); remainingEnvironment = sepIndex < 0 - ? "" - : remainingEnvironment.substring(0, sepIndex); + ? "" + : remainingEnvironment.substring(0, sepIndex); return shardInfo; } } diff --git a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/util/ConfigurationUtils.java b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/util/ConfigurationUtils.java similarity index 82% rename from ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/util/ConfigurationUtils.java rename to ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/util/ConfigurationUtils.java index 3e542165..fac7c93d 100644 --- a/ranger-discovery-bundle/src/main/java/io/appform/ranger/discovery/bundle/util/ConfigurationUtils.java +++ b/ranger-discovery-common/src/main/java/io/appform/ranger/discovery/common/util/ConfigurationUtils.java @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.appform.ranger.discovery.bundle.util; +package io.appform.ranger.discovery.common.util; import com.google.common.base.Strings; -import io.appform.ranger.discovery.bundle.Constants; +import io.appform.ranger.discovery.common.Constants; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -26,7 +26,9 @@ import java.util.Set; import java.util.stream.Collectors; -import static io.appform.ranger.discovery.bundle.Constants.*; +import static io.appform.ranger.discovery.common.Constants.HOST_PORT_DELIMITER; +import static io.appform.ranger.discovery.common.Constants.PATH_DELIMITER; +import static io.appform.ranger.discovery.common.Constants.ZOOKEEPER_HOST_DELIMITER; @NoArgsConstructor(access = AccessLevel.PRIVATE) diff --git a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/selectors/HierarchicalEnvironmentAwareShardSelectorTest.java b/ranger-discovery-common/src/test/java/io/appform/ranger/discovery/common/selectors/HierarchicalEnvironmentAwareShardSelectorTest.java similarity index 79% rename from ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/selectors/HierarchicalEnvironmentAwareShardSelectorTest.java rename to ranger-discovery-common/src/test/java/io/appform/ranger/discovery/common/selectors/HierarchicalEnvironmentAwareShardSelectorTest.java index 15f4376e..73bb4c1c 100644 --- a/ranger-discovery-bundle/src/test/java/io/appform/ranger/discovery/bundle/selectors/HierarchicalEnvironmentAwareShardSelectorTest.java +++ b/ranger-discovery-common/src/test/java/io/appform/ranger/discovery/common/selectors/HierarchicalEnvironmentAwareShardSelectorTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.appform.ranger.discovery.bundle.selectors; +package io.appform.ranger.discovery.common.selectors; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; @@ -45,7 +45,7 @@ class HierarchicalEnvironmentAwareShardSelectorTest { private MapBasedServiceRegistry serviceRegistry; @BeforeEach - public void setUp() { + void setUp() { MockitoAnnotations.openMocks(this); } @@ -60,20 +60,20 @@ void testNoNodeAvailableForTheEnvironment() { serviceNodes.put( ShardInfo.builder().environment("x.y").build(), new ServiceNode<>("host1", - 8888, - ShardInfo.builder().environment("x.y").build(), - HealthcheckStatus.healthy, - System.currentTimeMillis(), - "http")); + 8888, + ShardInfo.builder().environment("x.y").build(), + HealthcheckStatus.healthy, + System.currentTimeMillis(), + "http")); serviceNodes.put( ShardInfo.builder().environment("x").build(), new ServiceNode<>("host2", - 8888, - ShardInfo.builder().environment("x.y").build(), - HealthcheckStatus.healthy, - System.currentTimeMillis(), - "http")); + 8888, + ShardInfo.builder().environment("x.y").build(), + HealthcheckStatus.healthy, + System.currentTimeMillis(), + "http")); doReturn(serviceNodes).when(serviceRegistry).nodes(); @@ -92,19 +92,19 @@ void testNodeAvailableForChildEnv() { serviceNodes.put( ShardInfo.builder().environment("x.y").build(), new ServiceNode<>("host1", - 8888, - ShardInfo.builder().environment("x.y").build(), - HealthcheckStatus.healthy, - System.currentTimeMillis(), - "http")); + 8888, + ShardInfo.builder().environment("x.y").build(), + HealthcheckStatus.healthy, + System.currentTimeMillis(), + "http")); serviceNodes.put( ShardInfo.builder().environment("x").build(), new ServiceNode<>("host2", - 8888, - ShardInfo.builder().environment("x").build(), - HealthcheckStatus.healthy, - System.currentTimeMillis(), - "http")); + 8888, + ShardInfo.builder().environment("x").build(), + HealthcheckStatus.healthy, + System.currentTimeMillis(), + "http")); doReturn(serviceNodes).when(serviceRegistry).nodes(); val nodes = selector("x.y") @@ -129,19 +129,19 @@ void testNoNodeAvailableForChildEnvButAvailableForParentEnv() { serviceNodes.put( ShardInfo.builder().environment("x.y.z").build(), new ServiceNode<>("host1", - 8888, - ShardInfo.builder().environment("x.y").build(), - HealthcheckStatus.healthy, - System.currentTimeMillis(), - "http")); + 8888, + ShardInfo.builder().environment("x.y").build(), + HealthcheckStatus.healthy, + System.currentTimeMillis(), + "http")); serviceNodes.put( ShardInfo.builder().environment("x").build(), new ServiceNode<>("host2", - 9999, - ShardInfo.builder().environment("x").build(), - HealthcheckStatus.healthy, - System.currentTimeMillis(), - "http")); + 9999, + ShardInfo.builder().environment("x").build(), + HealthcheckStatus.healthy, + System.currentTimeMillis(), + "http")); doReturn(serviceNodes).when(serviceRegistry).nodes(); val nodes = selector("x.y").nodes(null, serviceRegistry); diff --git a/ranger-drove-client/pom.xml b/ranger-drove-client/pom.xml index 19eba185..e337771e 100644 --- a/ranger-drove-client/pom.xml +++ b/ranger-drove-client/pom.xml @@ -71,5 +71,4 @@ test - diff --git a/ranger-drove-client/src/main/java/io/appform/ranger/client/drove/SimpleRangerDroveClient.java b/ranger-drove-client/src/main/java/io/appform/ranger/client/drove/SimpleRangerDroveClient.java index 260ea421..25a7bc3d 100644 --- a/ranger-drove-client/src/main/java/io/appform/ranger/client/drove/SimpleRangerDroveClient.java +++ b/ranger-drove-client/src/main/java/io/appform/ranger/client/drove/SimpleRangerDroveClient.java @@ -69,7 +69,7 @@ public void start() { @Override public void stop() { log.info("Stopping the service finder"); - if(null != serviceFinder){ + if (null != serviceFinder) { this.serviceFinder.stop(); } } diff --git a/ranger-drove-client/src/test/java/io/appform/ranger/client/drove/BaseRangerDroveClientTest.java b/ranger-drove-client/src/test/java/io/appform/ranger/client/drove/BaseRangerDroveClientTest.java index 1b655966..78ac775a 100644 --- a/ranger-drove-client/src/test/java/io/appform/ranger/client/drove/BaseRangerDroveClientTest.java +++ b/ranger-drove-client/src/test/java/io/appform/ranger/client/drove/BaseRangerDroveClientTest.java @@ -34,7 +34,10 @@ import java.util.List; import java.util.Map; -import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.okJson; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; @Slf4j @@ -52,64 +55,64 @@ public abstract class BaseRangerDroveClientTest { @BeforeEach public void prepareHttpMocks() throws Exception { wireMockExtension.stubFor(get(urlPathEqualTo("/apis/v1/endpoints")) - .willReturn(aResponse() - .withBody(objectMapper.writeValueAsBytes( - ApiResponse.success(List.of(new ExposedAppInfo( - "TEST_APP", - "test-0.1", - "test.appform.io", - Map.of(), - List.of(new ExposedAppInfo.ExposedHost( - "executor001.internal", - 32456, - PortType.HTTP))))))) - .withStatus(200))); + .willReturn(aResponse() + .withBody(objectMapper.writeValueAsBytes( + ApiResponse.success(List.of(new ExposedAppInfo( + "TEST_APP", + "test-0.1", + "test.appform.io", + Map.of(), + List.of(new ExposedAppInfo.ExposedHost( + "executor001.internal", + 32456, + PortType.HTTP))))))) + .withStatus(200))); val response = ApiResponse.success(Map.of( "TEST_APP-1", new AppSummary("TEST_APP-1", - "TEST_APP", - 4, - 4, - 4, - 1024, - Map.of(), - ApplicationState.RUNNING, - new Date(), - new Date()), + "TEST_APP", + 4, + 4, + 4, + 1024, + Map.of(), + ApplicationState.RUNNING, + new Date(), + new Date()), "TEST_APP-2", new AppSummary("TEST_APP-2", - "TEST_APP", - 4, - 4, - 4, - 1024, - Map.of(), - ApplicationState.RUNNING, - new Date(), - new Date()), + "TEST_APP", + 4, + 4, + 4, + 1024, + Map.of(), + ApplicationState.RUNNING, + new Date(), + new Date()), "DEAD_APP-2", new AppSummary("DEAD_APP-2", - "DEAD_APP", - 0, - 0, - 4, - 1024, - Map.of(), - ApplicationState.MONITORING, - new Date(), - new Date()), + "DEAD_APP", + 0, + 0, + 4, + 1024, + Map.of(), + ApplicationState.MONITORING, + new Date(), + new Date()), "OTHER_APP-2", new AppSummary("OTHER_APP-2", - "OTHER_APP", - 4, - 4, - 4, - 1024, - Map.of(), - ApplicationState.RUNNING, - new Date(), - new Date()))); + "OTHER_APP", + 4, + 4, + 4, + 1024, + Map.of(), + ApplicationState.RUNNING, + new Date(), + new Date()))); wireMockExtension.stubFor(get("/apis/v1/applications").willReturn(okJson(objectMapper.writeValueAsString( response)))); diff --git a/ranger-drove-client/src/test/java/io/appform/ranger/client/drove/SimpleRangerDroveClientTest.java b/ranger-drove-client/src/test/java/io/appform/ranger/client/drove/SimpleRangerDroveClientTest.java index 5f233ae7..310c03d3 100644 --- a/ranger-drove-client/src/test/java/io/appform/ranger/client/drove/SimpleRangerDroveClientTest.java +++ b/ranger-drove-client/src/test/java/io/appform/ranger/client/drove/SimpleRangerDroveClientTest.java @@ -26,7 +26,7 @@ class SimpleRangerDroveClientTest extends BaseRangerDroveClientTest { @Test - void testSimpleDroveRangerClient(){ + void testSimpleDroveRangerClient() { val client = SimpleRangerDroveClient.builder() .clientConfig(getClientConfig()) .namespace("test") diff --git a/ranger-drove-client/src/test/java/io/appform/ranger/client/drove/UnshardedRangerDroveClientTest.java b/ranger-drove-client/src/test/java/io/appform/ranger/client/drove/UnshardedRangerDroveClientTest.java index 64019c98..deb7ce24 100644 --- a/ranger-drove-client/src/test/java/io/appform/ranger/client/drove/UnshardedRangerDroveClientTest.java +++ b/ranger-drove-client/src/test/java/io/appform/ranger/client/drove/UnshardedRangerDroveClientTest.java @@ -27,7 +27,7 @@ class UnshardedRangerDroveClientTest extends BaseRangerDroveClientTest { @Test - void testUnshardedRangerHubClient(){ + void testUnshardedRangerHubClient() { val clientConfig = getClientConfig(); val namespace = "test"; val client = UnshardedRangerDroveHubClient.builder() diff --git a/ranger-drove/pom.xml b/ranger-drove/pom.xml index 9d4c1163..a09fc64d 100644 --- a/ranger-drove/pom.xml +++ b/ranger-drove/pom.xml @@ -75,6 +75,11 @@ okhttp ${http.client.version} + + com.squareup.okhttp3 + logging-interceptor + ${http.client.version} + org.wiremock wiremock diff --git a/ranger-drove/src/main/java/io/appform/ranger/drove/DroveServiceFinderBuilders.java b/ranger-drove/src/main/java/io/appform/ranger/drove/DroveServiceFinderBuilders.java index 56460f01..146a20c3 100644 --- a/ranger-drove/src/main/java/io/appform/ranger/drove/DroveServiceFinderBuilders.java +++ b/ranger-drove/src/main/java/io/appform/ranger/drove/DroveServiceFinderBuilders.java @@ -16,18 +16,18 @@ package io.appform.ranger.drove; import io.appform.ranger.drove.servicefinder.DroveShardedServiceFinderBuilder; -import io.appform.ranger.drove.servicefinder.DroveUnshardedServiceFinderBuilider; +import io.appform.ranger.drove.servicefinder.DroveUnshardedServiceFinderBuilder; import lombok.experimental.UtilityClass; @UtilityClass @SuppressWarnings("unused") public final class DroveServiceFinderBuilders { - public static DroveShardedServiceFinderBuilder droveShardedServiceFinderBuilder(){ + public static DroveShardedServiceFinderBuilder droveShardedServiceFinderBuilder() { return new DroveShardedServiceFinderBuilder<>(); } - public static DroveUnshardedServiceFinderBuilider droveUnshardedServiceFinderBuilider(){ - return new DroveUnshardedServiceFinderBuilider<>(); + public static DroveUnshardedServiceFinderBuilder droveUnshardedServiceFinderBuilider() { + return new DroveUnshardedServiceFinderBuilder<>(); } } diff --git a/ranger-drove/src/main/java/io/appform/ranger/drove/common/DroveApiCommunicator.java b/ranger-drove/src/main/java/io/appform/ranger/drove/common/DroveApiCommunicator.java index 0bfdeee7..04434a22 100644 --- a/ranger-drove/src/main/java/io/appform/ranger/drove/common/DroveApiCommunicator.java +++ b/ranger-drove/src/main/java/io/appform/ranger/drove/common/DroveApiCommunicator.java @@ -31,7 +31,7 @@ import io.appform.ranger.drove.config.DroveUpstreamConfig; import lombok.extern.slf4j.Slf4j; import lombok.val; -import org.apache.http.HttpStatus; +import org.apache.hc.core5.http.HttpStatus; import java.util.List; import java.util.Map; @@ -133,45 +133,44 @@ public Map> listNodes(Iterable log.debug("Loading nodes list for services: {}", Lists.newArrayList(services)); val url = String.format("/apis/v1/endpoints?%s", Joiner.on("&") .join(StreamSupport.stream(services.spliterator(), false) - .map(service -> "app=" + service.getServiceName()) - .toList())); + .map(service -> "app=" + service.getServiceName()) + .toList())); logUrl(url); return executeRemoteCall(() -> droveClient.execute(new DroveClient.Request(DroveClient.Method.GET, url), - new DroveClient.ResponseHandler<>() { - @Override - public Map> defaultValue() { - throw new IllegalStateException("Default value should not be used here"); - } - - @Override - public Map> handle(DroveClient.Response response) throws Exception { - if (response.statusCode() != HttpStatus.SC_OK) { - throwDroveCommError(response); - } - val apiResponse = mapper.readValue(response.body(), - new TypeReference>>() { - }); - if (!apiResponse.getStatus().equals(ApiErrorCode.SUCCESS)) { - throwDroveCommError(response); - } - val data = Objects.requireNonNullElse(apiResponse.getData(), - List.of()); - return data.stream() - .filter(appInfo -> !Strings.isNullOrEmpty(appInfo.getAppName())) - .collect(Collectors.groupingBy( - appInfo -> new Service(namespace, appInfo.getAppName()), - Collectors.toList())); - } - })); + new DroveClient.ResponseHandler<>() { + @Override + public Map> defaultValue() { + throw new IllegalStateException("Default value should not be used here"); + } + + @Override + public Map> handle(DroveClient.Response response) throws Exception { + if (response.statusCode() != HttpStatus.SC_OK) { + throwDroveCommError(response); + } + val apiResponse = mapper.readValue(response.body(), + new TypeReference>>() { + }); + if (!apiResponse.getStatus().equals(ApiErrorCode.SUCCESS)) { + throwDroveCommError(response); + } + val data = Objects.requireNonNullElse(apiResponse.getData(), + List.of()); + return data.stream() + .filter(appInfo -> !Strings.isNullOrEmpty(appInfo.getAppName())) + .collect(Collectors.groupingBy( + appInfo -> new Service(namespace, appInfo.getAppName()), + Collectors.toList())); + } + })); } private T executeRemoteCall(Supplier executor) { upstreamAvailable.set(true); try { return executor.get(); - } - catch (DroveCommunicationException e) { + } catch (DroveCommunicationException e) { upstreamAvailable.set(false); throw e; } diff --git a/ranger-drove/src/main/java/io/appform/ranger/drove/common/DroveCachingCommunicator.java b/ranger-drove/src/main/java/io/appform/ranger/drove/common/DroveCachingCommunicator.java index 892a39ec..7905e86b 100644 --- a/ranger-drove/src/main/java/io/appform/ranger/drove/common/DroveCachingCommunicator.java +++ b/ranger-drove/src/main/java/io/appform/ranger/drove/common/DroveCachingCommunicator.java @@ -41,7 +41,11 @@ import org.checkerframework.checker.nullness.qual.Nullable; import java.time.Duration; -import java.util.*; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; /** * This is an optimization to reduce upstream service calls @@ -68,8 +72,8 @@ public DroveCachingCommunicator( .mapper(mapper) .offsetStore(offsetStore) .pollInterval(Objects.requireNonNullElse(config.getEventPollingInterval(), - DroveUpstreamConfig.DEFAULT_EVENT_POLLING_INTERVAL) - .toJavaDuration()) + DroveUpstreamConfig.DEFAULT_EVENT_POLLING_INTERVAL) + .toJavaDuration()) .build(); this.cache = Caffeine.newBuilder() .expireAfterWrite(Duration.ofSeconds(45)) //Delete the data after 45 secs. Will lead to sync refresh @@ -89,9 +93,9 @@ public DroveCachingCommunicator( }); val relevantEvents = EnumSet.of(DroveEventType.APP_STATE_CHANGE, DroveEventType.INSTANCE_STATE_CHANGE); Lists.partition(Objects.requireNonNullElse(services(), List.of()) - .stream() - .map(name -> new Service(namespace, name)) - .toList(), 10) + .stream() + .map(name -> new Service(namespace, name)) + .toList(), 10) .forEach(cache::getAll); log.info("Batch loading completed"); listener.onEventReceived().connect(events -> handleEvents(namespace, events, relevantEvents)); diff --git a/ranger-drove/src/main/java/io/appform/ranger/drove/common/DroveOkHttpTransport.java b/ranger-drove/src/main/java/io/appform/ranger/drove/common/DroveOkHttpTransport.java index 928a91a1..e0340aa2 100644 --- a/ranger-drove/src/main/java/io/appform/ranger/drove/common/DroveOkHttpTransport.java +++ b/ranger-drove/src/main/java/io/appform/ranger/drove/common/DroveOkHttpTransport.java @@ -58,16 +58,15 @@ public T get( try (val response = httpClient.newCall(request).execute()) { val body = response.body(); var strResponse = body != null ? body.string() : null; - if(!response.isSuccessful()) { + if (!response.isSuccessful()) { log.error("Error calling drove api {}: Status: {} Body: {}", - uri, response.code(), strResponse); + uri, response.code(), strResponse); } val droveResponse = new DroveClient.Response(response.code(), - response.headers().toMultimap(), - strResponse); + response.headers().toMultimap(), + strResponse); return responseHandler.handle(droveResponse); - } - catch (Exception e) { + } catch (Exception e) { log.error("Error calling drove: {}. Error: {}", e.getMessage(), e.getClass().getSimpleName()); throw new DroveCommunicationException(e.getMessage()); } diff --git a/ranger-drove/src/main/java/io/appform/ranger/drove/serde/DroveResponseDataDeserializer.java b/ranger-drove/src/main/java/io/appform/ranger/drove/serde/DroveResponseDataDeserializer.java index 53441f4a..18d370c1 100644 --- a/ranger-drove/src/main/java/io/appform/ranger/drove/serde/DroveResponseDataDeserializer.java +++ b/ranger-drove/src/main/java/io/appform/ranger/drove/serde/DroveResponseDataDeserializer.java @@ -34,21 +34,21 @@ public final List> deserialize(List appInfo) { val currTime = System.currentTimeMillis(); return appInfo.stream() .flatMap(appEndpoints -> - appEndpoints.getHosts() - .stream() - .map(endpoint -> { - val info = translate(appEndpoints, endpoint); - if(null == info) { - log.debug("Could not create data for service node: {}", endpoint); - return null; - } - return new ServiceNode<>(endpoint.getHost(), - endpoint.getPort(), - info, - HealthcheckStatus.healthy, - currTime, - endpoint.getPortType().name()); - })) + appEndpoints.getHosts() + .stream() + .map(endpoint -> { + val info = translate(appEndpoints, endpoint); + if (null == info) { + log.debug("Could not create data for service node: {}", endpoint); + return null; + } + return new ServiceNode<>(endpoint.getHost(), + endpoint.getPort(), + info, + HealthcheckStatus.healthy, + currTime, + endpoint.getPortType().name()); + })) .filter(Objects::nonNull) .toList(); } diff --git a/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveNodeDataSource.java b/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveNodeDataSource.java index dc266d2a..43c65761 100644 --- a/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveNodeDataSource.java +++ b/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveNodeDataSource.java @@ -58,8 +58,7 @@ public Optional>> refresh(D deserializer) { val nodes = deserializer.deserialize( Objects.requireNonNull(exposedAppInfos, "Unexpected empty response from server")); return Optional.of(nodes); - } - catch (DroveCommunicationException e) { + } catch (DroveCommunicationException e) { log.error("Drove communication error", e); return Optional.empty(); //In case of refresh failure, maintain old list } diff --git a/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveShardedServiceFinderBuilder.java b/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveShardedServiceFinderBuilder.java index fb6071fb..46b681c0 100644 --- a/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveShardedServiceFinderBuilder.java +++ b/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveShardedServiceFinderBuilder.java @@ -20,9 +20,9 @@ import io.appform.ranger.core.finder.SimpleShardedServiceFinderBuilder; import io.appform.ranger.core.model.NodeDataSource; import io.appform.ranger.core.model.Service; +import io.appform.ranger.drove.common.DroveCommunicator; import io.appform.ranger.drove.config.DroveUpstreamConfig; import io.appform.ranger.drove.serde.DroveResponseDataDeserializer; -import io.appform.ranger.drove.common.DroveCommunicator; import io.appform.ranger.drove.utils.RangerDroveUtils; import java.util.Objects; @@ -61,9 +61,9 @@ public SimpleShardedServiceFinder build() { @Override protected NodeDataSource> dataSource(Service service) { return new DroveNodeDataSource<>(service, clientConfig, mapper, - Objects.requireNonNullElseGet(droveClient, - () -> RangerDroveUtils.buildDroveClient( - namespace, clientConfig, mapper))); + Objects.requireNonNullElseGet(droveClient, + () -> RangerDroveUtils.buildDroveClient( + namespace, clientConfig, mapper))); } } diff --git a/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveUnshardedServiceFinderBuilider.java b/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveUnshardedServiceFinderBuilder.java similarity index 79% rename from ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveUnshardedServiceFinderBuilider.java rename to ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveUnshardedServiceFinderBuilder.java index 87cff3c4..062713f0 100644 --- a/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveUnshardedServiceFinderBuilider.java +++ b/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinder/DroveUnshardedServiceFinderBuilder.java @@ -20,32 +20,32 @@ import io.appform.ranger.core.finder.SimpleUnshardedServiceFinderBuilder; import io.appform.ranger.core.model.NodeDataSource; import io.appform.ranger.core.model.Service; +import io.appform.ranger.drove.common.DroveCommunicator; import io.appform.ranger.drove.config.DroveUpstreamConfig; import io.appform.ranger.drove.serde.DroveResponseDataDeserializer; -import io.appform.ranger.drove.common.DroveCommunicator; import io.appform.ranger.drove.utils.RangerDroveUtils; import java.util.Objects; -public class DroveUnshardedServiceFinderBuilider - extends SimpleUnshardedServiceFinderBuilder, +public class DroveUnshardedServiceFinderBuilder + extends SimpleUnshardedServiceFinderBuilder, DroveResponseDataDeserializer> { private DroveUpstreamConfig clientConfig; private ObjectMapper mapper; private DroveCommunicator droveCommunicator; - public DroveUnshardedServiceFinderBuilider withDroveCommunicator(final DroveCommunicator droveClient) { + public DroveUnshardedServiceFinderBuilder withDroveCommunicator(final DroveCommunicator droveClient) { this.droveCommunicator = droveClient; return this; } - public DroveUnshardedServiceFinderBuilider withClientConfig(final DroveUpstreamConfig clientConfig) { + public DroveUnshardedServiceFinderBuilder withClientConfig(final DroveUpstreamConfig clientConfig) { this.clientConfig = clientConfig; return this; } - public DroveUnshardedServiceFinderBuilider withObjectMapper(final ObjectMapper mapper) { + public DroveUnshardedServiceFinderBuilder withObjectMapper(final ObjectMapper mapper) { this.mapper = mapper; return this; } @@ -62,7 +62,7 @@ protected NodeDataSource> dataSource(Service clientConfig, mapper, Objects.requireNonNullElseGet(droveCommunicator, - () -> RangerDroveUtils.buildDroveClient(namespace, clientConfig, mapper))); + () -> RangerDroveUtils.buildDroveClient(namespace, clientConfig, mapper))); } } diff --git a/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinderhub/DroveServiceDataSource.java b/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinderhub/DroveServiceDataSource.java index f303dcdd..3533eeeb 100644 --- a/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinderhub/DroveServiceDataSource.java +++ b/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinderhub/DroveServiceDataSource.java @@ -19,9 +19,9 @@ import com.google.common.base.Preconditions; import io.appform.ranger.core.finderhub.ServiceDataSource; import io.appform.ranger.core.model.Service; +import io.appform.ranger.drove.common.DroveCommunicator; import io.appform.ranger.drove.common.DroveNodeDataStoreConnector; import io.appform.ranger.drove.config.DroveUpstreamConfig; -import io.appform.ranger.drove.common.DroveCommunicator; import lombok.extern.slf4j.Slf4j; import java.util.Collection; diff --git a/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinderhub/DroveShardedServiceFinderFactory.java b/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinderhub/DroveShardedServiceFinderFactory.java index cb83841e..932be739 100644 --- a/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinderhub/DroveShardedServiceFinderFactory.java +++ b/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinderhub/DroveShardedServiceFinderFactory.java @@ -22,10 +22,10 @@ import io.appform.ranger.core.model.Service; import io.appform.ranger.core.model.ServiceNodeSelector; import io.appform.ranger.core.model.ShardSelector; +import io.appform.ranger.drove.common.DroveCommunicator; import io.appform.ranger.drove.config.DroveUpstreamConfig; import io.appform.ranger.drove.serde.DroveResponseDataDeserializer; import io.appform.ranger.drove.servicefinder.DroveShardedServiceFinderBuilder; -import io.appform.ranger.drove.common.DroveCommunicator; import lombok.Builder; import lombok.val; @@ -47,8 +47,7 @@ public DroveShardedServiceFinderFactory( DroveResponseDataDeserializer deserializer, ShardSelector> shardSelector, ServiceNodeSelector nodeSelector, - int nodeRefreshIntervalMs) - { + int nodeRefreshIntervalMs) { this.clientConfig = droveConfig; this.droveClient = droveClient; this.mapper = mapper; diff --git a/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinderhub/DroveUnshardedServiceFinderFactory.java b/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinderhub/DroveUnshardedServiceFinderFactory.java index 3bf4c505..cca73d0f 100644 --- a/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinderhub/DroveUnshardedServiceFinderFactory.java +++ b/ranger-drove/src/main/java/io/appform/ranger/drove/servicefinderhub/DroveUnshardedServiceFinderFactory.java @@ -22,10 +22,10 @@ import io.appform.ranger.core.model.Service; import io.appform.ranger.core.model.ServiceNodeSelector; import io.appform.ranger.core.model.ShardSelector; +import io.appform.ranger.drove.common.DroveCommunicator; import io.appform.ranger.drove.config.DroveUpstreamConfig; import io.appform.ranger.drove.serde.DroveResponseDataDeserializer; -import io.appform.ranger.drove.servicefinder.DroveUnshardedServiceFinderBuilider; -import io.appform.ranger.drove.common.DroveCommunicator; +import io.appform.ranger.drove.servicefinder.DroveUnshardedServiceFinderBuilder; import lombok.Builder; import lombok.val; @@ -47,8 +47,7 @@ public DroveUnshardedServiceFinderFactory( DroveResponseDataDeserializer deserializer, ShardSelector> shardSelector, ServiceNodeSelector nodeSelector, - int nodeRefreshIntervalMs) - { + int nodeRefreshIntervalMs) { this.clientConfig = droveConfig; this.droveCommunicator = droveCommunicator; this.mapper = mapper; @@ -60,7 +59,7 @@ public DroveUnshardedServiceFinderFactory( @Override public ServiceFinder> buildFinder(Service service) { - val serviceFinder = new DroveUnshardedServiceFinderBuilider() + val serviceFinder = new DroveUnshardedServiceFinderBuilder() .withClientConfig(clientConfig) .withDroveCommunicator(droveCommunicator) .withObjectMapper(mapper) diff --git a/ranger-drove/src/main/java/io/appform/ranger/drove/utils/RangerDroveUtils.java b/ranger-drove/src/main/java/io/appform/ranger/drove/utils/RangerDroveUtils.java index 96f6143f..5172b973 100644 --- a/ranger-drove/src/main/java/io/appform/ranger/drove/utils/RangerDroveUtils.java +++ b/ranger-drove/src/main/java/io/appform/ranger/drove/utils/RangerDroveUtils.java @@ -49,25 +49,26 @@ public class RangerDroveUtils { - @SneakyThrows public static OkHttpClient createOkHttpClient(final DroveUpstreamConfig config) { val connectionTimeout = Objects.requireNonNullElse(config.getConnectionTimeout(), - DroveUpstreamConfig.DEFAULT_CONNECTION_TIMEOUT) + DroveUpstreamConfig.DEFAULT_CONNECTION_TIMEOUT) .toJavaDuration(); val operationTimeout = Objects.requireNonNullElse(config.getOperationTimeout(), - DroveUpstreamConfig.DEFAULT_OPERATION_TIMEOUT).toJavaDuration(); + DroveUpstreamConfig.DEFAULT_OPERATION_TIMEOUT).toJavaDuration(); val okHttpBuilder = new OkHttpClient.Builder(); - if(config.isInsecure()) { + if (config.isInsecure()) { val trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) { + // Trust all client certificates } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) { + // Trust all server certificates } @Override @@ -96,29 +97,27 @@ public static DroveCommunicator buildDroveClient( log.info("Building drove client for: {}", config.getEndpoints()); final var droveConfig = convertToDCConfig(config); final var droveClient = new DroveClient(droveConfig, - List.of(new BasicAuthDecorator(config.getUsername(), - config.getPassword()), - new AuthHeaderDecorator(config.getAuthHeader())), - new DroveOkHttpTransport(createOkHttpClient(config))); -// new DroveHttpComponentsTransport(droveConfig, -// createHttpClient(config))); + List.of(new BasicAuthDecorator(config.getUsername(), + config.getPassword()), + new AuthHeaderDecorator(config.getAuthHeader())), + new DroveOkHttpTransport(createOkHttpClient(config))); val apiCommunicator = new DroveApiCommunicator(namespace, config, droveClient, mapper); return config.isSkipCaching() - ? apiCommunicator - : new DroveCachingCommunicator(apiCommunicator, namespace, config, droveClient, mapper); + ? apiCommunicator + : new DroveCachingCommunicator(apiCommunicator, namespace, config, droveClient, mapper); } @NotNull public static DroveClientConfig convertToDCConfig(DroveUpstreamConfig config) { return new DroveClientConfig(config.getEndpoints(), - Objects.requireNonNullElse(config.getCheckInterval(), - DroveUpstreamConfig.DEFAULT_CHECK_INTERVAL) - .toJavaDuration(), - Objects.requireNonNullElse(config.getConnectionTimeout(), - DroveUpstreamConfig.DEFAULT_CONNECTION_TIMEOUT) - .toJavaDuration(), - Objects.requireNonNullElse(config.getOperationTimeout(), - DroveUpstreamConfig.DEFAULT_OPERATION_TIMEOUT) - .toJavaDuration()); + Objects.requireNonNullElse(config.getCheckInterval(), + DroveUpstreamConfig.DEFAULT_CHECK_INTERVAL) + .toJavaDuration(), + Objects.requireNonNullElse(config.getConnectionTimeout(), + DroveUpstreamConfig.DEFAULT_CONNECTION_TIMEOUT) + .toJavaDuration(), + Objects.requireNonNullElse(config.getOperationTimeout(), + DroveUpstreamConfig.DEFAULT_OPERATION_TIMEOUT) + .toJavaDuration()); } } diff --git a/ranger-drove/src/test/java/io/appform/ranger/drove/common/DroveApiCommunicatorTest.java b/ranger-drove/src/test/java/io/appform/ranger/drove/common/DroveApiCommunicatorTest.java index f9fd54e3..9aefd9f6 100644 --- a/ranger-drove/src/test/java/io/appform/ranger/drove/common/DroveApiCommunicatorTest.java +++ b/ranger-drove/src/test/java/io/appform/ranger/drove/common/DroveApiCommunicatorTest.java @@ -37,8 +37,15 @@ import java.util.Map; import java.util.function.Consumer; -import static com.github.tomakehurst.wiremock.client.WireMock.*; -import static org.junit.jupiter.api.Assertions.*; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.okJson; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * Tests for api based communicator @@ -54,65 +61,65 @@ void testSuccess(final WireMockRuntimeInfo wm) { val response = ApiResponse.success(Map.of( "TEST_APP-1", new AppSummary("TEST_APP-1", - "TEST_APP", - 4, - 4, - 4, - 1024, - Map.of(), - ApplicationState.RUNNING, - new Date(), - new Date()), + "TEST_APP", + 4, + 4, + 4, + 1024, + Map.of(), + ApplicationState.RUNNING, + new Date(), + new Date()), "TEST_APP-2", new AppSummary("TEST_APP-2", - "TEST_APP", - 4, - 4, - 4, - 1024, - Map.of(), - ApplicationState.RUNNING, - new Date(), - new Date()), + "TEST_APP", + 4, + 4, + 4, + 1024, + Map.of(), + ApplicationState.RUNNING, + new Date(), + new Date()), "DEAD_APP-2", new AppSummary("DEAD_APP-2", - "DEAD_APP", - 0, - 0, - 4, - 1024, - Map.of(), - ApplicationState.MONITORING, - new Date(), - new Date()), + "DEAD_APP", + 0, + 0, + 4, + 1024, + Map.of(), + ApplicationState.MONITORING, + new Date(), + new Date()), "OTHER_APP-2", new AppSummary("OTHER_APP-2", - "OTHER_APP", - 4, - 4, - 4, - 1024, - Map.of(), - ApplicationState.RUNNING, - new Date(), - new Date()))); + "OTHER_APP", + 4, + 4, + 4, + 1024, + Map.of(), + ApplicationState.RUNNING, + new Date(), + new Date()))); stubFor(get("/apis/v1/applications") - .withBasicAuth("guest", "guest") - .willReturn(okJson(MAPPER.writeValueAsString( - response)))); + .withBasicAuth("guest", "guest") + .willReturn(okJson(MAPPER.writeValueAsString( + response)))); stubFor(get(urlPathEqualTo("/apis/v1/endpoints")) - .willReturn(aResponse() - .withBody(MAPPER.writeValueAsBytes( - ApiResponse.success(List.of(new ExposedAppInfo( - "TEST_APP", - "test-0.1", - "test.appform.io", - Map.of(), - List.of(new ExposedAppInfo.ExposedHost( - "executor001.internal", - 32456, - PortType.HTTP))))))) - .withStatus(200))); + .willReturn(aResponse() + .withBody(MAPPER.writeValueAsBytes( + ApiResponse.success(List.of(new ExposedAppInfo( + "TEST_APP", + "test-0.1", + "test.appform.io", + Map.of(), + List.of(new ExposedAppInfo.ExposedHost( + "executor001.internal", + 32456, + PortType.HTTP))))))) + .withStatus(200))); try (val client = RangerDroveUtils.buildDroveClient( "testns", DroveUpstreamConfig.builder() @@ -127,15 +134,15 @@ void testSuccess(final WireMockRuntimeInfo wm) { assertFalse(services.isEmpty()); assertEquals(2, services.size()); assertFalse(client.listNodes(Service.builder() - .namespace("testns") - .serviceName("TEST_APP") - .build()) - .isEmpty()); + .namespace("testns") + .serviceName("TEST_APP") + .build()) + .isEmpty()); assertTrue(client.listNodes(Service.builder() - .namespace("testns") - .serviceName("OTHER_APP") - .build()) - .isEmpty()); + .namespace("testns") + .serviceName("OTHER_APP") + .build()) + .isEmpty()); } } @@ -143,7 +150,7 @@ void testSuccess(final WireMockRuntimeInfo wm) { @Test void testServicesAuthFail(final WireMockRuntimeInfo wm) { testAuthFail(wm, "/apis/v1/applications", - client -> assertThrows(DroveCommunicationException.class, client::services)); + client -> assertThrows(DroveCommunicationException.class, client::services)); } @Test @@ -153,15 +160,15 @@ void testLoadAuthFail(final WireMockRuntimeInfo wm) { .serviceName("TEST_APP") .build(); testAuthFail(wm, "/apis/v1/endpoints", - client -> assertThrows(DroveCommunicationException.class, - () -> client.listNodes(service))); + client -> assertThrows(DroveCommunicationException.class, + () -> client.listNodes(service))); } @Test @SneakyThrows void testServicesNetworkError(final WireMockRuntimeInfo wm) { testNetworkFail(wm, "/apis/v1/applications", - client -> assertThrows(DroveCommunicationException.class, client::services)); + client -> assertThrows(DroveCommunicationException.class, client::services)); } @Test @@ -171,13 +178,14 @@ void testLoadNetworkFail(final WireMockRuntimeInfo wm) { .serviceName("TEST_APP") .build(); testNetworkFail(wm, "/apis/v1/endpoints", - client -> assertThrows(DroveCommunicationException.class, - () -> client.listNodes(service))); + client -> assertThrows(DroveCommunicationException.class, + () -> client.listNodes(service))); } + @Test void testServiceApiFail(final WireMockRuntimeInfo wm) { testApiFail(wm, "/apis/v1/applications", - client -> assertThrows(DroveCommunicationException.class, client::services)); + client -> assertThrows(DroveCommunicationException.class, client::services)); } @Test @@ -187,7 +195,7 @@ void testLoadApiFail(final WireMockRuntimeInfo wm) { .serviceName("TEST_APP") .build(); testApiFail(wm, "/apis/v1/endpoints", - client -> assertThrows(DroveCommunicationException.class, () -> client.listNodes(service))); + client -> assertThrows(DroveCommunicationException.class, () -> client.listNodes(service))); } @@ -197,9 +205,9 @@ private void testAuthFail( final String api, Consumer test) { stubFor(get(urlPathEqualTo(api)) - .withBasicAuth("guest", "guest") - .willReturn(okJson(MAPPER.writeValueAsString( - ApiResponse.success(List.of()))))); + .withBasicAuth("guest", "guest") + .willReturn(okJson(MAPPER.writeValueAsString( + ApiResponse.success(List.of()))))); try (val client = RangerDroveUtils.buildDroveClient( "testns", DroveUpstreamConfig.builder() @@ -220,9 +228,9 @@ private void testApiFail( final String api, Consumer test) { stubFor(get(urlPathEqualTo(api)) - .withBasicAuth("guest", "guest") - .willReturn(okJson(MAPPER.writeValueAsString( - ApiResponse.failure("Emotional Damage!!"))))); + .withBasicAuth("guest", "guest") + .willReturn(okJson(MAPPER.writeValueAsString( + ApiResponse.failure("Emotional Damage!!"))))); try (val client = RangerDroveUtils.buildDroveClient( "testns", DroveUpstreamConfig.builder() @@ -243,8 +251,8 @@ private void testNetworkFail( final String api, Consumer test) { stubFor(get(urlPathEqualTo(api)) - .withBasicAuth("guest", "guest") - .willReturn(aResponse().withFault(Fault.MALFORMED_RESPONSE_CHUNK))); + .withBasicAuth("guest", "guest") + .willReturn(aResponse().withFault(Fault.MALFORMED_RESPONSE_CHUNK))); try (val client = RangerDroveUtils.buildDroveClient( "testns", DroveUpstreamConfig.builder() diff --git a/ranger-drove/src/test/java/io/appform/ranger/drove/common/DroveCachingCommunicatorTest.java b/ranger-drove/src/test/java/io/appform/ranger/drove/common/DroveCachingCommunicatorTest.java index d3316ab9..726aa89e 100644 --- a/ranger-drove/src/test/java/io/appform/ranger/drove/common/DroveCachingCommunicatorTest.java +++ b/ranger-drove/src/test/java/io/appform/ranger/drove/common/DroveCachingCommunicatorTest.java @@ -47,9 +47,15 @@ import java.util.Map; import java.util.Set; -import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.okJson; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.fail; /** * Tests for api based communicator @@ -61,12 +67,12 @@ class DroveCachingCommunicatorTest { @RegisterExtension private static final WireMockExtension extension = WireMockExtension.newInstance() .options(wireMockConfig() - .dynamicPort() - .extensions(new StateSetter())) + .dynamicPort() + .extensions(new StateSetter())) .build(); @AfterAll - public static void shutdown() { + static void shutdown() { extension.shutdownServer(); } @@ -85,9 +91,9 @@ void testSuccess() { assertFalse(services.isEmpty()); assertEquals(2, services.size()); assertFalse(client.listNodes(Service.builder() - .namespace("testns") - .serviceName("TEST_APP") - .build()).isEmpty()); + .namespace("testns") + .serviceName("TEST_APP") + .build()).isEmpty()); } } @@ -112,41 +118,41 @@ public String getName() { void testEventDrivenLoading() { val config = config(); extension.stubFor(get(urlPathEqualTo("/apis/v1/applications")) - .willReturn(okJson(toJson(ApiResponse.success(Map.of()))))); + .willReturn(okJson(toJson(ApiResponse.success(Map.of()))))); extension.stubFor(get(urlPathEqualTo("/apis/v1/cluster/events")) - .withServeEventListener( - Set.of(ServeEventListener.RequestPhase.AFTER_COMPLETE), - "state_setter", - Map.of()) - .willReturn(okJson(toJson( - ApiResponse.success( - List.of(new DroveAppStateChangeEvent( - Map.of(AppEventDataTag.APP_NAME, "TEST_APP")))))))); + .withServeEventListener( + Set.of(ServeEventListener.RequestPhase.AFTER_COMPLETE), + "state_setter", + Map.of()) + .willReturn(okJson(toJson( + ApiResponse.success( + List.of(new DroveAppStateChangeEvent( + Map.of(AppEventDataTag.APP_NAME, "TEST_APP")))))))); extension.stubFor(get(urlPathEqualTo("/apis/v1/endpoints")) - .inScenario("EventDrivenLoading") - .whenScenarioStateIs("BEFORE_EVENT") - .willReturn(okJson(toJson(ApiResponse.success(List.of()))))); + .inScenario("EventDrivenLoading") + .whenScenarioStateIs("BEFORE_EVENT") + .willReturn(okJson(toJson(ApiResponse.success(List.of()))))); extension.stubFor(get(urlPathEqualTo("/apis/v1/endpoints")) - .inScenario("EventDrivenLoading") - .whenScenarioStateIs("AFTER_EVENT") - .willReturn(aResponse() - .withBody(toJson( - ApiResponse.success(List.of(new ExposedAppInfo( - "TEST_APP", - "test-0.1", - "test.appform.io", - Map.of(), - List.of(new ExposedAppInfo.ExposedHost( - "executor001.internal", - 32456, - PortType.HTTP))))))) - .withStatus(200))); + .inScenario("EventDrivenLoading") + .whenScenarioStateIs("AFTER_EVENT") + .willReturn(aResponse() + .withBody(toJson( + ApiResponse.success(List.of(new ExposedAppInfo( + "TEST_APP", + "test-0.1", + "test.appform.io", + Map.of(), + List.of(new ExposedAppInfo.ExposedHost( + "executor001.internal", + 32456, + PortType.HTTP))))))) + .withStatus(200))); extension.setScenarioState("EventDrivenLoading", "BEFORE_EVENT"); try (val comm = RangerDroveUtils.buildDroveClient("testns", - config, - MAPPER)) { + config, + MAPPER)) { val service = Service.builder() .namespace("testns") .serviceName("TEST_APP") @@ -161,12 +167,12 @@ void testEventDrivenLoading() { void testServiceCommFailure() { setupNetworkError("/apis/v1/applications"); assertThrows(DroveCommunicationException.class, - () -> { - try (val dc = RangerDroveUtils.buildDroveClient( - "testns", config(), MAPPER)) { - fail("Should not have come here"); - } - }); + () -> { + try (val dc = RangerDroveUtils.buildDroveClient( + "testns", config(), MAPPER)) { + fail("Should not have come here"); + } + }); } @Test @@ -175,12 +181,12 @@ void testBulkLoadCommFailure() { setupAppsResponse(); setupNetworkError("/apis/v1/endpoints"); assertThrows(DroveCommunicationException.class, - () -> { - try (val dc = RangerDroveUtils.buildDroveClient( - "testns", config, MAPPER)) { - fail("Should not have come here"); - } - }); + () -> { + try (val dc = RangerDroveUtils.buildDroveClient( + "testns", config, MAPPER)) { + fail("Should not have come here"); + } + }); } @@ -208,18 +214,18 @@ private static DroveUpstreamConfig config() { @SneakyThrows private static void setupEndpointsResponse() { extension.stubFor(get(urlPathEqualTo("/apis/v1/endpoints")) - .willReturn(aResponse() - .withBody(toJson( - ApiResponse.success(List.of(new ExposedAppInfo( - "TEST_APP", - "test-0.1", - "test.appform.io", - Map.of(), - List.of(new ExposedAppInfo.ExposedHost( - "executor001.internal", - 32456, - PortType.HTTP))))))) - .withStatus(200))); + .willReturn(aResponse() + .withBody(toJson( + ApiResponse.success(List.of(new ExposedAppInfo( + "TEST_APP", + "test-0.1", + "test.appform.io", + Map.of(), + List.of(new ExposedAppInfo.ExposedHost( + "executor001.internal", + 32456, + PortType.HTTP))))))) + .withStatus(200))); } @SneakyThrows @@ -227,57 +233,57 @@ private static void setupAppsResponse() { val response = ApiResponse.success(Map.of( "TEST_APP-1", new AppSummary("TEST_APP-1", - "TEST_APP", - 4, - 4, - 4, - 1024, - Map.of(), - ApplicationState.RUNNING, - new Date(), - new Date()), + "TEST_APP", + 4, + 4, + 4, + 1024, + Map.of(), + ApplicationState.RUNNING, + new Date(), + new Date()), "TEST_APP-2", new AppSummary("TEST_APP-2", - "TEST_APP", - 4, - 4, - 4, - 1024, - Map.of(), - ApplicationState.RUNNING, - new Date(), - new Date()), + "TEST_APP", + 4, + 4, + 4, + 1024, + Map.of(), + ApplicationState.RUNNING, + new Date(), + new Date()), "DEAD_APP-2", new AppSummary("DEAD_APP-2", - "DEAD_APP", - 0, - 0, - 4, - 1024, - Map.of(), - ApplicationState.MONITORING, - new Date(), - new Date()), + "DEAD_APP", + 0, + 0, + 4, + 1024, + Map.of(), + ApplicationState.MONITORING, + new Date(), + new Date()), "OTHER_APP-2", new AppSummary("OTHER_APP-2", - "OTHER_APP", - 4, - 4, - 4, - 1024, - Map.of(), - ApplicationState.RUNNING, - new Date(), - new Date()))); + "OTHER_APP", + 4, + 4, + 4, + 1024, + Map.of(), + ApplicationState.RUNNING, + new Date(), + new Date()))); extension.stubFor(get("/apis/v1/applications") - .withBasicAuth("guest", "guest") - .willReturn(okJson(MAPPER.writeValueAsString( - response)))); + .withBasicAuth("guest", "guest") + .willReturn(okJson(MAPPER.writeValueAsString( + response)))); } private static void setupNetworkError(String api) { extension.stubFor(get(urlPathEqualTo(api)) - .withBasicAuth("guest", "guest") - .willReturn(aResponse().withFault(Fault.MALFORMED_RESPONSE_CHUNK))); + .withBasicAuth("guest", "guest") + .willReturn(aResponse().withFault(Fault.MALFORMED_RESPONSE_CHUNK))); } } \ No newline at end of file diff --git a/ranger-drove/src/test/java/io/appform/ranger/drove/common/DroveNodeDataStoreConnectorTest.java b/ranger-drove/src/test/java/io/appform/ranger/drove/common/DroveNodeDataStoreConnectorTest.java index 249b87ed..7bcf277e 100644 --- a/ranger-drove/src/test/java/io/appform/ranger/drove/common/DroveNodeDataStoreConnectorTest.java +++ b/ranger-drove/src/test/java/io/appform/ranger/drove/common/DroveNodeDataStoreConnectorTest.java @@ -27,7 +27,9 @@ import java.util.List; -import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.ok; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static org.junit.jupiter.api.Assertions.assertTrue; @WireMockTest diff --git a/ranger-drove/src/test/java/io/appform/ranger/drove/servicefinder/DroveNodeDataSourceTest.java b/ranger-drove/src/test/java/io/appform/ranger/drove/servicefinder/DroveNodeDataSourceTest.java index 3a7b90b7..8d0c4e54 100644 --- a/ranger-drove/src/test/java/io/appform/ranger/drove/servicefinder/DroveNodeDataSourceTest.java +++ b/ranger-drove/src/test/java/io/appform/ranger/drove/servicefinder/DroveNodeDataSourceTest.java @@ -31,7 +31,9 @@ import java.util.Map; import static com.phonepe.drove.models.application.PortType.TCP; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -70,11 +72,11 @@ void testSuccess() { when(droveClient.listNodes(any(Service.class))) .thenReturn(List.of(new ExposedAppInfo("TEST_APP", - "A1", - "xx.x.xx", - Map.of(), - List.of(new ExposedAppInfo.ExposedHost("h1", 100, TCP), - new ExposedAppInfo.ExposedHost("h2", 100, TCP))))); + "A1", + "xx.x.xx", + Map.of(), + List.of(new ExposedAppInfo.ExposedHost("h1", 100, TCP), + new ExposedAppInfo.ExposedHost("h2", 100, TCP))))); val ds = new DroveNodeDataSource( service, config, diff --git a/ranger-drove/src/test/java/io/appform/ranger/drove/servicefinder/DroveShardedServiceFinderBuilderTest.java b/ranger-drove/src/test/java/io/appform/ranger/drove/servicefinder/DroveShardedServiceFinderBuilderTest.java index 05d7f579..bcb7b31a 100644 --- a/ranger-drove/src/test/java/io/appform/ranger/drove/servicefinder/DroveShardedServiceFinderBuilderTest.java +++ b/ranger-drove/src/test/java/io/appform/ranger/drove/servicefinder/DroveShardedServiceFinderBuilderTest.java @@ -34,7 +34,10 @@ import java.util.List; import java.util.Map; -import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static org.awaitility.Awaitility.await; /** @@ -58,23 +61,23 @@ public NodeData(@JsonProperty("name") String name) { void testFinder(WireMockRuntimeInfo wm) throws Exception { val payload = MAPPER.writeValueAsBytes( ApiResponse.success(List.of(new ExposedAppInfo("test", - "test-0.1", - "test.appform.io", - Map.of(), - List.of(new ExposedAppInfo.ExposedHost( - "executor001.internal", - 32456, - PortType.HTTP)))))); + "test-0.1", + "test.appform.io", + Map.of(), + List.of(new ExposedAppInfo.ExposedHost( + "executor001.internal", + 32456, + PortType.HTTP)))))); stubFor(get(urlPathEqualTo("/apis/v1/endpoints")) - .willReturn(aResponse() - .withBody(payload) - .withStatus(200))); + .willReturn(aResponse() + .withBody(payload) + .withStatus(200))); val clientConfig = DroveUpstreamConfig.builder() .endpoints(List.of("http://localhost:" + wm.getHttpPort())) .skipCaching(true) .build(); - try(val droveClient = RangerDroveUtils.buildDroveClient("testns", clientConfig, MAPPER)) { + try (val droveClient = RangerDroveUtils.buildDroveClient("testns", clientConfig, MAPPER)) { val finder = new DroveShardedServiceFinderBuilder() .withClientConfig(clientConfig) .withNamespace("testns") diff --git a/ranger-drove/src/test/java/io/appform/ranger/drove/servicefinderhub/DroveServiceDataSourceTest.java b/ranger-drove/src/test/java/io/appform/ranger/drove/servicefinderhub/DroveServiceDataSourceTest.java index fe5fac64..39383d8f 100644 --- a/ranger-drove/src/test/java/io/appform/ranger/drove/servicefinderhub/DroveServiceDataSourceTest.java +++ b/ranger-drove/src/test/java/io/appform/ranger/drove/servicefinderhub/DroveServiceDataSourceTest.java @@ -33,8 +33,13 @@ import java.util.List; import java.util.Map; -import static com.github.tomakehurst.wiremock.client.WireMock.*; -import static org.junit.jupiter.api.Assertions.*; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.okJson; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; @WireMockTest class DroveServiceDataSourceTest { @@ -47,58 +52,58 @@ void testServiceDataSource(WireMockRuntimeInfo wireMockRuntimeInfo) { val response = ApiResponse.success(Map.of( "TEST_APP-1", new AppSummary("TEST_APP-1", - "TEST_APP", - 4, - 4, - 4, - 1024, - Map.of(), - ApplicationState.RUNNING, - new Date(), - new Date()), + "TEST_APP", + 4, + 4, + 4, + 1024, + Map.of(), + ApplicationState.RUNNING, + new Date(), + new Date()), "TEST_APP-2", new AppSummary("TEST_APP-2", - "TEST_APP", - 4, - 4, - 4, - 1024, - Map.of(), - ApplicationState.RUNNING, - new Date(), - new Date()), + "TEST_APP", + 4, + 4, + 4, + 1024, + Map.of(), + ApplicationState.RUNNING, + new Date(), + new Date()), "DEAD_APP-2", new AppSummary("DEAD_APP-2", - "DEAD_APP", - 0, - 0, - 4, - 1024, - Map.of(), - ApplicationState.MONITORING, - new Date(), - new Date()), + "DEAD_APP", + 0, + 0, + 4, + 1024, + Map.of(), + ApplicationState.MONITORING, + new Date(), + new Date()), "OTHER_APP-2", new AppSummary("OTHER_APP-2", - "OTHER_APP", - 4, - 4, - 4, - 1024, - Map.of(), - ApplicationState.RUNNING, - new Date(), - new Date()))); + "OTHER_APP", + 4, + 4, + 4, + 1024, + Map.of(), + ApplicationState.RUNNING, + new Date(), + new Date()))); val payload = MAPPER.writeValueAsString(response); stubFor(get("/apis/v1/applications").willReturn(okJson(payload))); val clientConfig = DroveUpstreamConfig.builder() .endpoints(List.of("http://localhost:" + wireMockRuntimeInfo.getHttpPort())) .build(); stubFor(get(urlPathEqualTo("/apis/v1/endpoints")) - .willReturn(okJson(MAPPER.writeValueAsString(ApiResponse.success(List.of()))))); + .willReturn(okJson(MAPPER.writeValueAsString(ApiResponse.success(List.of()))))); val namespace = "test"; - try(val droveClient = RangerDroveUtils.buildDroveClient(namespace, clientConfig, MAPPER)) { + try (val droveClient = RangerDroveUtils.buildDroveClient(namespace, clientConfig, MAPPER)) { val finder = new DroveServiceDataSource( clientConfig, MAPPER, diff --git a/ranger-drove/src/test/resources/logback.xml b/ranger-drove/src/test/resources/logback.xml index 9b90506f..a0cd0a86 100644 --- a/ranger-drove/src/test/resources/logback.xml +++ b/ranger-drove/src/test/resources/logback.xml @@ -23,10 +23,10 @@ - + - - + + \ No newline at end of file diff --git a/ranger-http-client/src/main/java/io/appform/ranger/client/http/AbstractRangerHttpHubClient.java b/ranger-http-client/src/main/java/io/appform/ranger/client/http/AbstractRangerHttpHubClient.java index 5dd6910b..91a6f636 100644 --- a/ranger-http-client/src/main/java/io/appform/ranger/client/http/AbstractRangerHttpHubClient.java +++ b/ranger-http-client/src/main/java/io/appform/ranger/client/http/AbstractRangerHttpHubClient.java @@ -51,10 +51,10 @@ public abstract class AbstractRangerHttpHubClient(clientConfig, - Objects.requireNonNullElseGet(getHttpClient(), - () -> RangerHttpUtils.httpClient( - clientConfig, - getMapper()))); + Objects.requireNonNullElseGet(getHttpClient(), + () -> RangerHttpUtils.httpClient( + clientConfig, + getMapper()))); } @Override diff --git a/ranger-http-client/src/main/java/io/appform/ranger/client/http/SimpleRangerHttpClient.java b/ranger-http-client/src/main/java/io/appform/ranger/client/http/SimpleRangerHttpClient.java index a8f307ec..b0398d87 100644 --- a/ranger-http-client/src/main/java/io/appform/ranger/client/http/SimpleRangerHttpClient.java +++ b/ranger-http-client/src/main/java/io/appform/ranger/client/http/SimpleRangerHttpClient.java @@ -72,7 +72,7 @@ public void start() { @Override public void stop() { log.info("Stopping the service finder"); - if(null != serviceFinder){ + if (null != serviceFinder) { this.serviceFinder.stop(); } } diff --git a/ranger-http-client/src/test/java/io/appform/ranger/client/http/BaseRangerHttpClientTest.java b/ranger-http-client/src/test/java/io/appform/ranger/client/http/BaseRangerHttpClientTest.java index a4facb94..9f604f20 100644 --- a/ranger-http-client/src/test/java/io/appform/ranger/client/http/BaseRangerHttpClientTest.java +++ b/ranger-http-client/src/test/java/io/appform/ranger/client/http/BaseRangerHttpClientTest.java @@ -36,7 +36,9 @@ import java.io.IOException; -import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; @Slf4j @@ -88,9 +90,9 @@ public void prepareHttpMocks() throws Exception { protected ServiceNodesResponse read(final byte[] data) { try { - return getObjectMapper().readValue(data, new TypeReference>() {}); - } - catch (IOException e) { + return getObjectMapper().readValue(data, new TypeReference>() { + }); + } catch (IOException e) { Exceptions.illegalState(e); } return null; diff --git a/ranger-http-client/src/test/java/io/appform/ranger/client/http/ShardedRangerHttpClientTest.java b/ranger-http-client/src/test/java/io/appform/ranger/client/http/ShardedRangerHttpClientTest.java index 956c5ff6..b858a1c7 100644 --- a/ranger-http-client/src/test/java/io/appform/ranger/client/http/ShardedRangerHttpClientTest.java +++ b/ranger-http-client/src/test/java/io/appform/ranger/client/http/ShardedRangerHttpClientTest.java @@ -25,7 +25,7 @@ class ShardedRangerHttpClientTest extends BaseRangerHttpClientTest { @Test - void testShardedHttpHubClient(){ + void testShardedHttpHubClient() { val httpClientConfig = getHttpClientConfig(); val client = ShardedRangerHttpHubClient.builder() .clientConfig(httpClientConfig) diff --git a/ranger-http-client/src/test/java/io/appform/ranger/client/http/SimpleRangerHttpClientTest.java b/ranger-http-client/src/test/java/io/appform/ranger/client/http/SimpleRangerHttpClientTest.java index 64f6b3cc..e79954a0 100644 --- a/ranger-http-client/src/test/java/io/appform/ranger/client/http/SimpleRangerHttpClientTest.java +++ b/ranger-http-client/src/test/java/io/appform/ranger/client/http/SimpleRangerHttpClientTest.java @@ -22,10 +22,10 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -class SimpleRangerHttpClientTest extends BaseRangerHttpClientTest{ +class SimpleRangerHttpClientTest extends BaseRangerHttpClientTest { @Test - void testSimpleHttpRangerClient(){ + void testSimpleHttpRangerClient() { val httpClientConfig = getHttpClientConfig(); val client = SimpleRangerHttpClient.builder() .clientConfig(httpClientConfig) diff --git a/ranger-http-client/src/test/java/io/appform/ranger/client/http/UnshardedRangerHttpClientTest.java b/ranger-http-client/src/test/java/io/appform/ranger/client/http/UnshardedRangerHttpClientTest.java index b4b64325..f5ba5349 100644 --- a/ranger-http-client/src/test/java/io/appform/ranger/client/http/UnshardedRangerHttpClientTest.java +++ b/ranger-http-client/src/test/java/io/appform/ranger/client/http/UnshardedRangerHttpClientTest.java @@ -25,7 +25,7 @@ class UnshardedRangerHttpClientTest extends BaseRangerHttpClientTest { @Test - void testUnshardedRangerHubClient(){ + void testUnshardedRangerHubClient() { val httpClientConfig = getHttpClientConfig(); val client = UnshardedRangerHttpHubClient.builder() .clientConfig(httpClientConfig) diff --git a/ranger-http-model/pom.xml b/ranger-http-model/pom.xml index a964e821..f504bb2e 100644 --- a/ranger-http-model/pom.xml +++ b/ranger-http-model/pom.xml @@ -18,12 +18,14 @@ + + 4.0.0 + - ranger io.appform.ranger + ranger 2.0.0-SNAPSHOT - 4.0.0 ranger-http-model HTTP Service Models for Ranger diff --git a/ranger-http/pom.xml b/ranger-http/pom.xml index b81208fb..152750aa 100644 --- a/ranger-http/pom.xml +++ b/ranger-http/pom.xml @@ -44,6 +44,11 @@ okhttp ${http.client.version} + + com.squareup.okhttp3 + logging-interceptor + ${http.client.version} + org.wiremock wiremock-standalone diff --git a/ranger-http/src/main/java/io/appform/ranger/http/HttpServiceFinderBuilders.java b/ranger-http/src/main/java/io/appform/ranger/http/HttpServiceFinderBuilders.java index ba279c57..9d1da033 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/HttpServiceFinderBuilders.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/HttpServiceFinderBuilders.java @@ -16,18 +16,18 @@ package io.appform.ranger.http; import io.appform.ranger.http.servicefinder.HttpShardedServiceFinderBuilder; -import io.appform.ranger.http.servicefinder.HttpUnshardedServiceFinderBuilider; +import io.appform.ranger.http.servicefinder.HttpUnshardedServiceFinderBuilder; import lombok.experimental.UtilityClass; @UtilityClass @SuppressWarnings("unused") public final class HttpServiceFinderBuilders { - public static HttpShardedServiceFinderBuilder httpShardedServiceFinderBuilder(){ + public static HttpShardedServiceFinderBuilder httpShardedServiceFinderBuilder() { return new HttpShardedServiceFinderBuilder<>(); } - public static HttpUnshardedServiceFinderBuilider httpUnshardedServiceFinderBuilider(){ - return new HttpUnshardedServiceFinderBuilider<>(); + public static HttpUnshardedServiceFinderBuilder httpUnshardedServiceFinderBuilider() { + return new HttpUnshardedServiceFinderBuilder<>(); } } diff --git a/ranger-http/src/main/java/io/appform/ranger/http/common/HttpNodeDataStoreConnector.java b/ranger-http/src/main/java/io/appform/ranger/http/common/HttpNodeDataStoreConnector.java index 210a6e02..7e733aef 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/common/HttpNodeDataStoreConnector.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/common/HttpNodeDataStoreConnector.java @@ -54,8 +54,8 @@ public void stop() { protected int defaultPort() { return config.isSecure() - ? 443 - : 80; + ? 443 + : 80; } @Override diff --git a/ranger-http/src/main/java/io/appform/ranger/http/model/ServiceDataSourceResponse.java b/ranger-http/src/main/java/io/appform/ranger/http/model/ServiceDataSourceResponse.java index 668a2277..3f34a5da 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/model/ServiceDataSourceResponse.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/model/ServiceDataSourceResponse.java @@ -33,7 +33,7 @@ public class ServiceDataSourceResponse { Set data; @JsonIgnore - public boolean valid(){ + public boolean valid() { return null != data; } } diff --git a/ranger-http/src/main/java/io/appform/ranger/http/model/ServiceNodesResponse.java b/ranger-http/src/main/java/io/appform/ranger/http/model/ServiceNodesResponse.java index 783bf3d0..c5b6e759 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/model/ServiceNodesResponse.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/model/ServiceNodesResponse.java @@ -36,7 +36,7 @@ public class ServiceNodesResponse { List> data; @JsonIgnore - public boolean valid(){ - return null != data; + public boolean valid() { + return null != data; } } diff --git a/ranger-http/src/main/java/io/appform/ranger/http/model/ServiceRegistrationResponse.java b/ranger-http/src/main/java/io/appform/ranger/http/model/ServiceRegistrationResponse.java index 8d367cb2..6e8a37c6 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/model/ServiceRegistrationResponse.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/model/ServiceRegistrationResponse.java @@ -31,7 +31,7 @@ public class ServiceRegistrationResponse { ServiceNode data; @JsonIgnore - public boolean valid(){ + public boolean valid() { return null != data; } } diff --git a/ranger-http/src/main/java/io/appform/ranger/http/serde/HTTPResponseDataDeserializer.java b/ranger-http/src/main/java/io/appform/ranger/http/serde/HTTPResponseDataDeserializer.java index 1b5949d3..5ded37e0 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/serde/HTTPResponseDataDeserializer.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/serde/HTTPResponseDataDeserializer.java @@ -23,5 +23,5 @@ */ @FunctionalInterface public interface HTTPResponseDataDeserializer extends Deserializer { - ServiceNodesResponse deserialize(byte []data); + ServiceNodesResponse deserialize(byte[] data); } diff --git a/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpApiCommunicator.java b/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpApiCommunicator.java index b5ee80f9..a85a8c59 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpApiCommunicator.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpApiCommunicator.java @@ -83,13 +83,11 @@ public Set services() { try (val response = httpClient.newCall(request).execute()) { if (response.isSuccessful()) { return parseServices(response, httpUrl); - } - else { + } else { throw new HttpCommunicationException( "Http call to returned a failure response. Url:" + httpUrl + " status: " + response.code()); } - } - catch (Exception e) { + } catch (Exception e) { throw new HttpCommunicationException( "Error parsing the response from server for url: " + httpUrl + " with exception " + e.getClass().getSimpleName() + ": " + e.getMessage()); @@ -120,29 +118,26 @@ public List> listNodes( try (val response = httpClient.newCall(request).execute()) { if (response.isSuccessful()) { return parseNodeList(deserializer, response, httpUrl); - } - else { + } else { throw new HttpCommunicationException("HTTP call failed. url: " + httpUrl + " status: " + response.code()); } - } - catch (Exception e) { + } catch (Exception e) { throw new HttpCommunicationException("Error getting node data from the http endpoint: " + httpUrl + - ". Error: " + e.getMessage()); + ". Error: " + e.getMessage()); } }); } @Override - public void close() throws Exception { - + public void close() { + //Not required } private U executeRemoteCall(Supplier executor) { upstreamAvailable.set(true); try { return executor.get(); - } - catch (HttpCommunicationException e) { + } catch (HttpCommunicationException e) { upstreamAvailable.set(false); throw e; } @@ -150,28 +145,25 @@ private U executeRemoteCall(Supplier executor) { private int defaultPort() { return config.isSecure() - ? 443 - : 80; + ? 443 + : 80; } private Set parseServices(Response response, HttpUrl httpUrl) { try (val body = response.body()) { if (null == body) { throw new HttpCommunicationException("Empty response body from: " + httpUrl); - } - else { + } else { val bytes = body.bytes(); val serviceDataSourceResponse = mapper.readValue(bytes, ServiceDataSourceResponse.class); if (serviceDataSourceResponse.valid()) { return serviceDataSourceResponse.getData(); - } - else { + } else { throw new HttpCommunicationException( "Http call to returned a failure response. Url:" + httpUrl + " data: " + serviceDataSourceResponse); } } - } - catch (Exception e) { + } catch (Exception e) { throw new HttpCommunicationException( "Error reading data from server. Url: " + httpUrl + "Error: " + e.getMessage()); } @@ -185,20 +177,17 @@ private static List> parseNodeList( if (null == body) { log.warn("HTTP call to {} returned empty body", httpUrl); throw new HttpCommunicationException("Empty response received for call to " + httpUrl); - } - else { + } else { val bytes = body.bytes(); val serviceNodesResponse = deserializer.deserialize(bytes); if (serviceNodesResponse.valid()) { return serviceNodesResponse.getData(); - } - else { + } else { throw new HttpCommunicationException( "Http call returned null nodes for url: " + httpUrl + " response: " + serviceNodesResponse); } } - } - catch (Exception e) { + } catch (Exception e) { throw new HttpCommunicationException( "Error parsing node data from server. Url: " + httpUrl + "Error: " + e.getMessage()); } diff --git a/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpCommunicationException.java b/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpCommunicationException.java index f8a2586e..82cc2c78 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpCommunicationException.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpCommunicationException.java @@ -20,7 +20,6 @@ /** * Thrown in case there is an issue communicating with the HTTP upstream. - */ public class HttpCommunicationException extends CommunicationException { public HttpCommunicationException(final String message) { diff --git a/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpShardedServiceFinderBuilder.java b/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpShardedServiceFinderBuilder.java index 44d3cf6e..05978633 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpShardedServiceFinderBuilder.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpShardedServiceFinderBuilder.java @@ -40,12 +40,12 @@ public HttpShardedServiceFinderBuilder withClientConfig(final HttpClientConfi return this; } - public HttpShardedServiceFinderBuilder withObjectMapper(final ObjectMapper mapper){ + public HttpShardedServiceFinderBuilder withObjectMapper(final ObjectMapper mapper) { this.mapper = mapper; return this; } - public HttpShardedServiceFinderBuilder withHttpCommunicator(final HttpCommunicator httpCommunicator){ + public HttpShardedServiceFinderBuilder withHttpCommunicator(final HttpCommunicator httpCommunicator) { this.httpCommunicator = httpCommunicator; return this; } @@ -58,8 +58,8 @@ public SimpleShardedServiceFinder build() { @Override protected NodeDataSource> dataSource(Service service) { return new HttpNodeDataSource<>(service, clientConfig, - Objects.requireNonNullElseGet(httpCommunicator, - () -> RangerHttpUtils.httpClient(clientConfig, mapper))); + Objects.requireNonNullElseGet(httpCommunicator, + () -> RangerHttpUtils.httpClient(clientConfig, mapper))); } } diff --git a/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpUnshardedServiceFinderBuilider.java b/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpUnshardedServiceFinderBuilder.java similarity index 74% rename from ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpUnshardedServiceFinderBuilider.java rename to ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpUnshardedServiceFinderBuilder.java index fae76ea2..1413e30c 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpUnshardedServiceFinderBuilider.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/servicefinder/HttpUnshardedServiceFinderBuilder.java @@ -26,24 +26,24 @@ import java.util.Objects; -public class HttpUnshardedServiceFinderBuilider - extends SimpleUnshardedServiceFinderBuilder, HTTPResponseDataDeserializer> { +public class HttpUnshardedServiceFinderBuilder + extends SimpleUnshardedServiceFinderBuilder, HTTPResponseDataDeserializer> { private HttpClientConfig clientConfig; private ObjectMapper mapper; private HttpCommunicator httpClient; - public HttpUnshardedServiceFinderBuilider withClientConfig(final HttpClientConfig clientConfig) { + public HttpUnshardedServiceFinderBuilder withClientConfig(final HttpClientConfig clientConfig) { this.clientConfig = clientConfig; return this; } - public HttpUnshardedServiceFinderBuilider withObjectMapper(final ObjectMapper mapper) { + public HttpUnshardedServiceFinderBuilder withObjectMapper(final ObjectMapper mapper) { this.mapper = mapper; return this; } - public HttpUnshardedServiceFinderBuilider withHttpClient(final HttpCommunicator httpClient) { + public HttpUnshardedServiceFinderBuilder withHttpClient(final HttpCommunicator httpClient) { this.httpClient = httpClient; return this; } @@ -56,8 +56,8 @@ public SimpleUnshardedServiceFinder build() { @Override protected NodeDataSource> dataSource(Service service) { return new HttpNodeDataSource<>(service, clientConfig, - Objects.requireNonNullElseGet(httpClient, - () -> RangerHttpUtils.httpClient(clientConfig, mapper))); + Objects.requireNonNullElseGet(httpClient, + () -> RangerHttpUtils.httpClient(clientConfig, mapper))); } } diff --git a/ranger-http/src/main/java/io/appform/ranger/http/servicefinderhub/HttpServiceDataSource.java b/ranger-http/src/main/java/io/appform/ranger/http/servicefinderhub/HttpServiceDataSource.java index a52cc214..0e44ed34 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/servicefinderhub/HttpServiceDataSource.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/servicefinderhub/HttpServiceDataSource.java @@ -34,7 +34,7 @@ public HttpServiceDataSource(HttpClientConfig config, HttpCommunicator httpCl @Override public Collection services() { - Objects.requireNonNull(config, "client config has not been set for node data"); + Objects.requireNonNull(config, "client config has not been set for node data"); return httpCommunicator.services(); } } diff --git a/ranger-http/src/main/java/io/appform/ranger/http/servicefinderhub/HttpShardedServiceFinderFactory.java b/ranger-http/src/main/java/io/appform/ranger/http/servicefinderhub/HttpShardedServiceFinderFactory.java index b1b1f508..7b41e248 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/servicefinderhub/HttpShardedServiceFinderFactory.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/servicefinderhub/HttpShardedServiceFinderFactory.java @@ -29,7 +29,7 @@ import lombok.Builder; import lombok.val; -public class HttpShardedServiceFinderFactory implements ServiceFinderFactory> { +public class HttpShardedServiceFinderFactory implements ServiceFinderFactory> { private final HttpClientConfig clientConfig; private final HttpCommunicator httpClient; @@ -47,8 +47,7 @@ public HttpShardedServiceFinderFactory( HTTPResponseDataDeserializer deserializer, ShardSelector> shardSelector, ServiceNodeSelector nodeSelector, - int nodeRefreshIntervalMs) - { + int nodeRefreshIntervalMs) { this.clientConfig = httpClientConfig; this.httpClient = httpClient; this.mapper = mapper; diff --git a/ranger-http/src/main/java/io/appform/ranger/http/servicefinderhub/HttpUnshardedServiceFinderFactory.java b/ranger-http/src/main/java/io/appform/ranger/http/servicefinderhub/HttpUnshardedServiceFinderFactory.java index 51c8cb02..3a8b5922 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/servicefinderhub/HttpUnshardedServiceFinderFactory.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/servicefinderhub/HttpUnshardedServiceFinderFactory.java @@ -25,7 +25,7 @@ import io.appform.ranger.http.config.HttpClientConfig; import io.appform.ranger.http.serde.HTTPResponseDataDeserializer; import io.appform.ranger.http.servicefinder.HttpCommunicator; -import io.appform.ranger.http.servicefinder.HttpUnshardedServiceFinderBuilider; +import io.appform.ranger.http.servicefinder.HttpUnshardedServiceFinderBuilder; import lombok.Builder; import lombok.val; @@ -59,7 +59,7 @@ public HttpUnshardedServiceFinderFactory( @Override public ServiceFinder> buildFinder(Service service) { - val serviceFinder = new HttpUnshardedServiceFinderBuilider() + val serviceFinder = new HttpUnshardedServiceFinderBuilder() .withClientConfig(clientConfig) .withObjectMapper(mapper) .withHttpClient(httpClient) diff --git a/ranger-http/src/main/java/io/appform/ranger/http/serviceprovider/HttpNodeDataSink.java b/ranger-http/src/main/java/io/appform/ranger/http/serviceprovider/HttpNodeDataSink.java index 627d8676..d7824a1a 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/serviceprovider/HttpNodeDataSink.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/serviceprovider/HttpNodeDataSink.java @@ -68,13 +68,13 @@ public void updateState(S serializer, ServiceNode serviceNode) { .build(); val requestBody = RequestBody.create(serializer.serialize(serviceNode)); val serviceRegistrationResponse = registerService(httpUrl, requestBody).orElse(null); - if(null == serviceRegistrationResponse || !serviceRegistrationResponse.valid()){ + if (null == serviceRegistrationResponse || !serviceRegistrationResponse.valid()) { log.warn("Http call to {} returned a failure response {}", httpUrl, serviceRegistrationResponse); Exceptions.illegalState("Error updating state on the server for node data: " + httpUrl); } } - private Optional> registerService(HttpUrl httpUrl, RequestBody requestBody){ + private Optional> registerService(HttpUrl httpUrl, RequestBody requestBody) { val request = new Request.Builder() .url(httpUrl) .post(requestBody) @@ -84,19 +84,17 @@ private Optional> registerService(HttpUrl httpUrl try (val body = response.body()) { if (null == body) { log.warn("HTTP call to {} returned empty body", httpUrl); - } - else { + } else { return Optional.of(mapper.readValue(body.bytes(), - new TypeReference>() {})); + new TypeReference>() { + })); } } - } - else { + } else { log.warn("HTTP call to {} has returned: {}", httpUrl, response.code()); } - } - catch (IOException e) { - log.error("Error updating state on the server with httpUrl {} with exception {} ", httpUrl, e); + } catch (IOException e) { + log.error("Error updating state on the server with httpUrl {} with exception {} ", httpUrl, e); } return Optional.empty(); } diff --git a/ranger-http/src/main/java/io/appform/ranger/http/serviceprovider/HttpShardedServiceProviderBuilder.java b/ranger-http/src/main/java/io/appform/ranger/http/serviceprovider/HttpShardedServiceProviderBuilder.java index 4caec43d..2fc479ec 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/serviceprovider/HttpShardedServiceProviderBuilder.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/serviceprovider/HttpShardedServiceProviderBuilder.java @@ -40,7 +40,7 @@ public HttpShardedServiceProviderBuilder withClientConfiguration(final HttpCl return this; } - public HttpShardedServiceProviderBuilder withObjectMapper(final ObjectMapper mapper){ + public HttpShardedServiceProviderBuilder withObjectMapper(final ObjectMapper mapper) { this.mapper = mapper; return this; } @@ -58,7 +58,7 @@ public ServiceProvider> build() { @Override protected NodeDataSink> dataSink(Service service) { return new HttpNodeDataSink<>(service, clientConfig, mapper, - Objects.requireNonNullElseGet(httpClient, - () -> RangerHttpUtils.httpClient(clientConfig, mapper))); + Objects.requireNonNullElseGet(httpClient, + () -> RangerHttpUtils.httpClient(clientConfig, mapper))); } } diff --git a/ranger-http/src/main/java/io/appform/ranger/http/utils/RangerHttpUtils.java b/ranger-http/src/main/java/io/appform/ranger/http/utils/RangerHttpUtils.java index 906e06e6..fb7d3ea7 100644 --- a/ranger-http/src/main/java/io/appform/ranger/http/utils/RangerHttpUtils.java +++ b/ranger-http/src/main/java/io/appform/ranger/http/utils/RangerHttpUtils.java @@ -40,11 +40,11 @@ public static HttpCommunicator httpClient( return new HttpApiCommunicator<>( new OkHttpClient.Builder() .callTimeout(config.getOperationTimeoutMs() == 0 - ? 3000 - : config.getOperationTimeoutMs(), TimeUnit.MILLISECONDS) + ? 3000 + : config.getOperationTimeoutMs(), TimeUnit.MILLISECONDS) .connectTimeout(config.getConnectionTimeoutMs() == 0 - ? 3000 - : config.getConnectionTimeoutMs(), TimeUnit.MILLISECONDS) + ? 3000 + : config.getConnectionTimeoutMs(), TimeUnit.MILLISECONDS) .readTimeout(config.getOperationTimeoutMs() == 0 ? 3000 : config.getOperationTimeoutMs(), TimeUnit.MILLISECONDS) diff --git a/ranger-http/src/test/java/io/appform/ranger/http/ResourceHelper.java b/ranger-http/src/test/java/io/appform/ranger/http/ResourceHelper.java index 06b4f843..5a480452 100644 --- a/ranger-http/src/test/java/io/appform/ranger/http/ResourceHelper.java +++ b/ranger-http/src/test/java/io/appform/ranger/http/ResourceHelper.java @@ -31,7 +31,7 @@ public class ResourceHelper { public static String getResource(String path) { val data = ResourceHelper.class.getClassLoader().getResourceAsStream(path); - if(null == data) return null; + if (null == data) return null; return new BufferedReader( new InputStreamReader(data)) .lines() @@ -41,7 +41,7 @@ public static String getResource(String path) { @SneakyThrows public static T getResource(String path, Class klass) { val data = getResource(path); - if(null == data) return null; + if (null == data) return null; return objectMapper.readValue(data, klass); } } diff --git a/ranger-http/src/test/java/io/appform/ranger/http/common/HttpNodeDataStoreConnectorTest.java b/ranger-http/src/test/java/io/appform/ranger/http/common/HttpNodeDataStoreConnectorTest.java index 41a67b0c..f703bf8a 100644 --- a/ranger-http/src/test/java/io/appform/ranger/http/common/HttpNodeDataStoreConnectorTest.java +++ b/ranger-http/src/test/java/io/appform/ranger/http/common/HttpNodeDataStoreConnectorTest.java @@ -23,16 +23,16 @@ import org.junit.jupiter.api.Test; class HttpNodeDataStoreConnectorTest { - + @Test - void testHttpNodeDataStoreConnector(){ + void testHttpNodeDataStoreConnector() { val objectMapper = new ObjectMapper(); val httpClientConfig = HttpClientConfig.builder() .host("localhost-1") .port(80) .build(); val httpNodeDataStoreConnector = new HttpNodeDataStoreConnector<>(httpClientConfig, - RangerHttpUtils.httpClient(httpClientConfig, objectMapper)); + RangerHttpUtils.httpClient(httpClientConfig, objectMapper)); Assertions.assertNotNull(httpNodeDataStoreConnector); Assertions.assertTrue(httpNodeDataStoreConnector.isActive()); } diff --git a/ranger-http/src/test/java/io/appform/ranger/http/config/HttpClientConfigTest.java b/ranger-http/src/test/java/io/appform/ranger/http/config/HttpClientConfigTest.java index 2fc8161a..f09c25f5 100644 --- a/ranger-http/src/test/java/io/appform/ranger/http/config/HttpClientConfigTest.java +++ b/ranger-http/src/test/java/io/appform/ranger/http/config/HttpClientConfigTest.java @@ -23,7 +23,7 @@ class HttpClientConfigTest { @Test - void testHttpClientConfig(){ + void testHttpClientConfig() { val resource = ResourceHelper.getResource("fixtures/httpClientConfig.json", HttpClientConfig.class); Assertions.assertNotNull(resource); Assertions.assertEquals("localhost-1", resource.getHost()); diff --git a/ranger-http/src/test/java/io/appform/ranger/http/model/ServiceNodeResponseTest.java b/ranger-http/src/test/java/io/appform/ranger/http/model/ServiceNodeResponseTest.java index 2f086e80..0aba8e7b 100644 --- a/ranger-http/src/test/java/io/appform/ranger/http/model/ServiceNodeResponseTest.java +++ b/ranger-http/src/test/java/io/appform/ranger/http/model/ServiceNodeResponseTest.java @@ -24,18 +24,18 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class ServiceNodeResponseTest { +class ServiceNodeResponseTest { @Value @Builder @Jacksonized - static class TestNodeInfo{ + static class TestNodeInfo { int shardId; String region; } @Test - public void testServiceNodesResponse(){ + void testServiceNodesResponse() { val serviceNodesResponse = ResourceHelper.getResource("fixtures/serviceNodesResponse.json", ServiceNodesResponse.class); Assertions.assertNotNull(serviceNodesResponse); Assertions.assertFalse(serviceNodesResponse.getData().isEmpty()); diff --git a/ranger-http/src/test/java/io/appform/ranger/http/model/ServiceRegistrationResponseTest.java b/ranger-http/src/test/java/io/appform/ranger/http/model/ServiceRegistrationResponseTest.java index 392f1cbc..5af9d523 100644 --- a/ranger-http/src/test/java/io/appform/ranger/http/model/ServiceRegistrationResponseTest.java +++ b/ranger-http/src/test/java/io/appform/ranger/http/model/ServiceRegistrationResponseTest.java @@ -20,10 +20,10 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class ServiceRegistrationResponseTest { +class ServiceRegistrationResponseTest { @Test - public void testServiceRegistrationResponse(){ + void testServiceRegistrationResponse() { val resource = ResourceHelper.getResource("fixtures/serviceResponse.json", ServiceRegistrationResponse.class); Assertions.assertNotNull(resource); Assertions.assertTrue(resource.valid()); diff --git a/ranger-http/src/test/java/io/appform/ranger/http/servicefinder/HttpShardedServiceFinderBuilderTest.java b/ranger-http/src/test/java/io/appform/ranger/http/servicefinder/HttpShardedServiceFinderBuilderTest.java index 88c1b6cb..a242d4cf 100644 --- a/ranger-http/src/test/java/io/appform/ranger/http/servicefinder/HttpShardedServiceFinderBuilderTest.java +++ b/ranger-http/src/test/java/io/appform/ranger/http/servicefinder/HttpShardedServiceFinderBuilderTest.java @@ -33,7 +33,10 @@ import java.io.IOException; import java.util.Collections; -import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; /** * @@ -63,9 +66,9 @@ void testFinder(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { .data(Collections.singletonList(node)) .build()); stubFor(get(urlPathEqualTo("/ranger/nodes/v1/testns/test")) - .willReturn(aResponse() - .withBody(payload) - .withStatus(200))); + .willReturn(aResponse() + .withBody(payload) + .withStatus(200))); val clientConfig = HttpClientConfig.builder() .host("127.0.0.1") .port(wireMockRuntimeInfo.getHttpPort()) @@ -80,9 +83,9 @@ void testFinder(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { .withObjectMapper(MAPPER) .withDeserializer(data -> { try { - return MAPPER.readValue(data, new TypeReference>() {}); - } - catch (IOException e) { + return MAPPER.readValue(data, new TypeReference>() { + }); + } catch (IOException e) { throw new IllegalArgumentException(e); } }) diff --git a/ranger-http/src/test/java/io/appform/ranger/http/servicefinderhub/HttpServiceDataSourceTest.java b/ranger-http/src/test/java/io/appform/ranger/http/servicefinderhub/HttpServiceDataSourceTest.java index ef0cf33d..e4cd2c36 100644 --- a/ranger-http/src/test/java/io/appform/ranger/http/servicefinderhub/HttpServiceDataSourceTest.java +++ b/ranger-http/src/test/java/io/appform/ranger/http/servicefinderhub/HttpServiceDataSourceTest.java @@ -29,7 +29,10 @@ import java.io.IOException; -import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; @WireMockTest class HttpServiceDataSourceTest { @@ -66,17 +69,17 @@ void testServiceDataSource(WireMockRuntimeInfo wireMockRuntimeInfo) throws IOExc .operationTimeoutMs(30_000) .build(); val httpServiceDataSource = new HttpServiceDataSource<>(clientConfig, - RangerHttpUtils.httpClient(clientConfig, MAPPER)); + RangerHttpUtils.httpClient(clientConfig, MAPPER)); val services = httpServiceDataSource.services(); Assertions.assertNotNull(services); Assertions.assertFalse(services.isEmpty()); Assertions.assertEquals(3, services.size()); Assertions.assertFalse(services.stream() - .noneMatch(each -> each.getServiceName().equalsIgnoreCase("test-s"))); + .noneMatch(each -> each.getServiceName().equalsIgnoreCase("test-s"))); Assertions.assertFalse(services.stream() - .noneMatch(each -> each.getServiceName().equalsIgnoreCase("test-s1"))); + .noneMatch(each -> each.getServiceName().equalsIgnoreCase("test-s1"))); Assertions.assertFalse(services.stream() - .noneMatch(each -> each.getServiceName().equalsIgnoreCase("test-s2"))); + .noneMatch(each -> each.getServiceName().equalsIgnoreCase("test-s2"))); } { //Here we set skip replication data to false. so query param is set val clientConfig = HttpClientConfig.builder() @@ -87,15 +90,15 @@ void testServiceDataSource(WireMockRuntimeInfo wireMockRuntimeInfo) throws IOExc .replicationSource(true) .build(); val httpServiceDataSource = new HttpServiceDataSource<>(clientConfig, - RangerHttpUtils.httpClient(clientConfig, MAPPER)); + RangerHttpUtils.httpClient(clientConfig, MAPPER)); val services = httpServiceDataSource.services(); Assertions.assertNotNull(services); Assertions.assertFalse(services.isEmpty()); Assertions.assertEquals(2, services.size()); Assertions.assertFalse(services.stream() - .noneMatch(each -> each.getServiceName().equalsIgnoreCase("test-s"))); + .noneMatch(each -> each.getServiceName().equalsIgnoreCase("test-s"))); Assertions.assertFalse(services.stream() - .noneMatch(each -> each.getServiceName().equalsIgnoreCase("test-s1"))); + .noneMatch(each -> each.getServiceName().equalsIgnoreCase("test-s1"))); } } diff --git a/ranger-http/src/test/java/io/appform/ranger/http/serviceprovider/HttpShardedServiceProviderBuilderTest.java b/ranger-http/src/test/java/io/appform/ranger/http/serviceprovider/HttpShardedServiceProviderBuilderTest.java index a2ee5795..7289325d 100644 --- a/ranger-http/src/test/java/io/appform/ranger/http/serviceprovider/HttpShardedServiceProviderBuilderTest.java +++ b/ranger-http/src/test/java/io/appform/ranger/http/serviceprovider/HttpShardedServiceProviderBuilderTest.java @@ -30,7 +30,11 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.binaryEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; @WireMockTest class HttpShardedServiceProviderBuilderTest { diff --git a/ranger-http/src/test/resources/fixtures/httpClientConfig.json b/ranger-http/src/test/resources/fixtures/httpClientConfig.json index 3855f309..86621d95 100644 --- a/ranger-http/src/test/resources/fixtures/httpClientConfig.json +++ b/ranger-http/src/test/resources/fixtures/httpClientConfig.json @@ -1,8 +1,8 @@ { - "host" : "localhost-1", - "port" : 80, - "secure" : false, - "connectionTimeoutMs" : 10, - "operationTimeoutMs" : 10, - "refreshIntervalMillis" : 1000 + "host": "localhost-1", + "port": 80, + "secure": false, + "connectionTimeoutMs": 10, + "operationTimeoutMs": 10, + "refreshIntervalMillis": 1000 } \ No newline at end of file diff --git a/ranger-http/src/test/resources/fixtures/serviceNodesResponse.json b/ranger-http/src/test/resources/fixtures/serviceNodesResponse.json index 0fa72860..2300d59a 100644 --- a/ranger-http/src/test/resources/fixtures/serviceNodesResponse.json +++ b/ranger-http/src/test/resources/fixtures/serviceNodesResponse.json @@ -1,22 +1,22 @@ { - "data" : [ + "data": [ { - "host" : "localhost-1", - "port" : 80, - "nodeData" : { - "shardId" : 1, - "region" : "r1" + "host": "localhost-1", + "port": 80, + "nodeData": { + "shardId": 1, + "region": "r1" }, - "healthcheckStatus" : "healthy" + "healthcheckStatus": "healthy" }, { - "host" : "localhost-2", - "port" : 90, - "nodeData" : { - "shardId" : 2, - "region" : "r2" + "host": "localhost-2", + "port": 90, + "nodeData": { + "shardId": 2, + "region": "r2" }, - "healthcheckStatus" : "healthy" + "healthcheckStatus": "healthy" } ] } \ No newline at end of file diff --git a/ranger-http/src/test/resources/fixtures/serviceResponse.json b/ranger-http/src/test/resources/fixtures/serviceResponse.json index c35da116..e8c5ea4e 100644 --- a/ranger-http/src/test/resources/fixtures/serviceResponse.json +++ b/ranger-http/src/test/resources/fixtures/serviceResponse.json @@ -1,6 +1,6 @@ { - "data" : { - "host" : "localhost", - "port" : 8080 + "data": { + "host": "localhost", + "port": 8080 } } \ No newline at end of file diff --git a/ranger-http/src/test/resources/logback.xml b/ranger-http/src/test/resources/logback.xml index 50ab1e2f..ea426e61 100644 --- a/ranger-http/src/test/resources/logback.xml +++ b/ranger-http/src/test/resources/logback.xml @@ -23,13 +23,13 @@ - + - + - - + + \ No newline at end of file diff --git a/ranger-hub-server-bundle-dw5/pom.xml b/ranger-hub-server-bundle-dw5/pom.xml new file mode 100644 index 00000000..6e7ebc07 --- /dev/null +++ b/ranger-hub-server-bundle-dw5/pom.xml @@ -0,0 +1,103 @@ + + + + + + ranger + io.appform.ranger + 2.0.0-SNAPSHOT + + + 4.0.0 + + ranger-hub-server-bundle-dw5 + Dropwizard 5.x bundle for making Ranger HTTP Hub Server + + + 5.0.0 + + + + + + io.dropwizard + dropwizard-bom + ${dropwizard.version} + pom + import + + + + + + + io.appform.ranger + ranger-http-client + ${project.version} + + + io.appform.ranger + ranger-zk-client + ${project.version} + + + io.appform.ranger + ranger-drove-client + ${project.version} + + + io.appform.ranger + ranger-server-bundle-dw5 + ${project.version} + + + io.appform.ranger + ranger-server-common + ${project.version} + + + io.dropwizard + dropwizard-core + provided + + + org.mockito + mockito-core + ${mockito.version} + test + + + org.wiremock + wiremock-standalone + ${wiremock.version} + test + + + io.dropwizard + dropwizard-testing + test + + + junit + junit + + + + + diff --git a/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundle.java b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundle.java new file mode 100644 index 00000000..bd1a0c6e --- /dev/null +++ b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundle.java @@ -0,0 +1,229 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.hub.server.bundle; + +import com.codahale.metrics.health.HealthCheck; +import com.fasterxml.jackson.core.type.TypeReference; +import com.google.common.base.Strings; +import com.phonepe.drove.models.api.ExposedAppInfo; +import io.appform.ranger.client.RangerHubClient; +import io.appform.ranger.client.drove.UnshardedRangerDroveHubClient; +import io.appform.ranger.client.http.UnshardedRangerHttpHubClient; +import io.appform.ranger.client.zk.UnshardedRangerZKHubClient; +import io.appform.ranger.common.server.ShardInfo; +import io.appform.ranger.core.finder.serviceregistry.ListBasedServiceRegistry; +import io.appform.ranger.core.model.HubConstants; +import io.appform.ranger.core.model.ServiceNode; +import io.appform.ranger.core.signals.Signal; +import io.appform.ranger.drove.config.DroveUpstreamConfig; +import io.appform.ranger.drove.serde.DroveResponseDataDeserializer; +import io.appform.ranger.drove.utils.RangerDroveUtils; +import io.appform.ranger.http.config.HttpClientConfig; +import io.appform.ranger.http.utils.RangerHttpUtils; +import io.appform.ranger.hub.server.bundle.configuration.RangerConfigurationVisitor; +import io.appform.ranger.hub.server.bundle.configuration.RangerDroveUpstreamConfiguration; +import io.appform.ranger.hub.server.bundle.configuration.RangerHttpUpstreamConfiguration; +import io.appform.ranger.hub.server.bundle.configuration.RangerServerConfiguration; +import io.appform.ranger.hub.server.bundle.configuration.RangerUpstreamConfiguration; +import io.appform.ranger.hub.server.bundle.configuration.RangerZkUpstreamConfiguration; +import io.appform.ranger.hub.server.bundle.healthcheck.RangerHealthCheck; +import io.appform.ranger.hub.server.bundle.lifecycle.CuratorLifecycle; +import io.appform.ranger.server.bundle.RangerServerBundle; +import io.dropwizard.core.Configuration; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.retry.RetryForever; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +@Slf4j +@SuppressWarnings("unused") +@NoArgsConstructor +public abstract class RangerHubServerBundle + extends RangerServerBundle, U> { + + protected abstract RangerServerConfiguration getRangerConfiguration(U configuration); + + private final List curatorFrameworks = new ArrayList<>(); + + @Override + protected List>> withHubs(U configuration) { + val serverConfig = getRangerConfiguration(configuration); + val upstreams = Objects.>requireNonNullElse( + serverConfig.getUpstreams(), Collections.emptyList()); + return upstreams.stream() + .map(rangerUpstreamConfiguration -> rangerUpstreamConfiguration.accept(new HubCreatorVisitor( + serverConfig.getNamespace(), serverConfig.getExcludedServices()))) + .flatMap(Collection::stream) + .toList(); + } + + @Override + protected List> withLifecycleSignals(U configuration) { + return curatorFrameworks.stream() + .map(curatorFramework -> (Signal) new CuratorLifecycle(curatorFramework)) + .toList(); + } + + @Override + protected List withHealthChecks(U configuration) { + return List.of(new RangerHealthCheck(curatorFrameworks)); + } + + @AllArgsConstructor + private class HubCreatorVisitor + implements RangerConfigurationVisitor>>> { + private final String namespace; + private final Set excludedServices; + + private RangerHubClient> addCuratorAndGetZkHubClient( + String zookeeper, RangerZkUpstreamConfiguration zkConfiguration) { + val curatorFramework = CuratorFrameworkFactory.builder() + .connectString(zookeeper) + .namespace(namespace) + .retryPolicy(new RetryForever(HubConstants.CONNECTION_RETRY_TIME_MS)) + .build(); + curatorFrameworks.add(curatorFramework); + return UnshardedRangerZKHubClient.builder() + .namespace(namespace) + .connectionString(zookeeper) + .curatorFramework(curatorFramework) + .disablePushUpdaters(zkConfiguration.isDisablePushUpdaters()) + .mapper(getMapper()) + .serviceRefreshTimeoutMs(zkConfiguration.getServiceRefreshTimeoutMs()) + .hubStartTimeoutMs(zkConfiguration.getHubStartTimeoutMs()) + .nodeRefreshTimeMs(zkConfiguration.getNodeRefreshTimeMs()) + .excludedServices(excludedServices) + .deserializer(data -> { + try { + return getMapper().readValue(data, new TypeReference>() { + }); + } catch (IOException e) { + logUnparseableData(data); + } + return null; + }) + .build(); + } + + private RangerHubClient> getHttpHubClient( + HttpClientConfig httpClientConfig, RangerHttpUpstreamConfiguration httpConfiguration) { + return UnshardedRangerHttpHubClient.builder() + .namespace(namespace) + .mapper(getMapper()) + .clientConfig(httpClientConfig) + .httpClient(RangerHttpUtils.httpClient(httpClientConfig, getMapper())) + .serviceRefreshTimeoutMs(httpConfiguration.getServiceRefreshTimeoutMs()) + .hubStartTimeoutMs(httpConfiguration.getHubStartTimeoutMs()) + .nodeRefreshTimeMs(httpConfiguration.getNodeRefreshTimeMs()) + .excludedServices(excludedServices) + .deserializer(data -> { + try { + return getMapper().readValue(data, new TypeReference<>() { + }); + } catch (IOException e) { + logUnparseableData(data); + } + return null; + }) + .build(); + } + + private RangerHubClient> getDroveClient( + final DroveUpstreamConfig droveConfig, RangerDroveUpstreamConfiguration droveUpstreamConfiguration) { + val envTagName = Objects.requireNonNullElse(droveConfig.getEnvironmentTagName(), + DroveUpstreamConfig.DEFAULT_ENVIRONMENT_TAG_NAME); + val regionTagName = Objects.requireNonNullElse(droveConfig.getRegionTagName(), + DroveUpstreamConfig.DEFAULT_REGION_TAG_NAME); + val droveCommunicator = RangerDroveUtils.buildDroveClient(namespace, droveConfig, getMapper()); + return UnshardedRangerDroveHubClient.builder() + .namespace(namespace) + .mapper(getMapper()) + .clientConfig(droveConfig) + .droveCommunicator(droveCommunicator) + .serviceRefreshTimeoutMs(droveUpstreamConfiguration.getServiceRefreshTimeoutMs()) + .hubStartTimeoutMs(droveUpstreamConfiguration.getHubStartTimeoutMs()) + .nodeRefreshTimeMs(droveUpstreamConfiguration.getNodeRefreshTimeMs()) + .excludedServices(excludedServices) + .deserializer(new DroveResponseDataDeserializer<>() { + @Override + protected ShardInfo translate(ExposedAppInfo appInfo, ExposedAppInfo.ExposedHost host) { + val tags = Objects.>requireNonNullElse( + appInfo.getTags(), Collections.emptyMap()); + var env = tags.get(envTagName); + env = Strings.isNullOrEmpty(env) ? droveConfig.getDefaultEnvironment() : env; + var region = tags.get(regionTagName); + region = Strings.isNullOrEmpty(region) ? droveConfig.getDefaultRegion() : region; + if (Strings.isNullOrEmpty(env) || Strings.isNullOrEmpty(region)) { + return null; + } + return ShardInfo.builder() + .environment(env) + .region(region) + .tags(tags.entrySet() + .stream() + .map(entry -> entry.getKey() + "|" + entry.getValue()) + .collect(Collectors.toUnmodifiableSet())) + .build(); + } + }) + .build(); + } + + @Override + public List>> visit( + RangerHttpUpstreamConfiguration rangerHttpConfiguration) { + return rangerHttpConfiguration.getHttpClientConfigs() + .stream() + .map(http -> getHttpHubClient(http, rangerHttpConfiguration)) + .toList(); + } + + @Override + public List>> visit(RangerZkUpstreamConfiguration rangerZkConfiguration) { + return rangerZkConfiguration.getZookeepers().stream() + .map(zk -> addCuratorAndGetZkHubClient(zk, rangerZkConfiguration)) + .toList(); + } + + @Override + public List>> visit( + RangerDroveUpstreamConfiguration rangerDroveConfiguration) { + return rangerDroveConfiguration.getDroveClusters() + .stream() + .map(zk -> getDroveClient(zk, rangerDroveConfiguration)) + .toList(); + } + } + + private static void logUnparseableData(byte[] data) { + log.warn("Error parsing service data with value {}", new String(data)); + } + +} diff --git a/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerConfigurationVisitor.java b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerConfigurationVisitor.java new file mode 100644 index 00000000..db01200a --- /dev/null +++ b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerConfigurationVisitor.java @@ -0,0 +1,27 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.hub.server.bundle.configuration; + +/** + * For handling configuration level handling + */ +public interface RangerConfigurationVisitor { + T visit(RangerHttpUpstreamConfiguration rangerHttpConfiguration); + + T visit(RangerZkUpstreamConfiguration rangerZkConfiguration); + + T visit(RangerDroveUpstreamConfiguration rangerDroveUpstreamConfiguration); +} diff --git a/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerDroveUpstreamConfiguration.java b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerDroveUpstreamConfiguration.java new file mode 100644 index 00000000..efc0d749 --- /dev/null +++ b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerDroveUpstreamConfiguration.java @@ -0,0 +1,54 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.hub.server.bundle.configuration; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.appform.ranger.drove.config.DroveUpstreamConfig; +import io.appform.ranger.hub.server.bundle.models.BackendType; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.util.List; + +/** + * + */ +@Getter +@Setter +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@JsonIgnoreProperties(ignoreUnknown = true) +public class RangerDroveUpstreamConfiguration extends RangerUpstreamConfiguration { + + @NotEmpty + @Valid + private List droveClusters; + + + public RangerDroveUpstreamConfiguration() { + super(BackendType.DROVE); + } + + @Override + public T accept(RangerConfigurationVisitor visitor) { + return visitor.visit(this); + } +} diff --git a/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerHttpUpstreamConfiguration.java b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerHttpUpstreamConfiguration.java new file mode 100644 index 00000000..1066cbe6 --- /dev/null +++ b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerHttpUpstreamConfiguration.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.hub.server.bundle.configuration; + + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.appform.ranger.http.config.HttpClientConfig; +import io.appform.ranger.hub.server.bundle.models.BackendType; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.util.List; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@JsonIgnoreProperties(ignoreUnknown = true) +public class RangerHttpUpstreamConfiguration extends RangerUpstreamConfiguration { + + @NotEmpty + @Valid + private List httpClientConfigs; + + public RangerHttpUpstreamConfiguration() { + super(BackendType.HTTP); + } + + @Override + public T accept(RangerConfigurationVisitor visitor) { + return visitor.visit(this); + } +} diff --git a/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerServerConfiguration.java b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerServerConfiguration.java new file mode 100644 index 00000000..79755be2 --- /dev/null +++ b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerServerConfiguration.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.hub.server.bundle.configuration; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Value; +import lombok.extern.jackson.Jacksonized; + +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * + */ +@Value +@Jacksonized +@Builder +public class RangerServerConfiguration { + @NotNull + @NotEmpty + String namespace; + + @NotEmpty + @Valid + List upstreams; + + Set excludedServices; + + public Set getExcludedServices() { + return Objects.requireNonNullElseGet(excludedServices, Set::of); + } + +} diff --git a/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerUpstreamConfiguration.java b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerUpstreamConfiguration.java new file mode 100644 index 00000000..d5bac1a0 --- /dev/null +++ b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerUpstreamConfiguration.java @@ -0,0 +1,55 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.hub.server.bundle.configuration; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import io.appform.ranger.core.model.HubConstants; +import io.appform.ranger.hub.server.bundle.models.BackendType; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; + + +@AllArgsConstructor +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type", visible = true) +@JsonSubTypes({ + @JsonSubTypes.Type(value = RangerHttpUpstreamConfiguration.class, name = "HTTP"), + @JsonSubTypes.Type(value = RangerZkUpstreamConfiguration.class, name = "ZK"), + @JsonSubTypes.Type(value = RangerDroveUpstreamConfiguration.class, name = "DROVE"), +}) +@Getter +public abstract class RangerUpstreamConfiguration { + + @NotNull + private BackendType type; + + @Min(HubConstants.MINIMUM_REFRESH_TIME_MS) + private int nodeRefreshTimeMs = HubConstants.MINIMUM_REFRESH_TIME_MS; + + @Min(HubConstants.MINIMUM_SERVICE_REFRESH_TIMEOUT_MS) + private int serviceRefreshTimeoutMs = HubConstants.SERVICE_REFRESH_TIMEOUT_MS; + + @Min(HubConstants.MINIMUM_HUB_START_TIMEOUT_MS) + private int hubStartTimeoutMs = HubConstants.HUB_START_TIMEOUT_MS; + + protected RangerUpstreamConfiguration(BackendType type) { + this.type = type; + } + + public abstract T accept(final RangerConfigurationVisitor visitor); +} diff --git a/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerZkUpstreamConfiguration.java b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerZkUpstreamConfiguration.java new file mode 100644 index 00000000..8651c60d --- /dev/null +++ b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerZkUpstreamConfiguration.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.hub.server.bundle.configuration; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.appform.ranger.hub.server.bundle.models.BackendType; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.util.List; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@JsonIgnoreProperties(ignoreUnknown = true) +public class RangerZkUpstreamConfiguration extends RangerUpstreamConfiguration { + + @NotEmpty + @Valid + private List zookeepers; + + private boolean disablePushUpdaters; + + protected RangerZkUpstreamConfiguration() { + super(BackendType.ZK); + } + + @Override + public T accept(RangerConfigurationVisitor visitor) { + return visitor.visit(this); + } +} diff --git a/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/healthcheck/RangerHealthCheck.java b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/healthcheck/RangerHealthCheck.java new file mode 100644 index 00000000..83ce1357 --- /dev/null +++ b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/healthcheck/RangerHealthCheck.java @@ -0,0 +1,40 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.hub.server.bundle.healthcheck; + +import com.codahale.metrics.health.HealthCheck; +import lombok.extern.slf4j.Slf4j; +import org.apache.curator.framework.CuratorFramework; + +import java.util.List; + +@Slf4j +public class RangerHealthCheck extends HealthCheck { + + private final List curatorFrameworks; + + public RangerHealthCheck(final List curatorFrameworks) { + this.curatorFrameworks = curatorFrameworks; + } + + @Override + protected Result check() { + return curatorFrameworks.stream() + .allMatch(curatorFramework -> curatorFramework.getZookeeperClient().isConnected()) + ? Result.healthy("Service is healthy") + : Result.unhealthy("Can't connect to zookeeper"); + } +} diff --git a/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/lifecycle/CuratorLifecycle.java b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/lifecycle/CuratorLifecycle.java new file mode 100644 index 00000000..1f98d719 --- /dev/null +++ b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/lifecycle/CuratorLifecycle.java @@ -0,0 +1,53 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.hub.server.bundle.lifecycle; + +import io.appform.ranger.common.server.ShardInfo; +import io.appform.ranger.core.signals.Signal; +import lombok.extern.slf4j.Slf4j; +import org.apache.curator.framework.CuratorFramework; + +import java.util.Collections; + +@Slf4j +public class CuratorLifecycle extends Signal { + + private final CuratorFramework curatorFramework; + + public CuratorLifecycle(CuratorFramework curatorFramework) { + super(() -> null, Collections.emptyList()); + this.curatorFramework = curatorFramework; + } + + @Override + public void start() { + log.info("Starting the curator"); + + curatorFramework.start(); + try { + curatorFramework.blockUntilConnected(); + } catch (InterruptedException e) { + log.error("Curator block interrupted", e); + Thread.currentThread().interrupt(); + } + log.info("Started the curator"); + } + + @Override + public void stop() { + curatorFramework.close(); + } +} diff --git a/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/models/BackendType.java b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/models/BackendType.java new file mode 100644 index 00000000..e99dcc8c --- /dev/null +++ b/ranger-hub-server-bundle-dw5/src/main/java/io/appform/ranger/hub/server/bundle/models/BackendType.java @@ -0,0 +1,22 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.hub.server.bundle.models; + +public enum BackendType { + ZK, + HTTP, + DROVE, +} diff --git a/ranger-hub-server-bundle-dw5/src/test/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundleTest.java b/ranger-hub-server-bundle-dw5/src/test/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundleTest.java new file mode 100644 index 00000000..36076228 --- /dev/null +++ b/ranger-hub-server-bundle-dw5/src/test/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundleTest.java @@ -0,0 +1,150 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.hub.server.bundle; + +import com.codahale.metrics.health.HealthCheckRegistry; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import com.google.common.collect.ImmutableList; +import io.appform.ranger.client.RangerHubClient; +import io.appform.ranger.common.server.ShardInfo; +import io.appform.ranger.core.healthcheck.HealthcheckStatus; +import io.appform.ranger.core.model.Service; +import io.appform.ranger.core.model.ServiceNode; +import io.appform.ranger.http.config.HttpClientConfig; +import io.appform.ranger.http.model.ServiceDataSourceResponse; +import io.appform.ranger.http.model.ServiceNodesResponse; +import io.appform.ranger.hub.server.bundle.configuration.RangerHttpUpstreamConfiguration; +import io.appform.ranger.hub.server.bundle.configuration.RangerServerConfiguration; +import io.appform.ranger.hub.server.bundle.configuration.RangerUpstreamConfiguration; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.setup.AdminEnvironment; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.jersey.DropwizardResourceConfig; +import io.dropwizard.jersey.setup.JerseyEnvironment; +import io.dropwizard.lifecycle.setup.LifecycleEnvironment; +import lombok.Getter; +import lombok.SneakyThrows; +import lombok.val; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static com.github.tomakehurst.wiremock.client.WireMock.any; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.okJson; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * + */ +@WireMockTest +class RangerHubServerBundleTest { + + @Test + @SneakyThrows + void test(final WireMockRuntimeInfo wm) { + @Getter + class TestConfig extends Configuration { + private final RangerServerConfiguration upstreams = RangerServerConfiguration.builder() + .namespace("test") + .upstreams(ImmutableList.builder() + .add(new RangerHttpUpstreamConfiguration() + .setHttpClientConfigs(List.of(HttpClientConfig.builder() + .host("localhost") + .port(wm.getHttpPort()) + .build()))) + .build()) + .build(); + + } + final TestConfig testConfig = new TestConfig(); + final HealthCheckRegistry healthChecks = mock(HealthCheckRegistry.class); + final JerseyEnvironment jerseyEnvironment = mock(JerseyEnvironment.class); + final LifecycleEnvironment lifecycleEnvironment = mock(LifecycleEnvironment.class); + final Environment environment = mock(Environment.class); + final AdminEnvironment adminEnvironment = mock(AdminEnvironment.class); + final Bootstrap bootstrap = mock(Bootstrap.class); + final ObjectMapper mapper = new ObjectMapper(); + + when(jerseyEnvironment.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(environment.jersey()).thenReturn(jerseyEnvironment); + when(environment.lifecycle()).thenReturn(lifecycleEnvironment); + when(environment.healthChecks()).thenReturn(healthChecks); + when(environment.admin()).thenReturn(adminEnvironment); + when(environment.getObjectMapper()).thenReturn(mapper); + when(bootstrap.getHealthCheckRegistry()).thenReturn(mock(HealthCheckRegistry.class)); + + val bundle = new RangerHubServerBundle() { + + @Override + protected RangerServerConfiguration getRangerConfiguration(TestConfig configuration) { + return testConfig.getUpstreams(); + } + }; + val services = IntStream.rangeClosed(1, 10) + .mapToObj(i -> Service.builder() + .namespace("test") + .serviceName("service-" + i) + .build()) + .collect(Collectors.toUnmodifiableSet()); + stubFor(get(urlPathEqualTo("/ranger/services/v1")) + .willReturn(okJson(environment.getObjectMapper() + .writeValueAsString(ServiceDataSourceResponse.builder() + .data(services) + .build())))); + stubFor(any(urlPathMatching("/ranger/nodes/v1/test/service-[0-9]+")) + .willReturn(okJson(mapper.writeValueAsString( + ServiceNodesResponse.builder() + .data(IntStream.rangeClosed(1, 5) + .mapToObj(i -> ServiceNode.builder() + .host("host-" + i) + .port(5000) + .nodeData(ShardInfo.builder() + .environment("blah") + .region("reg") + .build()) + .healthcheckStatus(HealthcheckStatus.healthy) + .lastUpdatedTimeStamp(System.currentTimeMillis()) + .build()) + .toList()) + .build())))); + + bundle.initialize(bootstrap); + bundle.run(testConfig, environment); + bundle.getHubs().forEach(RangerHubClient::start); + IntStream.rangeClosed(1, 10) + .forEach(i -> { + val nodes = bundle.getHubs() + .stream() + .flatMap(hub -> hub.getAllNodes(Service.builder().namespace("test").serviceName("service-" + i).build()).stream()) + .toList(); + Assertions.assertEquals(5, nodes.size()); + }); + + } + +} \ No newline at end of file diff --git a/ranger-hub-server-bundle/pom.xml b/ranger-hub-server-bundle/pom.xml index c23fc25e..a9d14e4e 100644 --- a/ranger-hub-server-bundle/pom.xml +++ b/ranger-hub-server-bundle/pom.xml @@ -16,8 +16,8 @@ --> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> ranger io.appform.ranger @@ -40,61 +40,66 @@ ranger-hub-server-bundle Dropwizard bundle for making Ranger HTTP Hub Server - - - io.appform.ranger - ranger-http-client - ${project.version} - - - io.appform.ranger - ranger-zk-client - ${project.version} - - - io.appform.ranger - ranger-drove-client - ${project.version} - - - io.appform.ranger - ranger-server-bundle - ${project.version} - - - io.appform.ranger - ranger-server-common - ${project.version} - - - io.dropwizard - dropwizard-core - ${dropwizard.version} - provided - - - org.mockito - mockito-core - ${mockito.version} - test - - - org.wiremock - wiremock-standalone - ${wiremock.version} - test - - - io.dropwizard - dropwizard-testing - test - - - junit - junit - - - - + + 2.1.12 + + + + + io.appform.ranger + ranger-http-client + ${project.version} + + + io.appform.ranger + ranger-zk-client + ${project.version} + + + io.appform.ranger + ranger-drove-client + ${project.version} + + + io.appform.ranger + ranger-server-bundle + ${project.version} + + + io.appform.ranger + ranger-server-common + ${project.version} + + + io.dropwizard + dropwizard-core + ${dropwizard.version} + provided + + + org.mockito + mockito-core + ${mockito.version} + test + + + org.wiremock + wiremock-standalone + ${wiremock.version} + test + + + io.dropwizard + dropwizard-testing + ${dropwizard.version} + test + + + junit + junit + + + + diff --git a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundle.java b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundle.java index 8a3eb670..b886bacf 100644 --- a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundle.java +++ b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundle.java @@ -33,7 +33,12 @@ import io.appform.ranger.drove.utils.RangerDroveUtils; import io.appform.ranger.http.config.HttpClientConfig; import io.appform.ranger.http.utils.RangerHttpUtils; -import io.appform.ranger.hub.server.bundle.configuration.*; +import io.appform.ranger.hub.server.bundle.configuration.RangerConfigurationVisitor; +import io.appform.ranger.hub.server.bundle.configuration.RangerDroveUpstreamConfiguration; +import io.appform.ranger.hub.server.bundle.configuration.RangerHttpUpstreamConfiguration; +import io.appform.ranger.hub.server.bundle.configuration.RangerServerConfiguration; +import io.appform.ranger.hub.server.bundle.configuration.RangerUpstreamConfiguration; +import io.appform.ranger.hub.server.bundle.configuration.RangerZkUpstreamConfiguration; import io.appform.ranger.hub.server.bundle.healthcheck.RangerHealthCheck; import io.appform.ranger.hub.server.bundle.lifecycle.CuratorLifecycle; import io.appform.ranger.server.bundle.RangerServerBundle; @@ -47,7 +52,13 @@ import org.apache.curator.retry.RetryForever; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; @Slf4j @@ -113,8 +124,7 @@ private RangerHubClient> addCurat try { return getMapper().readValue(data, new TypeReference>() { }); - } - catch (IOException e) { + } catch (IOException e) { logUnparseableData(data); } return null; @@ -135,9 +145,9 @@ private RangerHubClient> getHttpH .excludedServices(excludedServices) .deserializer(data -> { try { - return getMapper().readValue(data, new TypeReference<>() {}); - } - catch (IOException e) { + return getMapper().readValue(data, new TypeReference<>() { + }); + } catch (IOException e) { logUnparseableData(data); } return null; @@ -148,9 +158,9 @@ private RangerHubClient> getHttpH private RangerHubClient> getDroveClient( final DroveUpstreamConfig droveConfig, RangerDroveUpstreamConfiguration droveUpstreamConfiguration) { val envTagName = Objects.requireNonNullElse(droveConfig.getEnvironmentTagName(), - DroveUpstreamConfig.DEFAULT_ENVIRONMENT_TAG_NAME); + DroveUpstreamConfig.DEFAULT_ENVIRONMENT_TAG_NAME); val regionTagName = Objects.requireNonNullElse(droveConfig.getRegionTagName(), - DroveUpstreamConfig.DEFAULT_REGION_TAG_NAME); + DroveUpstreamConfig.DEFAULT_REGION_TAG_NAME); val droveCommunicator = RangerDroveUtils.buildDroveClient(namespace, droveConfig, getMapper()); return UnshardedRangerDroveHubClient.builder() .namespace(namespace) @@ -177,9 +187,9 @@ protected ShardInfo translate(ExposedAppInfo appInfo, ExposedAppInfo.ExposedHost .environment(env) .region(region) .tags(tags.entrySet() - .stream() - .map(entry -> entry.getKey() + "|" + entry.getValue()) - .collect(Collectors.toUnmodifiableSet())) + .stream() + .map(entry -> entry.getKey() + "|" + entry.getValue()) + .collect(Collectors.toUnmodifiableSet())) .build(); } }) diff --git a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerDroveUpstreamConfiguration.java b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerDroveUpstreamConfiguration.java index 9d5322a2..4c1fc7d3 100644 --- a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerDroveUpstreamConfiguration.java +++ b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerDroveUpstreamConfiguration.java @@ -19,8 +19,9 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.appform.ranger.drove.config.DroveUpstreamConfig; import io.appform.ranger.hub.server.bundle.models.BackendType; -import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; import lombok.ToString; import javax.validation.Valid; @@ -30,7 +31,8 @@ /** * */ -@Data +@Getter +@Setter @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerHttpUpstreamConfiguration.java b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerHttpUpstreamConfiguration.java index 96b9c423..9a6fd800 100644 --- a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerHttpUpstreamConfiguration.java +++ b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerHttpUpstreamConfiguration.java @@ -19,15 +19,17 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.appform.ranger.http.config.HttpClientConfig; import io.appform.ranger.hub.server.bundle.models.BackendType; -import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; import lombok.ToString; import javax.validation.Valid; import javax.validation.constraints.NotEmpty; import java.util.List; -@Data +@Getter +@Setter @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @JsonIgnoreProperties(ignoreUnknown = true) @@ -37,9 +39,9 @@ public class RangerHttpUpstreamConfiguration extends RangerUpstreamConfiguration @Valid private List httpClientConfigs; - public RangerHttpUpstreamConfiguration() { - super(BackendType.HTTP); - } + public RangerHttpUpstreamConfiguration() { + super(BackendType.HTTP); + } @Override public T accept(RangerConfigurationVisitor visitor) { diff --git a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerServerConfiguration.java b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerServerConfiguration.java index e2232a33..bbb4c982 100644 --- a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerServerConfiguration.java +++ b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerServerConfiguration.java @@ -15,8 +15,6 @@ */ package io.appform.ranger.hub.server.bundle.configuration; -import java.util.Objects; -import java.util.Set; import lombok.Builder; import lombok.Value; import lombok.extern.jackson.Jacksonized; @@ -25,6 +23,8 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; +import java.util.Objects; +import java.util.Set; /** * @@ -44,7 +44,7 @@ public class RangerServerConfiguration { Set excludedServices; public Set getExcludedServices() { - return Objects.requireNonNullElseGet(excludedServices,Set::of); + return Objects.requireNonNullElseGet(excludedServices, Set::of); } } diff --git a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerUpstreamConfiguration.java b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerUpstreamConfiguration.java index 06ec4b43..f044081b 100644 --- a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerUpstreamConfiguration.java +++ b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerUpstreamConfiguration.java @@ -28,28 +28,28 @@ @AllArgsConstructor @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type", visible = true) @JsonSubTypes({ - @JsonSubTypes.Type(value = RangerHttpUpstreamConfiguration.class, name = "HTTP"), - @JsonSubTypes.Type(value = RangerZkUpstreamConfiguration.class, name = "ZK"), - @JsonSubTypes.Type(value = RangerDroveUpstreamConfiguration.class, name = "DROVE"), + @JsonSubTypes.Type(value = RangerHttpUpstreamConfiguration.class, name = "HTTP"), + @JsonSubTypes.Type(value = RangerZkUpstreamConfiguration.class, name = "ZK"), + @JsonSubTypes.Type(value = RangerDroveUpstreamConfiguration.class, name = "DROVE"), }) @Getter public abstract class RangerUpstreamConfiguration { - @NotNull - private BackendType type; + @NotNull + private BackendType type; - @Min(HubConstants.MINIMUM_REFRESH_TIME_MS) - private int nodeRefreshTimeMs = HubConstants.MINIMUM_REFRESH_TIME_MS; + @Min(HubConstants.MINIMUM_REFRESH_TIME_MS) + private int nodeRefreshTimeMs = HubConstants.MINIMUM_REFRESH_TIME_MS; - @Min(HubConstants.MINIMUM_SERVICE_REFRESH_TIMEOUT_MS) - private int serviceRefreshTimeoutMs = HubConstants.SERVICE_REFRESH_TIMEOUT_MS; + @Min(HubConstants.MINIMUM_SERVICE_REFRESH_TIMEOUT_MS) + private int serviceRefreshTimeoutMs = HubConstants.SERVICE_REFRESH_TIMEOUT_MS; - @Min(HubConstants.MINIMUM_HUB_START_TIMEOUT_MS) - private int hubStartTimeoutMs = HubConstants.HUB_START_TIMEOUT_MS; + @Min(HubConstants.MINIMUM_HUB_START_TIMEOUT_MS) + private int hubStartTimeoutMs = HubConstants.HUB_START_TIMEOUT_MS; - protected RangerUpstreamConfiguration(BackendType type) { - this.type = type; - } + protected RangerUpstreamConfiguration(BackendType type) { + this.type = type; + } - public abstract T accept(final RangerConfigurationVisitor visitor); + public abstract T accept(final RangerConfigurationVisitor visitor); } diff --git a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerZkUpstreamConfiguration.java b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerZkUpstreamConfiguration.java index 8927e835..05803c03 100644 --- a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerZkUpstreamConfiguration.java +++ b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/configuration/RangerZkUpstreamConfiguration.java @@ -17,32 +17,34 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.appform.ranger.hub.server.bundle.models.BackendType; -import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; import lombok.ToString; import javax.validation.Valid; import javax.validation.constraints.NotEmpty; import java.util.List; -@Data +@Getter +@Setter @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @JsonIgnoreProperties(ignoreUnknown = true) public class RangerZkUpstreamConfiguration extends RangerUpstreamConfiguration { - @NotEmpty - @Valid - private List zookeepers; + @NotEmpty + @Valid + private List zookeepers; - private boolean disablePushUpdaters; + private boolean disablePushUpdaters; - protected RangerZkUpstreamConfiguration() { - super(BackendType.ZK); - } + protected RangerZkUpstreamConfiguration() { + super(BackendType.ZK); + } - @Override - public T accept(RangerConfigurationVisitor visitor) { - return visitor.visit(this); - } + @Override + public T accept(RangerConfigurationVisitor visitor) { + return visitor.visit(this); + } } diff --git a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/healthcheck/RangerHealthCheck.java b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/healthcheck/RangerHealthCheck.java index 76fb0d3c..83ce1357 100644 --- a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/healthcheck/RangerHealthCheck.java +++ b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/healthcheck/RangerHealthCheck.java @@ -24,17 +24,17 @@ @Slf4j public class RangerHealthCheck extends HealthCheck { - private final List curatorFrameworks; + private final List curatorFrameworks; - public RangerHealthCheck(final List curatorFrameworks){ - this.curatorFrameworks = curatorFrameworks; - } + public RangerHealthCheck(final List curatorFrameworks) { + this.curatorFrameworks = curatorFrameworks; + } - @Override - protected Result check() { - return curatorFrameworks.stream() - .allMatch(curatorFramework -> curatorFramework.getZookeeperClient().isConnected()) - ? Result.healthy("Service is healthy") - : Result.unhealthy("Can't connect to zookeeper"); - } + @Override + protected Result check() { + return curatorFrameworks.stream() + .allMatch(curatorFramework -> curatorFramework.getZookeeperClient().isConnected()) + ? Result.healthy("Service is healthy") + : Result.unhealthy("Can't connect to zookeeper"); + } } diff --git a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/lifecycle/CuratorLifecycle.java b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/lifecycle/CuratorLifecycle.java index cebf856b..1f98d719 100644 --- a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/lifecycle/CuratorLifecycle.java +++ b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/lifecycle/CuratorLifecycle.java @@ -25,30 +25,29 @@ @Slf4j public class CuratorLifecycle extends Signal { - private final CuratorFramework curatorFramework; + private final CuratorFramework curatorFramework; - public CuratorLifecycle(CuratorFramework curatorFramework) { - super(() -> null, Collections.emptyList()); - this.curatorFramework = curatorFramework; - } - - @Override - public void start() { - log.info("Starting the curator"); - - curatorFramework.start(); - try { - curatorFramework.blockUntilConnected(); + public CuratorLifecycle(CuratorFramework curatorFramework) { + super(() -> null, Collections.emptyList()); + this.curatorFramework = curatorFramework; } - catch (InterruptedException e) { - log.error("Curator block interrupted", e); - Thread.currentThread().interrupt(); + + @Override + public void start() { + log.info("Starting the curator"); + + curatorFramework.start(); + try { + curatorFramework.blockUntilConnected(); + } catch (InterruptedException e) { + log.error("Curator block interrupted", e); + Thread.currentThread().interrupt(); + } + log.info("Started the curator"); } - log.info("Started the curator"); - } - @Override - public void stop() { - curatorFramework.close(); - } + @Override + public void stop() { + curatorFramework.close(); + } } diff --git a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/models/BackendType.java b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/models/BackendType.java index 16c68886..e99dcc8c 100644 --- a/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/models/BackendType.java +++ b/ranger-hub-server-bundle/src/main/java/io/appform/ranger/hub/server/bundle/models/BackendType.java @@ -16,7 +16,7 @@ package io.appform.ranger.hub.server.bundle.models; public enum BackendType { - ZK, - HTTP, - DROVE, + ZK, + HTTP, + DROVE, } diff --git a/ranger-hub-server-bundle/src/test/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundleTest.java b/ranger-hub-server-bundle/src/test/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundleTest.java index 3b41b263..4cf92b96 100644 --- a/ranger-hub-server-bundle/src/test/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundleTest.java +++ b/ranger-hub-server-bundle/src/test/java/io/appform/ranger/hub/server/bundle/RangerHubServerBundleTest.java @@ -49,7 +49,12 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static com.github.tomakehurst.wiremock.client.WireMock.any; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.okJson; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -67,12 +72,12 @@ class TestConfig extends Configuration { private final RangerServerConfiguration upstreams = RangerServerConfiguration.builder() .namespace("test") .upstreams(ImmutableList.builder() - .add(new RangerHttpUpstreamConfiguration() - .setHttpClientConfigs(List.of(HttpClientConfig.builder() - .host("localhost") - .port(wm.getHttpPort()) - .build()))) - .build()) + .add(new RangerHttpUpstreamConfiguration() + .setHttpClientConfigs(List.of(HttpClientConfig.builder() + .host("localhost") + .port(wm.getHttpPort()) + .build()))) + .build()) .build(); } @@ -101,37 +106,37 @@ protected RangerServerConfiguration getRangerConfiguration(TestConfig configurat } }; val services = IntStream.rangeClosed(1, 10) - .mapToObj(i -> Service.builder() - .namespace("test") - .serviceName("service-" + i) - .build()) - .collect(Collectors.toUnmodifiableSet()); + .mapToObj(i -> Service.builder() + .namespace("test") + .serviceName("service-" + i) + .build()) + .collect(Collectors.toUnmodifiableSet()); stubFor(get(urlPathEqualTo("/ranger/services/v1")) - .willReturn(okJson(environment.getObjectMapper() - .writeValueAsString(ServiceDataSourceResponse.builder() - .data(services) - .build())))); + .willReturn(okJson(environment.getObjectMapper() + .writeValueAsString(ServiceDataSourceResponse.builder() + .data(services) + .build())))); stubFor(any(urlPathMatching("/ranger/nodes/v1/test/service-[0-9]+")) - .willReturn(okJson(mapper.writeValueAsString( - ServiceNodesResponse.builder() - .data(IntStream.rangeClosed(1, 5) - .mapToObj(i -> ServiceNode.builder() - .host("host-" + i) - .port(5000) - .nodeData(ShardInfo.builder() - .environment("blah") - .region("reg") - .build()) - .healthcheckStatus(HealthcheckStatus.healthy) - .lastUpdatedTimeStamp(System.currentTimeMillis()) - .build()) - .toList()) - .build())))); + .willReturn(okJson(mapper.writeValueAsString( + ServiceNodesResponse.builder() + .data(IntStream.rangeClosed(1, 5) + .mapToObj(i -> ServiceNode.builder() + .host("host-" + i) + .port(5000) + .nodeData(ShardInfo.builder() + .environment("blah") + .region("reg") + .build()) + .healthcheckStatus(HealthcheckStatus.healthy) + .lastUpdatedTimeStamp(System.currentTimeMillis()) + .build()) + .toList()) + .build())))); bundle.initialize(bootstrap); bundle.run(testConfig, environment); bundle.getHubs().forEach(RangerHubClient::start); - IntStream.rangeClosed(1,10) + IntStream.rangeClosed(1, 10) .forEach(i -> { val nodes = bundle.getHubs() .stream() diff --git a/ranger-id/perf/results/io.appform.ranger.id.IdGeneratorPerfTest.testGenerate.json b/ranger-id/perf/results/io.appform.ranger.id.IdGeneratorPerfTest.testGenerate.json index 52200d6a..889c2ddf 100644 --- a/ranger-id/perf/results/io.appform.ranger.id.IdGeneratorPerfTest.testGenerate.json +++ b/ranger-id/perf/results/io.appform.ranger.id.IdGeneratorPerfTest.testGenerate.json @@ -1,8 +1,8 @@ { - "name" : "io.appform.ranger.id.IdGeneratorPerfTest.testGenerate", - "mode" : "Throughput", - "iterations" : 4, - "threads" : 1, - "forks" : 3, - "mean_ops" : 975682.0796321044 + "name": "io.appform.ranger.id.IdGeneratorPerfTest.testGenerate", + "mode": "Throughput", + "iterations": 4, + "threads": 1, + "forks": 3, + "mean_ops": 395461.00074843783 } \ No newline at end of file diff --git a/ranger-id/perf/results/io.appform.ranger.id.IdGeneratorPerfTest.testGenerateBase36.json b/ranger-id/perf/results/io.appform.ranger.id.IdGeneratorPerfTest.testGenerateBase36.json index abce97e7..c90b372b 100644 --- a/ranger-id/perf/results/io.appform.ranger.id.IdGeneratorPerfTest.testGenerateBase36.json +++ b/ranger-id/perf/results/io.appform.ranger.id.IdGeneratorPerfTest.testGenerateBase36.json @@ -1,8 +1,8 @@ { - "name" : "io.appform.ranger.id.IdGeneratorPerfTest.testGenerateBase36", - "mode" : "Throughput", - "iterations" : 4, - "threads" : 1, - "forks" : 3, - "mean_ops" : 906486.314013776 + "name": "io.appform.ranger.id.IdGeneratorPerfTest.testGenerateBase36", + "mode": "Throughput", + "iterations": 4, + "threads": 1, + "forks": 3, + "mean_ops": 271525.95816006133 } \ No newline at end of file diff --git a/ranger-id/pom.xml b/ranger-id/pom.xml index 81d3bf38..d54fcc8f 100644 --- a/ranger-id/pom.xml +++ b/ranger-id/pom.xml @@ -17,6 +17,7 @@ UTF-8 3.2.4 1.35 + 2.12.7 @@ -25,6 +26,11 @@ failsafe ${failsafe.version} + + joda-time + joda-time + ${joda-time.version} + io.appform.ranger ranger-zk-client diff --git a/ranger-id/src/main/java/io/appform/ranger/id/CollisionChecker.java b/ranger-id/src/main/java/io/appform/ranger/id/CollisionChecker.java index 7e897a27..9be99a6d 100644 --- a/ranger-id/src/main/java/io/appform/ranger/id/CollisionChecker.java +++ b/ranger-id/src/main/java/io/appform/ranger/id/CollisionChecker.java @@ -58,8 +58,7 @@ public boolean check(long timeInMillis, int location) { } bitSet.set(location); return true; - } - finally { + } finally { dataLock.unlock(); } } @@ -71,8 +70,7 @@ public void free(long time, int location) { return; } bitSet.clear(location); - } - finally { + } finally { dataLock.unlock(); } } diff --git a/ranger-id/src/main/java/io/appform/ranger/id/Domain.java b/ranger-id/src/main/java/io/appform/ranger/id/Domain.java index 3315a76a..3e790c8f 100644 --- a/ranger-id/src/main/java/io/appform/ranger/id/Domain.java +++ b/ranger-id/src/main/java/io/appform/ranger/id/Domain.java @@ -33,9 +33,9 @@ public class Domain { public static final String DEFAULT_DOMAIN_NAME = "__DEFAULT_DOMAIN__"; public static final Domain DEFAULT = new Domain(DEFAULT_DOMAIN_NAME, - List.of(), - new DefaultIdFormatter(), - TimeUnit.MILLISECONDS); + List.of(), + new DefaultIdFormatter(), + TimeUnit.MILLISECONDS); private final String domain; private final List constraints; diff --git a/ranger-id/src/main/java/io/appform/ranger/id/Id.java b/ranger-id/src/main/java/io/appform/ranger/id/Id.java index 2356a8ae..1db1c52e 100644 --- a/ranger-id/src/main/java/io/appform/ranger/id/Id.java +++ b/ranger-id/src/main/java/io/appform/ranger/id/Id.java @@ -16,7 +16,11 @@ package io.appform.ranger.id; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; import java.util.Date; diff --git a/ranger-id/src/main/java/io/appform/ranger/id/IdGenerator.java b/ranger-id/src/main/java/io/appform/ranger/id/IdGenerator.java index efd2acf1..ca47af58 100644 --- a/ranger-id/src/main/java/io/appform/ranger/id/IdGenerator.java +++ b/ranger-id/src/main/java/io/appform/ranger/id/IdGenerator.java @@ -28,7 +28,9 @@ import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.Optional; /** * Id generation @@ -51,7 +53,7 @@ public static synchronized void initialize( int node, List globalConstraints, Map> domainSpecificConstraints) { initialize(node); - if(null != globalConstraints && !globalConstraints.isEmpty() ) { + if (null != globalConstraints && !globalConstraints.isEmpty()) { baseGenerator.registerGlobalConstraints(globalConstraints); } @@ -101,7 +103,7 @@ public static Id generate( } /** - * Generate id that mathces all passed constraints. + * Generate id that matches all passed constraints. * NOTE: There are performance implications for this. * The evaluation of constraints will take it's toll on id generation rates. Tun rests to check speed. * @@ -114,9 +116,9 @@ public static Optional generateWithConstraints(String prefix, @NonNull Strin } /** - * Generate id that mathces all passed constraints. + * Generate id that matches all passed constraints. * NOTE: There are performance implications for this. - * The evaluation of constraints will take it's toll on id generation rates. Tun rests to check speed. + * The evaluation of constraints will take its toll on id generation rates. Tun rests to check speed. * * @param prefix String prefix * @param domain Domain for constraint selection @@ -167,11 +169,11 @@ public static Optional generateWithConstraints( final List inConstraints, boolean skipGlobal) { return generate(IdGenerationRequest.builder() - .prefix(prefix) - .constraints(inConstraints) - .skipGlobal(skipGlobal) - .idFormatter(IdFormatters.original()) - .build()); + .prefix(prefix) + .constraints(inConstraints) + .skipGlobal(skipGlobal) + .idFormatter(IdFormatters.original()) + .build()); } /** @@ -189,12 +191,12 @@ private static Optional generateWithConstraints( final Domain domain, boolean skipGlobal) { return generate(IdGenerationRequest.builder() - .prefix(prefix) - .constraints(domain.getConstraints()) - .skipGlobal(skipGlobal) - .domain(domain.getDomain()) - .idFormatter(domain.getIdFormatter()) - .build()); + .prefix(prefix) + .constraints(domain.getConstraints()) + .skipGlobal(skipGlobal) + .domain(domain.getDomain()) + .idFormatter(domain.getIdFormatter()) + .build()); } public static Optional generate(final IdGenerationRequest request) { diff --git a/ranger-id/src/main/java/io/appform/ranger/id/constraints/impl/MurmurBasedKeyPartitioner.java b/ranger-id/src/main/java/io/appform/ranger/id/constraints/impl/MurmurBasedKeyPartitioner.java index f3c9ad87..881cadc8 100644 --- a/ranger-id/src/main/java/io/appform/ranger/id/constraints/impl/MurmurBasedKeyPartitioner.java +++ b/ranger-id/src/main/java/io/appform/ranger/id/constraints/impl/MurmurBasedKeyPartitioner.java @@ -34,7 +34,6 @@ public MurmurBasedKeyPartitioner(int maxPartitions) { } @Override - @SuppressWarnings("UnstableApiUsage") public int partition(Id id) { int hashCode = Hashing.murmur3_128().hashString(id.toString(), StandardCharsets.UTF_8).asInt(); hashCode *= hashCode < 0 ? -1 : 1; diff --git a/ranger-id/src/main/java/io/appform/ranger/id/constraints/impl/PartitionValidator.java b/ranger-id/src/main/java/io/appform/ranger/id/constraints/impl/PartitionValidator.java index f0fe9598..bd3323ab 100644 --- a/ranger-id/src/main/java/io/appform/ranger/id/constraints/impl/PartitionValidator.java +++ b/ranger-id/src/main/java/io/appform/ranger/id/constraints/impl/PartitionValidator.java @@ -32,9 +32,9 @@ public class PartitionValidator implements IdValidationConstraint { public PartitionValidator(int partition, KeyPartitioner partitioner) { Preconditions.checkArgument(partition > 0, - "Provide a non-negative and non-zero partition count"); + "Provide a non-negative and non-zero partition count"); Preconditions.checkArgument(partitioner != null, - "Provide a non null key partitioner"); + "Provide a non null key partitioner"); this.partition = partition; this.partitioner = partitioner; } diff --git a/ranger-id/src/main/java/io/appform/ranger/id/formatter/DefaultIdFormatter.java b/ranger-id/src/main/java/io/appform/ranger/id/formatter/DefaultIdFormatter.java index f9cd2166..d7e88edc 100644 --- a/ranger-id/src/main/java/io/appform/ranger/id/formatter/DefaultIdFormatter.java +++ b/ranger-id/src/main/java/io/appform/ranger/id/formatter/DefaultIdFormatter.java @@ -25,7 +25,7 @@ import java.util.regex.Pattern; public class DefaultIdFormatter implements IdFormatter { - private static final Pattern PATTERN = Pattern.compile("(.*)([0-9]{15})([0-9]{4})([0-9]{3})"); + private static final Pattern PATTERN = Pattern.compile("(.*)(\\d{15})(\\d{4})(\\d{3})"); private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyMMddHHmmssSSS"); @Override diff --git a/ranger-id/src/main/java/io/appform/ranger/id/formatter/IdParserType.java b/ranger-id/src/main/java/io/appform/ranger/id/formatter/IdParserType.java index 4ec0ea45..9c007aec 100644 --- a/ranger-id/src/main/java/io/appform/ranger/id/formatter/IdParserType.java +++ b/ranger-id/src/main/java/io/appform/ranger/id/formatter/IdParserType.java @@ -4,7 +4,7 @@ @Getter public enum IdParserType { - DEFAULT (0); + DEFAULT(0); private final int value; diff --git a/ranger-id/src/main/java/io/appform/ranger/id/formatter/IdParsers.java b/ranger-id/src/main/java/io/appform/ranger/id/formatter/IdParsers.java index 76d57317..ffeef2dd 100644 --- a/ranger-id/src/main/java/io/appform/ranger/id/formatter/IdParsers.java +++ b/ranger-id/src/main/java/io/appform/ranger/id/formatter/IdParsers.java @@ -29,7 +29,7 @@ @UtilityClass public class IdParsers { private static final int MINIMUM_ID_LENGTH = 22; - private static final Pattern PATTERN = Pattern.compile("([A-Za-z]*)([0-9]{22})([0-9]{2})?(.*)"); + private static final Pattern PATTERN = Pattern.compile("([A-Za-z]*)(\\d{22})(\\d{2})?(.*)"); private final Map parserRegistry = Map.of( IdFormatters.original().getType().getValue(), IdFormatters.original() @@ -64,14 +64,13 @@ public class IdParsers { * @param idString the string representation of the ID to parse. Must not be null and should be * at least {@value #MINIMUM_ID_LENGTH} characters long to be considered valid * @return an {@link Optional} containing the parsed {@link Id} if the string could be successfully - * parsed and converted, or {@link Optional#empty()} if: - *
    - *
  • The input string is null
  • - *
  • The input string is shorter than the minimum required length
  • - *
  • The input string doesn't match the expected regex pattern
  • - *
  • An exception occurs during parsing
  • - *
- * + * parsed and converted, or {@link Optional#empty()} if: + *
    + *
  • The input string is null
  • + *
  • The input string is shorter than the minimum required length
  • + *
  • The input string doesn't match the expected regex pattern
  • + *
  • An exception occurs during parsing
  • + *
* @see Id * @see IdFormatter * @see IdFormatters#original() diff --git a/ranger-id/src/main/java/io/appform/ranger/id/generator/IdGeneratorBase.java b/ranger-id/src/main/java/io/appform/ranger/id/generator/IdGeneratorBase.java index ed2c8bff..aee34054 100644 --- a/ranger-id/src/main/java/io/appform/ranger/id/generator/IdGeneratorBase.java +++ b/ranger-id/src/main/java/io/appform/ranger/id/generator/IdGeneratorBase.java @@ -7,8 +7,8 @@ import io.appform.ranger.id.Domain; import io.appform.ranger.id.GenerationResult; import io.appform.ranger.id.Id; -import io.appform.ranger.id.NonceInfo; import io.appform.ranger.id.IdValidationState; +import io.appform.ranger.id.NonceInfo; import io.appform.ranger.id.constraints.IdValidationConstraint; import io.appform.ranger.id.formatter.IdFormatter; import io.appform.ranger.id.formatter.IdFormatters; diff --git a/ranger-id/src/main/java/io/appform/ranger/id/nonce/RandomNonceGenerator.java b/ranger-id/src/main/java/io/appform/ranger/id/nonce/RandomNonceGenerator.java index a9789216..441d3eb2 100644 --- a/ranger-id/src/main/java/io/appform/ranger/id/nonce/RandomNonceGenerator.java +++ b/ranger-id/src/main/java/io/appform/ranger/id/nonce/RandomNonceGenerator.java @@ -5,8 +5,8 @@ import io.appform.ranger.id.Constants; import io.appform.ranger.id.Domain; import io.appform.ranger.id.GenerationResult; -import io.appform.ranger.id.NonceInfo; import io.appform.ranger.id.IdValidationState; +import io.appform.ranger.id.NonceInfo; import io.appform.ranger.id.request.IdGenerationInput; import lombok.val; diff --git a/ranger-id/src/test/java/io/appform/ranger/id/IdGeneratorPerfTest.java b/ranger-id/src/test/java/io/appform/ranger/id/IdGeneratorPerfTest.java index 43e1241b..6bd7605b 100644 --- a/ranger-id/src/test/java/io/appform/ranger/id/IdGeneratorPerfTest.java +++ b/ranger-id/src/test/java/io/appform/ranger/id/IdGeneratorPerfTest.java @@ -19,11 +19,13 @@ import io.appform.ranger.id.formatter.IdFormatters; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.infra.Blackhole; -import java.io.IOException; - /** * Test performance between different constructs */ @@ -34,7 +36,7 @@ public class IdGeneratorPerfTest extends BenchmarkTest { public static class BenchmarkState { @Setup(Level.Trial) - public void setUp() throws IOException { + public void setUp() { IdGenerator.initialize(23); } } diff --git a/ranger-id/src/test/java/io/appform/ranger/id/IdGeneratorTest.java b/ranger-id/src/test/java/io/appform/ranger/id/IdGeneratorTest.java index 31c86a97..c8d18a74 100644 --- a/ranger-id/src/test/java/io/appform/ranger/id/IdGeneratorTest.java +++ b/ranger-id/src/test/java/io/appform/ranger/id/IdGeneratorTest.java @@ -16,7 +16,6 @@ package io.appform.ranger.id; -import com.google.common.collect.ImmutableList; import io.appform.ranger.id.constraints.IdValidationConstraint; import io.appform.ranger.id.constraints.impl.JavaHashCodeBasedKeyPartitioner; import io.appform.ranger.id.constraints.impl.PartitionValidator; @@ -37,6 +36,7 @@ import java.time.ZonedDateTime; import java.util.Collections; import java.util.Date; +import java.util.List; import java.util.Optional; import java.util.concurrent.Callable; import java.util.concurrent.Executors; @@ -179,7 +179,7 @@ void testGenerateWithConstraintsNoConstraint() { void testConstraintFailure() { Assertions.assertFalse(IdGenerator.generateWithConstraints( "TST", - ImmutableList.of(id -> false), + List.of(id -> false), false).isPresent()); } @@ -225,7 +225,7 @@ void testParseSuccess() { Assertions.assertEquals(247, id.getExponent()); Assertions.assertEquals(3972, id.getNode()); Assertions.assertEquals(generateDate(2020, 11, 25, 9, 59, 3, 64, ZoneId.systemDefault()), - id.getGeneratedDate()); + id.getGeneratedDate()); } @Test @@ -247,11 +247,11 @@ private Date generateDate(int year, int month, int day, int hour, int min, int s ZonedDateTime.of( LocalDateTime.of( year, month, day, hour, min, sec, Math.multiplyExact(ms, 1000000) - ), + ), zoneId - ) - ) - ); + ) + ) + ); } diff --git a/ranger-id/src/test/java/io/appform/ranger/id/IdParsersTest.java b/ranger-id/src/test/java/io/appform/ranger/id/IdParsersTest.java index 63f9c0de..662d1773 100644 --- a/ranger-id/src/test/java/io/appform/ranger/id/IdParsersTest.java +++ b/ranger-id/src/test/java/io/appform/ranger/id/IdParsersTest.java @@ -9,7 +9,7 @@ import java.text.SimpleDateFormat; import java.util.Date; -public class IdParsersTest { +class IdParsersTest { @Test void testDefaultId() throws ParseException { diff --git a/ranger-server-bundle-dw5/README.md b/ranger-server-bundle-dw5/README.md new file mode 100644 index 00000000..47a17439 --- /dev/null +++ b/ranger-server-bundle-dw5/README.md @@ -0,0 +1,65 @@ +# Ranger Server Bundle + +Ranger server bundle is a common dropwizard bundle atop which we could implement any http based ranger backend. + +- Provides the core interface atop which any ranger http backend could be built. +- Provides type-safe generic interface for integration with the above. +- A really easy plug and play system to get started. +- Abstracts out ranger's finder hub's complexity. +- Written atop the wonderful. [Dropwizard](http://dropwizard.io/) + +#### Using a server bundle to initialize a ZK backend. + +``` + val rangerServerBundle = new RangerServerBundle, ZkNodeDataDeserializer, + AppConfiguration>() { + + @Override + protected List>> withHubs(AppConfiguration configuration) { + return Lists.newArrayList( + RangerServerUtils.buildRangerHub(curatorFramework, rangerConfiguration, environment.getObjectMapper()) + ); + } + + @Override + protected boolean withInitialRotationStatus(AppConfiguration configuration) { + return appConfiguration.isInitialRotationStatus(); + } + }; + rangerServerBundle.run(appConfiguration, environment); + + rangerServerBundle.start() +``` + +#### Using a server bundle to initialize a HTTP backend. + +``` + val rangerServerBundle = new RangerServerBundle, HTTPResponseDataDeserializer, + AppConfiguration>() { + + @Override + protected List>> withHubs(AppConfiguration configuration) { + val clientConfigs = configuration.getRangerConfiguration().getHttpClientConfigs(); + return clientConfigs.stream().map(clientConfig -> + RangerHttpServerUtils.buildRangerHub( + rangerConfiguration.getNamespace(), + rangerConfiguration.getNodeRefreshTimeMs(), + clientConfig, + environment.getObjectMapper() + )).toList(); + } + + @Override + protected boolean withInitialRotationStatus(AppConfiguration configuration) { + return appConfiguration.isInitialRotationStatus(); + } + }; + rangerServerBundle.run(appConfiguration, environment); + rangerServerBundle.start(); +``` + +Stop the bundle once you are done with it. + +``` +rangerServerBundle.stop(); +``` \ No newline at end of file diff --git a/ranger-server-bundle-dw5/pom.xml b/ranger-server-bundle-dw5/pom.xml new file mode 100644 index 00000000..83f23493 --- /dev/null +++ b/ranger-server-bundle-dw5/pom.xml @@ -0,0 +1,90 @@ + + + + + + ranger + io.appform.ranger + 2.0.0-SNAPSHOT + + 4.0.0 + + ranger-server-bundle-dw5 + Dropwizard 5.x Server Bundle for Ranger + + + 5.0.0 + + + + + + io.dropwizard + dropwizard-bom + ${dropwizard.version} + pom + import + + + + + + + io.appform.ranger + ranger-client + ${project.version} + + + io.appform.ranger + ranger-http-model + ${project.version} + + + io.dropwizard + dropwizard-core + ${dropwizard.version} + provided + + + io.dropwizard + dropwizard-jackson + ${dropwizard.version} + provided + + + org.mockito + mockito-core + ${mockito.version} + test + + + org.wiremock + wiremock-standalone + ${wiremock.version} + test + + + io.appform.ranger + ranger-client + ${project.version} + test-jar + + + + diff --git a/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/RangerServerBundle.java b/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/RangerServerBundle.java new file mode 100644 index 00000000..740d244f --- /dev/null +++ b/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/RangerServerBundle.java @@ -0,0 +1,134 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.server.bundle; + +import com.codahale.metrics.health.HealthCheck; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.appform.ranger.client.RangerHubClient; +import io.appform.ranger.core.model.ServiceRegistry; +import io.appform.ranger.core.signals.Signal; +import io.appform.ranger.server.bundle.resources.RangerResource; +import io.appform.ranger.server.bundle.rotation.BirTask; +import io.appform.ranger.server.bundle.rotation.OorTask; +import io.appform.ranger.server.bundle.rotation.RotationCheck; +import io.appform.ranger.server.bundle.rotation.RotationStatus; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.ConfiguredBundle; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.lifecycle.Managed; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import lombok.val; + +import java.util.List; + +@Getter +@Slf4j +public abstract class RangerServerBundle< + T, + R extends ServiceRegistry, + U extends Configuration> implements ConfiguredBundle { + + /* + Why are we taking a list of hubs, instead of one? To be able to aggregate from different dataSources if need be + instead of just fetching from a single dataSource. + + Please check the {@link RangerResource} for how a list is getting aggregated. + + You could also define your custom aggregation by using the {@link RangerHubClient} + */ + private List> hubs; + private ObjectMapper mapper; + + protected void preBundle(U configuration) { + /* + Noop here! Let the subclasses override if there are any. Not a mandatory check everywhere. Http doesn't need it, only dataStore builders will need them. + Need not be abstract! + */ + } + + /* + Letting the subclasses override should they have to again. The default is set to false always. Need not be abstract, not a mandatory parameter. + */ + @SuppressWarnings("unused") + protected boolean withInitialRotationStatus(U configuration) { + return true; + } + + /* + Not a mandatory parameter (for example, needed for zk, not for http! + Letting the subclasses override should they have to, need not be abstract. Avoids boilerplate code everywhere, the default impl! + */ + @SuppressWarnings("unused") + protected List> withLifecycleSignals(U configuration) { + return List.of(); + } + + protected abstract List> withHubs(U configuration); + + protected abstract List withHealthChecks(U configuration); + + @Override + public void initialize(Bootstrap bootstrap) { + /* + Nothing to init here! + */ + } + + + @Override + public void run(U configuration, Environment environment) { + preBundle(configuration); + + mapper = environment.getObjectMapper(); + hubs = withHubs(configuration); + + val rotationStatus = new RotationStatus(withInitialRotationStatus(configuration)); + val lifecycleSignals = withLifecycleSignals(configuration); + val healthChecks = withHealthChecks(configuration); + + environment.admin() + .addTask(new OorTask(rotationStatus)); + environment.admin() + .addTask(new BirTask(rotationStatus)); + + environment.lifecycle().manage(new Managed() { + @Override + public void start() { + log.info("Starting the server manager"); + lifecycleSignals.forEach(Signal::start); + hubs.forEach(RangerHubClient::start); + log.info("Started the server manager"); + } + + @Override + public void stop() { + log.info("Stopping the server manager"); + hubs.forEach(RangerHubClient::stop); + lifecycleSignals.forEach(Signal::stop); + log.info("Stopped the server manager"); + } + }); + /* + The reason why health checks are bound separately instead of a single checker is would like to see what was the exact health check that failed, + during debug if any client intends to. Combining into one, that would be lost, at best only the first failed check will be seen. + */ + environment.healthChecks().register("rotation-check", new RotationCheck(rotationStatus)); + healthChecks.forEach(healthCheck -> environment.healthChecks().register(healthCheck.getClass().getName(), healthCheck)); + environment.jersey().register(new RangerResource<>(hubs)); + } +} diff --git a/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/resources/RangerResource.java b/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/resources/RangerResource.java new file mode 100644 index 00000000..ea67504f --- /dev/null +++ b/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/resources/RangerResource.java @@ -0,0 +1,93 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.server.bundle.resources; + +import com.codahale.metrics.annotation.Timed; +import io.appform.ranger.client.RangerHubClient; +import io.appform.ranger.core.model.Service; +import io.appform.ranger.core.model.ServiceNode; +import io.appform.ranger.core.model.ServiceRegistry; +import io.appform.ranger.http.response.model.GenericResponse; +import jakarta.inject.Inject; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DefaultValue; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; +import lombok.extern.slf4j.Slf4j; +import lombok.val; + +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Slf4j +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Path("/ranger") +public class RangerResource> { + + private final List> rangerHubs; + + @Inject + public RangerResource(List> rangerHubs) { + this.rangerHubs = rangerHubs; + } + + @GET + @Path("/services/v1") + @Timed + public GenericResponse> getServices( + @QueryParam("skipDataFromReplicationSources") @DefaultValue("false") boolean skipDataFromReplicationSources) { + return GenericResponse.>builder() + .data(rangerHubs.stream() + .filter(hub -> !skipDataFromReplicationSources || !hub.isReplicationSource()) + .map(RangerHubClient::getRegisteredServices) + .flatMap(Collection::stream) + .collect(Collectors.toSet())) + .build(); + } + + @GET + @Path("/nodes/v1/{namespace}/{serviceName}") + @Timed + public GenericResponse>> getNodes( + @NotNull @NotEmpty @PathParam("namespace") final String namespace, + @NotNull @NotEmpty @PathParam("serviceName") final String serviceName, + @QueryParam("skipDataFromReplicationSources") @DefaultValue("false") boolean skipDataFromReplicationSources) { + val service = Service.builder().namespace(namespace).serviceName(serviceName).build(); + return GenericResponse.>>builder() + .data(rangerHubs.stream() + .filter(hub -> !(skipDataFromReplicationSources && hub.isReplicationSource())) + .map(hub -> hub.getAllNodes(service)) + .flatMap(List::stream) + .collect(Collectors.toMap(node -> node.getHost() + ":" + node.getPort(), + Function.identity(), + (oldV, newV) -> + oldV.getLastUpdatedTimeStamp() > newV.getLastUpdatedTimeStamp() + ? oldV + : newV)) + .values()) + .build(); + } +} diff --git a/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/rotation/BirTask.java b/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/rotation/BirTask.java new file mode 100644 index 00000000..05ae35b4 --- /dev/null +++ b/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/rotation/BirTask.java @@ -0,0 +1,40 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.server.bundle.rotation; + +import io.dropwizard.servlets.tasks.Task; +import lombok.extern.slf4j.Slf4j; + +import java.io.PrintWriter; +import java.util.List; +import java.util.Map; + +@Slf4j +public class BirTask extends Task { + + private final RotationStatus rotationStatus; + + public BirTask(RotationStatus rotationStatus) { + super("ranger-bir"); + this.rotationStatus = rotationStatus; + } + + @Override + public void execute(Map> map, PrintWriter printWriter) { + rotationStatus.bir(); + log.info("Taking node back into rotation on ranger"); + } +} diff --git a/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/rotation/OorTask.java b/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/rotation/OorTask.java new file mode 100644 index 00000000..136b048d --- /dev/null +++ b/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/rotation/OorTask.java @@ -0,0 +1,40 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.server.bundle.rotation; + +import io.dropwizard.servlets.tasks.Task; +import lombok.extern.slf4j.Slf4j; + +import java.io.PrintWriter; +import java.util.List; +import java.util.Map; + +@Slf4j +public class OorTask extends Task { + + private final RotationStatus rotationStatus; + + public OorTask(RotationStatus rotationStatus) { + super("ranger-oor"); + this.rotationStatus = rotationStatus; + } + + @Override + public void execute(Map> map, PrintWriter printWriter) { + rotationStatus.oor(); + log.info("Taking node out of rotation on ranger"); + } +} diff --git a/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/rotation/RotationCheck.java b/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/rotation/RotationCheck.java new file mode 100644 index 00000000..71f79171 --- /dev/null +++ b/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/rotation/RotationCheck.java @@ -0,0 +1,32 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.server.bundle.rotation; + +import com.codahale.metrics.health.HealthCheck; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class RotationCheck extends HealthCheck { + + private final RotationStatus rotationStatus; + + @Override + protected Result check() { + return null != rotationStatus && rotationStatus.status() ? Result.healthy("Service is rotation") : + Result.unhealthy("Service is OOR"); + } +} diff --git a/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/rotation/RotationStatus.java b/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/rotation/RotationStatus.java new file mode 100644 index 00000000..5d700283 --- /dev/null +++ b/ranger-server-bundle-dw5/src/main/java/io/appform/ranger/server/bundle/rotation/RotationStatus.java @@ -0,0 +1,39 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.server.bundle.rotation; + +import java.util.concurrent.atomic.AtomicBoolean; + +@SuppressWarnings("unused") +public class RotationStatus { + private final AtomicBoolean status; + + public RotationStatus(boolean initialStatus) { + status = new AtomicBoolean(initialStatus); + } + + public void oor() { + status.set(false); + } + + public void bir() { + status.set(true); + } + + public boolean status() { + return status.get(); + } +} diff --git a/ranger-server-bundle-dw5/src/test/java/io/appform/ranger/server/bundle/RangerServerBundleTest.java b/ranger-server-bundle-dw5/src/test/java/io/appform/ranger/server/bundle/RangerServerBundleTest.java new file mode 100644 index 00000000..857edbe4 --- /dev/null +++ b/ranger-server-bundle-dw5/src/test/java/io/appform/ranger/server/bundle/RangerServerBundleTest.java @@ -0,0 +1,120 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.appform.ranger.server.bundle; + +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.health.HealthCheck; +import com.codahale.metrics.health.HealthCheckRegistry; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.appform.ranger.client.RangerHubClient; +import io.appform.ranger.client.stubs.RangerTestHub; +import io.appform.ranger.client.utils.RangerHubTestUtils; +import io.appform.ranger.core.finder.serviceregistry.ListBasedServiceRegistry; +import io.appform.ranger.core.units.TestNodeData; +import io.appform.ranger.core.utils.RangerTestUtils; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.setup.AdminEnvironment; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.jersey.DropwizardResourceConfig; +import io.dropwizard.jersey.setup.JerseyEnvironment; +import io.dropwizard.lifecycle.setup.LifecycleEnvironment; +import lombok.val; +import org.eclipse.jetty.util.component.LifeCycle; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; + +import static io.appform.ranger.client.utils.RangerHubTestUtils.service; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class RangerServerBundleTest { + + private static final JerseyEnvironment JERSEY_ENVIRONMENT = mock(JerseyEnvironment.class); + private static final MetricRegistry METRIC_REGISTRY = mock(MetricRegistry.class); + private static final LifecycleEnvironment LIFECYCLE_ENVIRONMENT = new LifecycleEnvironment(METRIC_REGISTRY); + private static final Environment ENVIRONMENT = mock(Environment.class); + private static final Bootstrap BOOTSTRAP = mock(Bootstrap.class); + private static final Configuration CONFIGURATION = mock(Configuration.class); + + private static final RangerServerBundle, Configuration> + RANGER_SERVER_BUNDLE = new RangerServerBundle<>() { + + @Override + protected List>> withHubs(Configuration configuration) { + return Collections.singletonList(RangerHubTestUtils.getTestHub()); + } + + @Override + protected List withHealthChecks(Configuration configuration) { + return Collections.emptyList(); + } + }; + + @BeforeAll + static void setup() throws Exception { + when(JERSEY_ENVIRONMENT.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); + when(ENVIRONMENT.jersey()).thenReturn(JERSEY_ENVIRONMENT); + when(ENVIRONMENT.lifecycle()).thenReturn(LIFECYCLE_ENVIRONMENT); + when(ENVIRONMENT.getObjectMapper()).thenReturn(new ObjectMapper()); + val adminEnvironment = mock(AdminEnvironment.class); + doNothing().when(adminEnvironment).addTask(any()); + when(ENVIRONMENT.admin()).thenReturn(adminEnvironment); + + val healthCheckRegistry = mock(HealthCheckRegistry.class); + doNothing().when(healthCheckRegistry).register(anyString(), any()); + when(ENVIRONMENT.healthChecks()).thenReturn(healthCheckRegistry); + + RANGER_SERVER_BUNDLE.initialize(BOOTSTRAP); + RANGER_SERVER_BUNDLE.run(CONFIGURATION, ENVIRONMENT); + for (val lifeCycle : LIFECYCLE_ENVIRONMENT.getManagedObjects()) { + lifeCycle.start(); + } + } + + + @Test + void testRangerBundle() { + var hub = RANGER_SERVER_BUNDLE.getHubs().get(0); + assertInstanceOf(RangerTestHub.class, hub); + var node = hub.getNode(service).orElse(null); + Assertions.assertNotNull(node); + assertTrue(node.getHost().equalsIgnoreCase("localhost")); + Assertions.assertEquals(9200, node.getPort()); + Assertions.assertEquals(1, node.getNodeData().getShardId()); + Assertions.assertNull(hub.getNode(RangerTestUtils.getService("test", "test")).orElse(null)); + Assertions.assertNull(hub.getNode(service, nodeData -> nodeData.getShardId() == 2).orElse(null)); + Assertions.assertNull(hub.getNode(RangerTestUtils.getService("test", "test"), + nodeData -> nodeData.getShardId() == 1).orElse(null)); + } + + @AfterAll + static void tearDown() throws Exception { + for (LifeCycle lifeCycle : LIFECYCLE_ENVIRONMENT.getManagedObjects()) { + lifeCycle.stop(); + } + } +} diff --git a/ranger-server-bundle/README.md b/ranger-server-bundle/README.md index eae598f5..47a17439 100644 --- a/ranger-server-bundle/README.md +++ b/ranger-server-bundle/README.md @@ -1,13 +1,14 @@ # Ranger Server Bundle -Ranger server bundle is a common dropwizard bundle atop which we could implement any http based ranger backend. +Ranger server bundle is a common dropwizard bundle atop which we could implement any http based ranger backend. + - Provides the core interface atop which any ranger http backend could be built. -- Provides type-safe generic interface for integration with the above. -- A really easy plug and play system to get started. -- Abstracts out ranger's finder hub's complexity. +- Provides type-safe generic interface for integration with the above. +- A really easy plug and play system to get started. +- Abstracts out ranger's finder hub's complexity. - Written atop the wonderful. [Dropwizard](http://dropwizard.io/) -#### Using a server bundle to initialize a ZK backend. +#### Using a server bundle to initialize a ZK backend. ``` val rangerServerBundle = new RangerServerBundle, ZkNodeDataDeserializer, @@ -57,7 +58,7 @@ Ranger server bundle is a common dropwizard bundle atop which we could implement rangerServerBundle.start(); ``` -Stop the bundle once you are done with it. +Stop the bundle once you are done with it. ``` rangerServerBundle.stop(); diff --git a/ranger-server-bundle/pom.xml b/ranger-server-bundle/pom.xml index 06b791f8..806fc110 100644 --- a/ranger-server-bundle/pom.xml +++ b/ranger-server-bundle/pom.xml @@ -28,6 +28,10 @@ ranger-server-bundle Dropwizard Server Bundle for Ranger + + 2.1.12 + + io.appform.ranger @@ -42,6 +46,13 @@ io.dropwizard dropwizard-core + ${dropwizard.version} + provided + + + io.dropwizard + dropwizard-jackson + ${dropwizard.version} provided diff --git a/ranger-server-bundle/src/main/java/io/appform/ranger/server/bundle/RangerServerBundle.java b/ranger-server-bundle/src/main/java/io/appform/ranger/server/bundle/RangerServerBundle.java index 59b2e451..c46cd918 100644 --- a/ranger-server-bundle/src/main/java/io/appform/ranger/server/bundle/RangerServerBundle.java +++ b/ranger-server-bundle/src/main/java/io/appform/ranger/server/bundle/RangerServerBundle.java @@ -41,7 +41,7 @@ public abstract class RangerServerBundle< T, R extends ServiceRegistry, - U extends Configuration> implements ConfiguredBundle{ + U extends Configuration> implements ConfiguredBundle { /* Why are we taking a list of hubs, instead of one? To be able to aggregate from different dataSources if need be @@ -54,7 +54,7 @@ public abstract class RangerServerBundle< private List> hubs; private ObjectMapper mapper; - protected void preBundle(U configuration){ + protected void preBundle(U configuration) { /* Noop here! Let the subclasses override if there are any. Not a mandatory check everywhere. Http doesn't need it, only dataStore builders will need them. Need not be abstract! @@ -65,7 +65,7 @@ protected void preBundle(U configuration){ Letting the subclasses override should they have to again. The default is set to false always. Need not be abstract, not a mandatory parameter. */ @SuppressWarnings("unused") - protected boolean withInitialRotationStatus(U configuration){ + protected boolean withInitialRotationStatus(U configuration) { return true; } @@ -74,7 +74,7 @@ Not a mandatory parameter (for example, needed for zk, not for http! Letting the subclasses override should they have to, need not be abstract. Avoids boilerplate code everywhere, the default impl! */ @SuppressWarnings("unused") - protected List> withLifecycleSignals(U configuration){ + protected List> withLifecycleSignals(U configuration) { return List.of(); } diff --git a/ranger-server-bundle/src/main/java/io/appform/ranger/server/bundle/resources/RangerResource.java b/ranger-server-bundle/src/main/java/io/appform/ranger/server/bundle/resources/RangerResource.java index d30e72da..b8988eab 100644 --- a/ranger-server-bundle/src/main/java/io/appform/ranger/server/bundle/resources/RangerResource.java +++ b/ranger-server-bundle/src/main/java/io/appform/ranger/server/bundle/resources/RangerResource.java @@ -27,7 +27,13 @@ import javax.inject.Inject; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -import javax.ws.rs.*; +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import java.util.Collection; import java.util.List; @@ -55,10 +61,10 @@ public GenericResponse> getServices( @QueryParam("skipDataFromReplicationSources") @DefaultValue("false") boolean skipDataFromReplicationSources) { return GenericResponse.>builder() .data(rangerHubs.stream() - .filter(hub -> !skipDataFromReplicationSources || !hub.isReplicationSource()) - .map(RangerHubClient::getRegisteredServices) - .flatMap(Collection::stream) - .collect(Collectors.toSet())) + .filter(hub -> !skipDataFromReplicationSources || !hub.isReplicationSource()) + .map(RangerHubClient::getRegisteredServices) + .flatMap(Collection::stream) + .collect(Collectors.toSet())) .build(); } @@ -72,16 +78,16 @@ public GenericResponse>> getNodes( val service = Service.builder().namespace(namespace).serviceName(serviceName).build(); return GenericResponse.>>builder() .data(rangerHubs.stream() - .filter(hub -> !(skipDataFromReplicationSources && hub.isReplicationSource())) - .map(hub -> hub.getAllNodes(service)) - .flatMap(List::stream) - .collect(Collectors.toMap(node -> node.getHost() + ":" + node.getPort(), - Function.identity(), - (oldV, newV) -> - oldV.getLastUpdatedTimeStamp() > newV.getLastUpdatedTimeStamp() - ? oldV - : newV)) - .values()) + .filter(hub -> !(skipDataFromReplicationSources && hub.isReplicationSource())) + .map(hub -> hub.getAllNodes(service)) + .flatMap(List::stream) + .collect(Collectors.toMap(node -> node.getHost() + ":" + node.getPort(), + Function.identity(), + (oldV, newV) -> + oldV.getLastUpdatedTimeStamp() > newV.getLastUpdatedTimeStamp() + ? oldV + : newV)) + .values()) .build(); } } diff --git a/ranger-server-bundle/src/test/java/io/appform/ranger/server/bundle/RangerServerBundleTest.java b/ranger-server-bundle/src/test/java/io/appform/ranger/server/bundle/RangerServerBundleTest.java index afae5220..f37cd8c1 100644 --- a/ranger-server-bundle/src/test/java/io/appform/ranger/server/bundle/RangerServerBundleTest.java +++ b/ranger-server-bundle/src/test/java/io/appform/ranger/server/bundle/RangerServerBundleTest.java @@ -34,16 +34,24 @@ import io.dropwizard.setup.Environment; import lombok.val; import org.eclipse.jetty.util.component.LifeCycle; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import java.util.Collections; import java.util.List; import static io.appform.ranger.client.utils.RangerHubTestUtils.service; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; -public class RangerServerBundleTest { +class RangerServerBundleTest { private static final JerseyEnvironment JERSEY_ENVIRONMENT = mock(JerseyEnvironment.class); private static final MetricRegistry METRIC_REGISTRY = mock(MetricRegistry.class); @@ -67,7 +75,7 @@ protected List withHealthChecks(Configuration configuration) { }; @BeforeAll - public static void setup() throws Exception { + static void setup() throws Exception { when(JERSEY_ENVIRONMENT.getResourceConfig()).thenReturn(new DropwizardResourceConfig()); when(ENVIRONMENT.jersey()).thenReturn(JERSEY_ENVIRONMENT); when(ENVIRONMENT.lifecycle()).thenReturn(LIFECYCLE_ENVIRONMENT); @@ -91,20 +99,20 @@ public static void setup() throws Exception { @Test void testRangerBundle() { var hub = RANGER_SERVER_BUNDLE.getHubs().get(0); - Assertions.assertTrue(hub instanceof RangerTestHub); + assertInstanceOf(RangerTestHub.class, hub); var node = hub.getNode(service).orElse(null); Assertions.assertNotNull(node); - Assertions.assertTrue(node.getHost().equalsIgnoreCase("localhost")); + assertTrue(node.getHost().equalsIgnoreCase("localhost")); Assertions.assertEquals(9200, node.getPort()); Assertions.assertEquals(1, node.getNodeData().getShardId()); Assertions.assertNull(hub.getNode(RangerTestUtils.getService("test", "test")).orElse(null)); Assertions.assertNull(hub.getNode(service, nodeData -> nodeData.getShardId() == 2).orElse(null)); Assertions.assertNull(hub.getNode(RangerTestUtils.getService("test", "test"), - nodeData -> nodeData.getShardId() == 1).orElse(null)); + nodeData -> nodeData.getShardId() == 1).orElse(null)); } @AfterAll - public static void tearDown() throws Exception { + static void tearDown() throws Exception { for (LifeCycle lifeCycle : LIFECYCLE_ENVIRONMENT.getManagedObjects()) { lifeCycle.stop(); } diff --git a/ranger-server-common/pom.xml b/ranger-server-common/pom.xml index 5d4d419a..d65fcc89 100644 --- a/ranger-server-common/pom.xml +++ b/ranger-server-common/pom.xml @@ -27,5 +27,4 @@ ranger-server-common Common libraries for Ranger - diff --git a/ranger-server-common/src/test/java/io/appform/ranger/common/server/ShardInfoTest.java b/ranger-server-common/src/test/java/io/appform/ranger/common/server/ShardInfoTest.java index 9e5f054c..b25bdc53 100644 --- a/ranger-server-common/src/test/java/io/appform/ranger/common/server/ShardInfoTest.java +++ b/ranger-server-common/src/test/java/io/appform/ranger/common/server/ShardInfoTest.java @@ -28,12 +28,12 @@ import java.util.stream.Collectors; -public class ShardInfoTest { +class ShardInfoTest { private static final ObjectMapper mapper = new ObjectMapper(); private String getResource(String path) { val data = ShardInfoTest.class.getClassLoader().getResourceAsStream(path); - if(null == data) return null; + if (null == data) return null; return new BufferedReader( new InputStreamReader(data)) .lines() @@ -42,14 +42,14 @@ private String getResource(String path) { @SneakyThrows @SuppressWarnings("SameParameterValue") - private T getResource(String path, Class klass) { + private T getResource(String path, Class klass) { val data = getResource(path); - if(null == data) return null; + if (null == data) return null; return mapper.readValue(data, klass); } @Test - public void testShardInfo(){ + void testShardInfo() { val shardInfo1 = getResource("fixtures/env1.json", ShardInfo.class); val shardInfo2 = getResource("fixtures/env2.json", ShardInfo.class); Assertions.assertNotNull(shardInfo1); diff --git a/ranger-server-common/src/test/resources/fixtures/env1.json b/ranger-server-common/src/test/resources/fixtures/env1.json index 1a5445d9..34b8f18a 100644 --- a/ranger-server-common/src/test/resources/fixtures/env1.json +++ b/ranger-server-common/src/test/resources/fixtures/env1.json @@ -1,4 +1,4 @@ { - "environment" : "e", - "region" : "r" + "environment": "e", + "region": "r" } \ No newline at end of file diff --git a/ranger-server-common/src/test/resources/fixtures/env2.json b/ranger-server-common/src/test/resources/fixtures/env2.json index ccf047f1..2c656bde 100644 --- a/ranger-server-common/src/test/resources/fixtures/env2.json +++ b/ranger-server-common/src/test/resources/fixtures/env2.json @@ -1,4 +1,6 @@ { - "environment" : "e", - "tags" : ["tag1"] + "environment": "e", + "tags": [ + "tag1" + ] } \ No newline at end of file diff --git a/ranger-server-dw5/pom.xml b/ranger-server-dw5/pom.xml new file mode 100644 index 00000000..7201bb27 --- /dev/null +++ b/ranger-server-dw5/pom.xml @@ -0,0 +1,113 @@ + + + + + 4.0.0 + + io.appform.ranger + ranger + 2.0.0-SNAPSHOT + + + ranger-server-dw5 + Ranger HTTP Server on Dropwizard 5.x + + + 2.0.1 + 8.0.0-rc.5 + 5.0.0 + 1.19.0 + 3.6.1 + + + + + + io.dropwizard + dropwizard-bom + ${dropwizard.version} + pom + import + + + + + + + io.appform.ranger + ranger-hub-server-bundle-dw5 + ${project.version} + + + io.dropwizard + dropwizard-core + + + jakarta.inject + jakarta.inject-api + ${jakarta.inject-api.version} + + + ru.vyarus + dropwizard-guicey + ${dw-guicey.version} + + + + + + + org.apache.maven.plugins + maven-shade-plugin + ${maven-shade-plugin.version} + + false + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + package + + shade + + + + + + io.appform.ranger.server.App + + + + + + + + + diff --git a/ranger-server-dw5/src/main/java/io/appform/ranger/server/App.java b/ranger-server-dw5/src/main/java/io/appform/ranger/server/App.java new file mode 100644 index 00000000..8a61bb28 --- /dev/null +++ b/ranger-server-dw5/src/main/java/io/appform/ranger/server/App.java @@ -0,0 +1,62 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.server; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; +import io.appform.ranger.hub.server.bundle.RangerHubServerBundle; +import io.appform.ranger.hub.server.bundle.configuration.RangerServerConfiguration; +import io.dropwizard.core.Application; +import io.dropwizard.core.setup.Bootstrap; +import io.dropwizard.core.setup.Environment; +import lombok.SneakyThrows; +import lombok.val; + +/** + * + */ +public class App extends Application { + + @Override + public void initialize(Bootstrap bootstrap) { + bootstrap.addBundle(new RangerHubServerBundle() { + @Override + protected RangerServerConfiguration getRangerConfiguration(AppConfig configuration) { + return configuration.getRanger(); + } + }); + } + + @Override + public void run(AppConfig appConfig, Environment environment) { + val objectMapper = environment.getObjectMapper(); + objectMapper.registerModule(new ParameterNamesModule()); + objectMapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY); + objectMapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL); + objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + objectMapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS); + } + + @SneakyThrows + public static void main(String[] args) { + new App().run(args); + } +} diff --git a/ranger-server-dw5/src/main/java/io/appform/ranger/server/AppConfig.java b/ranger-server-dw5/src/main/java/io/appform/ranger/server/AppConfig.java new file mode 100644 index 00000000..be66a047 --- /dev/null +++ b/ranger-server-dw5/src/main/java/io/appform/ranger/server/AppConfig.java @@ -0,0 +1,38 @@ +/* + * Copyright 2024 Authors, Flipkart Internet Pvt. Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.appform.ranger.server; + +import io.appform.ranger.hub.server.bundle.configuration.RangerServerConfiguration; +import io.dropwizard.core.Configuration; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + + +/** + * + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AppConfig extends Configuration { + @NotNull + @Valid + RangerServerConfiguration ranger; +} diff --git a/ranger-server-dw5/src/main/resources/local.yml b/ranger-server-dw5/src/main/resources/local.yml new file mode 100644 index 00000000..8e0c6012 --- /dev/null +++ b/ranger-server-dw5/src/main/resources/local.yml @@ -0,0 +1,41 @@ +ranger: + namespace: mynamespace + upstreams: + - type: HTTP + nodeRefreshTimeMs: 5000 + serviceRefreshTimeoutMs: 300000 + hubStartTimeoutMs: 210000 + httpClientConfigs: + - host: localhost + port: 80 + - type: ZK + nodeRefreshTimeMs: 5000 + serviceRefreshTimeoutMs: 3000 + hubStartTimeoutMs: 5000 + zookeepers: [ "localhost:2181" ] + disablePushUpdaters: true + + +server: + maxThreads: 1024 + minThreads: 1024 + applicationConnectors: + - type: http + port: 18080 + adminConnectors: + - type: http + port: 18081 + applicationContextPath: / + requestLog: + appenders: + - type: console + timeZone: IST + +logging: + level: INFO + + appenders: + - type: console + threshold: INFO + timeZone: IST + logFormat: "%(%-5level) [%date] [%thread] [%logger{0}]: %message%n" diff --git a/ranger-server/pom.xml b/ranger-server/pom.xml index 2196b30e..d07ef9f0 100644 --- a/ranger-server/pom.xml +++ b/ranger-server/pom.xml @@ -31,8 +31,20 @@ 2.0.1 5.10.2 + 2.1.12 + 1.19.0 + 3.6.1 + + + + commons-codec + commons-codec + ${commons-codec.version} + + + io.appform.ranger @@ -42,6 +54,7 @@ io.dropwizard dropwizard-core + ${dropwizard.version} jakarta.inject @@ -60,7 +73,7 @@ org.apache.maven.plugins maven-shade-plugin - 2.4.3 + ${maven-shade-plugin.version} false @@ -82,8 +95,10 @@ - - + + io.appform.ranger.server.App diff --git a/ranger-server/src/main/java/io/appform/ranger/server/App.java b/ranger-server/src/main/java/io/appform/ranger/server/App.java index 31e074ff..60fcdac8 100644 --- a/ranger-server/src/main/java/io/appform/ranger/server/App.java +++ b/ranger-server/src/main/java/io/appform/ranger/server/App.java @@ -45,11 +45,11 @@ protected RangerServerConfiguration getRangerConfiguration(AppConfig configurati } @Override - public void run(AppConfig appConfig, Environment environment) throws Exception { + public void run(AppConfig appConfig, Environment environment) { val objectMapper = environment.getObjectMapper(); objectMapper.registerModule(new ParameterNamesModule()); - objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); - objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY); + objectMapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL); objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); objectMapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS); diff --git a/ranger-zk-client/pom.xml b/ranger-zk-client/pom.xml index 76f51ce2..96c0b586 100644 --- a/ranger-zk-client/pom.xml +++ b/ranger-zk-client/pom.xml @@ -44,13 +44,6 @@ curator-test ${curator.version} test - - - log4j - log4j - - - diff --git a/ranger-zk-client/src/main/java/io/appform/ranger/client/zk/SimpleRangerZKClient.java b/ranger-zk-client/src/main/java/io/appform/ranger/client/zk/SimpleRangerZKClient.java index 4a3d865b..511d1056 100644 --- a/ranger-zk-client/src/main/java/io/appform/ranger/client/zk/SimpleRangerZKClient.java +++ b/ranger-zk-client/src/main/java/io/appform/ranger/client/zk/SimpleRangerZKClient.java @@ -63,7 +63,7 @@ public void start() { if (effectiveRefreshTime < HubConstants.MINIMUM_REFRESH_TIME_MS) { effectiveRefreshTime = HubConstants.MINIMUM_REFRESH_TIME_MS; log.warn("Node info update interval too low: {} ms. Has been upgraded to {} ms ", - nodeRefreshIntervalMs, + nodeRefreshIntervalMs, HubConstants.MINIMUM_REFRESH_TIME_MS); } diff --git a/ranger-zk-client/src/main/java/io/appform/ranger/client/zk/UnshardedRangerZKHubClient.java b/ranger-zk-client/src/main/java/io/appform/ranger/client/zk/UnshardedRangerZKHubClient.java index 2b3eea83..19e879e8 100644 --- a/ranger-zk-client/src/main/java/io/appform/ranger/client/zk/UnshardedRangerZKHubClient.java +++ b/ranger-zk-client/src/main/java/io/appform/ranger/client/zk/UnshardedRangerZKHubClient.java @@ -41,14 +41,14 @@ public class UnshardedRangerZKHubClient @Override protected ServiceFinderFactory> getFinderFactory() { return ZKUnshardedServiceFinderFactory.builder() - .curatorFramework(getCuratorFramework()) - .connectionString(getConnectionString()) - .nodeRefreshIntervalMs(getNodeRefreshTimeMs()) - .disablePushUpdaters(isDisablePushUpdaters()) - .deserializer(getDeserializer()) - .shardSelector(shardSelector) - .nodeSelector(nodeSelector) - .build(); + .curatorFramework(getCuratorFramework()) + .connectionString(getConnectionString()) + .nodeRefreshIntervalMs(getNodeRefreshTimeMs()) + .disablePushUpdaters(isDisablePushUpdaters()) + .deserializer(getDeserializer()) + .shardSelector(shardSelector) + .nodeSelector(nodeSelector) + .build(); } } diff --git a/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/BaseRangerZKClientTest.java b/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/BaseRangerZKClientTest.java index 0ef7e484..f1024c62 100644 --- a/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/BaseRangerZKClientTest.java +++ b/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/BaseRangerZKClientTest.java @@ -34,7 +34,6 @@ import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.curator.test.TestingCluster; import org.junit.jupiter.api.AfterEach; - import org.junit.jupiter.api.BeforeEach; import java.io.IOException; @@ -62,7 +61,7 @@ public void startTestCluster() throws Exception { .build(); curatorFramework.start(); curatorFramework.blockUntilConnected(); - initilizeProvider(); + initializeProvider(); log.debug("Started zk subsystem"); } @@ -73,16 +72,16 @@ public void stopTestCluster() throws Exception { if (null != testingCluster) { testingCluster.close(); } - if(null != provider){ + if (null != provider) { provider.stop(); } } protected ServiceNode read(final byte[] data) { try { - return getObjectMapper().readValue(data, new TypeReference>() {}); - } - catch (IOException e) { + return getObjectMapper().readValue(data, new TypeReference>() { + }); + } catch (IOException e) { Exceptions.illegalState(e); } return null; @@ -91,14 +90,13 @@ protected ServiceNode read(final byte[] data) { protected byte[] write(final ServiceNode node) { try { return getObjectMapper().writeValueAsBytes(node); - } - catch (IOException e) { + } catch (IOException e) { Exceptions.illegalState(e); } return null; } - protected void initilizeProvider(){ + protected void initializeProvider() { val refreshProviderSignal = new ExternalTriggeredSignal<>( () -> HealthcheckResult.builder() .status(HealthcheckStatus.healthy) diff --git a/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/ShardedZKRangerClientTest.java b/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/ShardedZKRangerClientTest.java index 48278988..37507bb6 100644 --- a/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/ShardedZKRangerClientTest.java +++ b/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/ShardedZKRangerClientTest.java @@ -26,7 +26,7 @@ class ShardedZKRangerClientTest extends BaseRangerZKClientTest { @Test - void testShardedHub(){ + void testShardedHub() { val zkHubClient = ShardedRangerZKHubClient.builder() .namespace("test-n") .connectionString(getTestingCluster().getConnectString()) diff --git a/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/SimpleRangerZKClientTest.java b/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/SimpleRangerZKClientTest.java index c0603c50..a7616cda 100644 --- a/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/SimpleRangerZKClientTest.java +++ b/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/SimpleRangerZKClientTest.java @@ -23,8 +23,8 @@ class SimpleRangerZKClientTest extends BaseRangerZKClientTest { @Test - void testBaseClient(){ - val client = SimpleRangerZKClient.builder() + void testBaseClient() { + val client = SimpleRangerZKClient.builder() .curatorFramework(getCuratorFramework()) .deserializer(this::read) .namespace("test-n") @@ -33,7 +33,7 @@ void testBaseClient(){ .mapper(getObjectMapper()) .build(); client.start(); - Assertions.assertNotNull( client.getNode().orElse(null)); + Assertions.assertNotNull(client.getNode().orElse(null)); Assertions.assertNotNull(client.getNode(c -> c.getShardId() == 1).orElse(null)); Assertions.assertNull(client.getNode(c -> c.getShardId() == 2).orElse(null)); } diff --git a/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/UnshardedZKRangerClientTest.java b/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/UnshardedZKRangerClientTest.java index a7a479c0..1daf31a7 100644 --- a/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/UnshardedZKRangerClientTest.java +++ b/ranger-zk-client/src/test/java/io/appform/ranger/client/zk/UnshardedZKRangerClientTest.java @@ -26,8 +26,8 @@ class UnshardedZKRangerClientTest extends BaseRangerZKClientTest { @Test - void testShardedHub(){ - val zkHubClient =UnshardedRangerZKHubClient.builder() + void testShardedHub() { + val zkHubClient = UnshardedRangerZKHubClient.builder() .namespace("test-n") .connectionString(getTestingCluster().getConnectString()) .curatorFramework(getCuratorFramework()) diff --git a/ranger-zookeeper/pom.xml b/ranger-zookeeper/pom.xml index bcf9e57f..0b11c70a 100644 --- a/ranger-zookeeper/pom.xml +++ b/ranger-zookeeper/pom.xml @@ -26,7 +26,7 @@ 4.0.0 ranger-zookeeper - Zookeeper based dicovery for Ranger + Zookeeper based discovery for Ranger @@ -39,12 +39,6 @@ org.apache.curator curator-framework ${curator.version} - - - log4j - log4j - - org.apache.curator @@ -56,12 +50,6 @@ curator-test ${curator.version} test - - - log4j - log4j - - io.appform.ranger @@ -70,5 +58,4 @@ test-jar - diff --git a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/ServiceFinderBuilders.java b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/ServiceFinderBuilders.java index 536dc617..464348e5 100644 --- a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/ServiceFinderBuilders.java +++ b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/ServiceFinderBuilders.java @@ -21,7 +21,7 @@ @UtilityClass public class ServiceFinderBuilders { - + public static ZkSimpleShardedServiceFinderBuilder shardedFinderBuilder() { return new ZkSimpleShardedServiceFinderBuilder<>(); } diff --git a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/common/ZkNodeDataStoreConnector.java b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/common/ZkNodeDataStoreConnector.java index b07619ca..517b1a9e 100644 --- a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/common/ZkNodeDataStoreConnector.java +++ b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/common/ZkNodeDataStoreConnector.java @@ -15,7 +15,14 @@ */ package io.appform.ranger.zookeeper.common; -import com.github.rholder.retry.*; + +import com.github.rholder.retry.Attempt; +import com.github.rholder.retry.AttemptTimeLimiters; +import com.github.rholder.retry.BlockStrategies; +import com.github.rholder.retry.RetryListener; +import com.github.rholder.retry.Retryer; +import com.github.rholder.retry.RetryerBuilder; +import com.github.rholder.retry.WaitStrategies; import io.appform.ranger.core.model.NodeDataStoreConnector; import io.appform.ranger.core.model.Service; import io.appform.ranger.core.util.Exceptions; @@ -81,7 +88,7 @@ public void start() { if (started.get()) { log.info("Start called on already initialized data source for service {}. Ignoring.", - service.getServiceName()); + service.getServiceName()); return; } val path = PathBuilder.servicePath(service); @@ -92,20 +99,17 @@ public void start() { .create() .creatingParentContainersIfNeeded() .forPath(path); - } - catch (KeeperException e) { + } catch (KeeperException e) { if (e.code() == KeeperException.Code.NODEEXISTS) { log.info("Service node {} already exists for service: {}", path, service.getServiceName()); } - } - catch (InterruptedException e) { + } catch (InterruptedException e) { log.error("Thread interrupted"); Thread.currentThread().interrupt(); Exceptions.illegalState("Could not start ZK data source for service: " - + service.getServiceName() - + " as thread was interrupted"); - } - catch (Exception e) { + + service.getServiceName() + + " as thread was interrupted"); + } catch (Exception e) { Exceptions.illegalState("Could not start ZK data source for service: " + service.getServiceName(), e); } started.set(true); @@ -115,8 +119,7 @@ public void start() { public void ensureConnected() { try { discoveryRetrier.call(this::isActive); - } - catch (Exception e) { + } catch (Exception e) { Exceptions.illegalState("Could not get zk connection", e); } } @@ -131,7 +134,7 @@ public void stop() { log.warn("Shutdown called for service: {}, but data source is not started.", service.getServiceName()); } log.info("Shutting down data source for service: {}. (It's a no-op.)", - service.getServiceName()); + service.getServiceName()); stopped.set(true); } diff --git a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkCommunicationException.java b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkCommunicationException.java index 3de05d85..063109f0 100644 --- a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkCommunicationException.java +++ b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkCommunicationException.java @@ -20,7 +20,6 @@ /** * Thrown in case there is an issue communicating with the Zookeeper upstream. - */ public class ZkCommunicationException extends CommunicationException { public ZkCommunicationException(final String message) { diff --git a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkNodeDataSource.java b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkNodeDataSource.java index 0548e622..ccf7a45e 100644 --- a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkNodeDataSource.java +++ b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkNodeDataSource.java @@ -54,12 +54,12 @@ public Optional>> refresh(D deserializer) { private Optional>> checkForUpdateOnZookeeper(D deserializer) { if (!isStarted()) { log.warn("Data source is not yet started for service: {}. No nodes will be returned.", - service.getServiceName()); + service.getServiceName()); return Optional.empty(); } if (isStopped()) { log.warn("Data source is stopped already for service: {}. No nodes will be returned.", - service.getServiceName()); + service.getServiceName()); return Optional.empty(); } Preconditions.checkNotNull(deserializer, "Deserializer has not been set for node data"); @@ -67,7 +67,7 @@ private Optional>> checkForUpdateOnZookeeper(D deserializer) val serviceName = service.getServiceName(); if (!isActive()) { log.warn("ZK connection is not active. Ignoring refresh request for service: {}", - service.getServiceName()); + service.getServiceName()); return Optional.empty(); } val parentPath = PathBuilder.servicePath(service); @@ -84,14 +84,12 @@ private Optional>> checkForUpdateOnZookeeper(D deserializer) nodes.add(node); } return Optional.of(nodes); - } - catch (NoNodeException e) { + } catch (NoNodeException e) { log.error( "No ZK container node found for service: {}. Will return empty list for now. Please doublecheck service name", service.getServiceName()); return Optional.of(Collections.emptyList()); - } - catch (Exception e) { + } catch (Exception e) { log.error("Error getting node data from zookeeper: ", e); throw new ZkCommunicationException("Error getting node data from zookeeper: exception %s , message: %s" .formatted(e.getClass().getSimpleName(), e.getMessage())); @@ -102,15 +100,13 @@ private Optional readChild(String parentPath, String child) throws Excep final String path = String.format("%s/%s", parentPath, child); try { return Optional.ofNullable(curatorFramework.getData().forPath(path)); - } - catch (KeeperException.NoNodeException e) { + } catch (KeeperException.NoNodeException e) { log.warn("Node not found for path {}", path); return Optional.empty(); - } - catch (KeeperException e) { + } catch (KeeperException e) { log.error("Could not get data for node: {}", path, e); return Optional.empty(); - } catch (Exception e){ + } catch (Exception e) { log.error("Could not read child for node: {}", path, e); throw e; } diff --git a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkSimpleShardedServiceFinderBuilder.java b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkSimpleShardedServiceFinderBuilder.java index c0e418c8..86f6a2f1 100644 --- a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkSimpleShardedServiceFinderBuilder.java +++ b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkSimpleShardedServiceFinderBuilder.java @@ -75,8 +75,7 @@ protected List> implementationSpecificRefreshSignals(final Service ser if (!disablePushUpdaters) { return Collections.singletonList( new ZkWatcherRegistryUpdateSignal<>(service, nodeDataSource, curatorFramework)); - } - else { + } else { log.info("Push based signal updater not registered for service: {}", service.getServiceName()); } return Collections.emptyList(); diff --git a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkSimpleUnshardedServiceFinderBuilder.java b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkSimpleUnshardedServiceFinderBuilder.java index 17a42fa0..50bb309a 100644 --- a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkSimpleUnshardedServiceFinderBuilder.java +++ b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/ZkSimpleUnshardedServiceFinderBuilder.java @@ -79,9 +79,9 @@ protected List> implementationSpecificRefreshSignals( if (!disablePushUpdaters) { return Collections.singletonList( new ZkWatcherRegistryUpdateSignal<>(service, nodeDataSource, curatorFramework)); - } - else { + } else { log.info("Push based signal updater not registered for service: {}", service.getServiceName()); } return Collections.emptyList(); - }} + } +} diff --git a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/signals/ZkWatcherRegistryUpdateSignal.java b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/signals/ZkWatcherRegistryUpdateSignal.java index 0e094ff9..1b840fcd 100644 --- a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/signals/ZkWatcherRegistryUpdateSignal.java +++ b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinder/signals/ZkWatcherRegistryUpdateSignal.java @@ -53,7 +53,7 @@ public ZkWatcherRegistryUpdateSignal( public void start() { dataSource.ensureConnected(); log.info("Node data source is connected, Initializing watchers for service: {}", - service.getServiceName()); + service.getServiceName()); try { curatorFramework.getChildren() .usingWatcher((CuratorWatcher) event -> { diff --git a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinderhub/ZKUnshardedServiceFinderFactory.java b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinderhub/ZKUnshardedServiceFinderFactory.java index 4a470522..340b4af9 100644 --- a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinderhub/ZKUnshardedServiceFinderFactory.java +++ b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinderhub/ZKUnshardedServiceFinderFactory.java @@ -28,7 +28,7 @@ import org.apache.curator.framework.CuratorFramework; -public class ZKUnshardedServiceFinderFactory implements ServiceFinderFactory>{ +public class ZKUnshardedServiceFinderFactory implements ServiceFinderFactory> { private final CuratorFramework curatorFramework; private final String connectionString; diff --git a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinderhub/ZkServiceDataSource.java b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinderhub/ZkServiceDataSource.java index 43dc32de..f95aae50 100644 --- a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinderhub/ZkServiceDataSource.java +++ b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/servicefinderhub/ZkServiceDataSource.java @@ -43,7 +43,7 @@ public class ZkServiceDataSource implements ServiceDataSource { public ZkServiceDataSource(String namespace, String connectionString, - CuratorFramework curatorFramework){ + CuratorFramework curatorFramework) { this.namespace = namespace; this.connectionString = connectionString; this.curatorFramework = curatorFramework; @@ -62,7 +62,7 @@ public Collection services() { @Override public void start() { - if(null == curatorFramework){ + if (null == curatorFramework) { Preconditions.checkNotNull(connectionString); log.info("Building custom curator framework"); curatorFramework = CuratorFrameworkFactory.builder() @@ -75,8 +75,7 @@ public void start() { } try { curatorFramework.blockUntilConnected(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { log.error("Curator block interrupted", e); Thread.currentThread().interrupt(); } @@ -86,7 +85,7 @@ public void start() { @Override public void stop() { log.info("Service data stopped"); - if(!curatorProvided) curatorFramework.close(); + if (!curatorProvided) curatorFramework.close(); log.info("Service data source stopped"); } } diff --git a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/serviceprovider/ZkNodeDataSink.java b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/serviceprovider/ZkNodeDataSink.java index 69e27af1..c4a026aa 100644 --- a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/serviceprovider/ZkNodeDataSink.java +++ b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/serviceprovider/ZkNodeDataSink.java @@ -34,7 +34,7 @@ * */ @Slf4j -public class ZkNodeDataSink> extends ZkNodeDataStoreConnector implements NodeDataSink { +public class ZkNodeDataSink> extends ZkNodeDataStoreConnector implements NodeDataSink { public ZkNodeDataSink( Service service, CuratorFramework curatorFramework) { @@ -45,7 +45,7 @@ public ZkNodeDataSink( public void updateState(S serializer, ServiceNode serviceNode) { if (isStopped()) { log.warn("Node has been stopped already for service: {}. No update will be possible.", - service.getServiceName()); + service.getServiceName()); return; } Preconditions.checkNotNull(serializer, "Serializer has not been set for node data"); @@ -54,12 +54,10 @@ public void updateState(S serializer, ServiceNode serviceNode) { if (null == curatorFramework.checkExists().forPath(path)) { log.info("No node exists for path: {}. Will create now.", path); createPath(serviceNode, serializer); - } - else { + } else { curatorFramework.setData().forPath(path, serializer.serialize(serviceNode)); } - } - catch (Exception e) { + } catch (Exception e) { log.error("Error updating node data at path " + path, e); Exceptions.illegalState(e); } @@ -77,11 +75,9 @@ private synchronized void createPath( .forPath(instancePath, serializer.serialize(serviceNode)); log.info("Created instance path: {}", instancePath); } - } - catch (KeeperException.NodeExistsException e) { + } catch (KeeperException.NodeExistsException e) { log.warn("Node already exists.. Race condition?", e); - } - catch (Exception e) { + } catch (Exception e) { val message = String.format( "Could not create node for %s after 60 retries (1 min). " + "This service will not be discoverable. Retry after some time.", service.getServiceName()); diff --git a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/util/PathBuilder.java b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/util/PathBuilder.java index 73f9f8fe..4423d8b3 100644 --- a/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/util/PathBuilder.java +++ b/ranger-zookeeper/src/main/java/io/appform/ranger/zookeeper/util/PathBuilder.java @@ -23,13 +23,13 @@ @UtilityClass public class PathBuilder { - public static String REGISTERED_SERVICES_PATH = "/"; + public static final String REGISTERED_SERVICES_PATH = "/"; public static String servicePath(final Service service) { return String.format("/%s", service.getServiceName()); } - public static String instancePath(final Service service, final ServiceNode node) { + public static String instancePath(final Service service, final ServiceNode node) { return String.format("/%s/%s", service.getServiceName(), node.representation()); } } diff --git a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/ServiceHealthAggregatorTest.java b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/ServiceHealthAggregatorTest.java index 34358e89..3c35c06f 100644 --- a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/ServiceHealthAggregatorTest.java +++ b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/ServiceHealthAggregatorTest.java @@ -35,7 +35,7 @@ class ServiceHealthAggregatorTest { @SuppressWarnings("unchecked") @BeforeEach - public void setUp() { + void setUp() { testMonitor = new TestMonitor("TestHealthMonitor", TimeEntity.everySecond(), 1000); serviceHealthAggregator.addIsolatedMonitor(testMonitor); serviceHealthAggregator.addInlineMonitor(new Monitor() { @@ -55,7 +55,7 @@ public boolean isDisabled() { } @AfterEach - public void tearDown() { + void tearDown() { serviceHealthAggregator.stop(); } diff --git a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/ServiceProviderIntegrationTest.java b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/ServiceProviderIntegrationTest.java index 7943393d..6f203d4c 100644 --- a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/ServiceProviderIntegrationTest.java +++ b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/ServiceProviderIntegrationTest.java @@ -53,7 +53,7 @@ class ServiceProviderIntegrationTest { SimpleShardedServiceFinder serviceFinder; @BeforeEach - public void startTestCluster() throws Exception { + void startTestCluster() throws Exception { objectMapper = new ObjectMapper(); testingCluster = new TestingCluster(3); testingCluster.start(); @@ -71,7 +71,8 @@ public void startTestCluster() throws Exception { .withServiceName("test-service") .withDeserializer(data -> { try { - return objectMapper.readValue(data, new TypeReference>() {}); + return objectMapper.readValue(data, new TypeReference>() { + }); } catch (IOException e) { Exceptions.illegalState(e); } @@ -83,7 +84,7 @@ public void startTestCluster() throws Exception { } @AfterEach - public void stopTestCluster() throws Exception { + void stopTestCluster() throws Exception { if (null != testingCluster) { testingCluster.close(); } diff --git a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/monitor/sample/PingCheckMonitorTest.java b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/monitor/sample/PingCheckMonitorTest.java index 588334e6..ca7934b0 100644 --- a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/monitor/sample/PingCheckMonitorTest.java +++ b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/monitor/sample/PingCheckMonitorTest.java @@ -19,7 +19,7 @@ import io.appform.ranger.core.healthservice.TimeEntity; import io.appform.ranger.core.healthservice.monitor.sample.PingCheckMonitor; import lombok.val; -import org.apache.http.client.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpGet; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/monitor/sample/RotationStatusMonitorTest.java b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/monitor/sample/RotationStatusMonitorTest.java index c5d01996..3c692987 100644 --- a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/monitor/sample/RotationStatusMonitorTest.java +++ b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/healthservice/monitor/sample/RotationStatusMonitorTest.java @@ -31,12 +31,12 @@ class RotationStatusMonitorTest { File file = new File(filePath); @BeforeEach - public void setUp() throws Exception { + void setUp() throws Exception { deleteRotationFile(); } @AfterEach - public void tearDown() throws Exception { + void tearDown() throws Exception { deleteRotationFile(); } @@ -60,11 +60,10 @@ void testMonitor2() throws Exception { } private void deleteRotationFile() throws Exception { - if (file.exists()) { - if (!file.delete()) { - System.out.println("Unable to delete file = " + filePath); - throw new Exception("Unable to delete file = " + filePath); - } + if (file.exists() && !file.delete()) { + System.out.println("Unable to delete file = " + filePath); + throw new Exception("Unable to delete file = " + filePath); } + } } \ No newline at end of file diff --git a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/CustomShardSelectorTest.java b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/CustomShardSelectorTest.java index c5e27b43..346fc356 100644 --- a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/CustomShardSelectorTest.java +++ b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/CustomShardSelectorTest.java @@ -27,9 +27,11 @@ import io.appform.ranger.zookeeper.ServiceFinderBuilders; import io.appform.ranger.zookeeper.ServiceProviderBuilders; import io.appform.ranger.zookeeper.serde.ZkNodeDataSerializer; -import lombok.*; +import lombok.Builder; +import lombok.Value; import lombok.extern.jackson.Jacksonized; import lombok.extern.slf4j.Slf4j; +import lombok.val; import org.apache.curator.test.TestingCluster; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; @@ -49,7 +51,7 @@ class CustomShardSelectorTest { private final List>> serviceProviders = Lists.newArrayList(); @BeforeEach - public void startTestCluster() throws Exception { + void startTestCluster() throws Exception { objectMapper = new ObjectMapper(); testingCluster = new TestingCluster(3); testingCluster.start(); @@ -59,7 +61,7 @@ public void startTestCluster() throws Exception { } @AfterEach - public void stopTestCluster() throws Exception { + void stopTestCluster() throws Exception { serviceProviders.forEach(ServiceProvider::stop); if (null != testingCluster) { testingCluster.close(); @@ -103,7 +105,8 @@ void testBasicDiscovery() { .withDeserializer(data -> { try { return objectMapper.readValue(data, - new TypeReference>() {}); + new TypeReference>() { + }); } catch (IOException e) { e.printStackTrace(); } @@ -135,8 +138,7 @@ private void registerService(String host, int port, int a, int b) { .withSerializer(data -> { try { return objectMapper.writeValueAsBytes(data); - } - catch (JsonProcessingException e) { + } catch (JsonProcessingException e) { e.printStackTrace(); } return null; diff --git a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceNoProviderTest.java b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceNoProviderTest.java index d1947e9c..ee98e14a 100644 --- a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceNoProviderTest.java +++ b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceNoProviderTest.java @@ -29,7 +29,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - import java.io.IOException; class ServiceNoProviderTest { @@ -38,14 +37,14 @@ class ServiceNoProviderTest { private ObjectMapper objectMapper; @BeforeEach - public void startTestCluster() throws Exception { + void startTestCluster() throws Exception { objectMapper = new ObjectMapper(); testingCluster = new TestingCluster(3); testingCluster.start(); } @AfterEach - public void stopTestCluster() throws Exception { + void stopTestCluster() throws Exception { if (null != testingCluster) { testingCluster.close(); } @@ -60,10 +59,9 @@ void testBasicDiscovery() { .withDeserializer(data -> { try { return objectMapper.readValue(data, - new TypeReference>() { - }); - } - catch (IOException e) { + new TypeReference>() { + }); + } catch (IOException e) { e.printStackTrace(); } return null; @@ -86,10 +84,9 @@ void testBasicDiscoveryRR() { .withDeserializer(data -> { try { return objectMapper.readValue(data, - new TypeReference>() { - }); - } - catch (IOException e) { + new TypeReference>() { + }); + } catch (IOException e) { e.printStackTrace(); } return null; diff --git a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceProviderExtCuratorTest.java b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceProviderExtCuratorTest.java index 9d2cec7b..d2514c73 100644 --- a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceProviderExtCuratorTest.java +++ b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceProviderExtCuratorTest.java @@ -51,7 +51,7 @@ class ServiceProviderExtCuratorTest { private CuratorFramework curatorFramework; @BeforeEach - public void startTestCluster() throws Exception { + void startTestCluster() throws Exception { objectMapper = new ObjectMapper(); testingCluster = new TestingCluster(3); testingCluster.start(); @@ -66,10 +66,10 @@ public void startTestCluster() throws Exception { } @AfterEach - public void stopTestCluster() throws Exception { + void stopTestCluster() throws Exception { serviceProviders.forEach(ServiceProvider::stop); curatorFramework.close(); - if(null != testingCluster) { + if (null != testingCluster) { testingCluster.close(); } } diff --git a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceProviderHealthcheckTest.java b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceProviderHealthcheckTest.java index 8abe455d..418152ea 100644 --- a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceProviderHealthcheckTest.java +++ b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceProviderHealthcheckTest.java @@ -45,7 +45,7 @@ class ServiceProviderHealthcheckTest { private final Map serviceProviders = Maps.newHashMap(); @BeforeEach - public void startTestCluster() throws Exception { + void startTestCluster() throws Exception { objectMapper = new ObjectMapper(); testingCluster = new TestingCluster(3); testingCluster.start(); @@ -54,7 +54,7 @@ public void startTestCluster() throws Exception { } @AfterEach - public void stopTestCluster() throws Exception { + void stopTestCluster() throws Exception { if (null != testingCluster) { testingCluster.close(); } diff --git a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceProviderTest.java b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceProviderTest.java index d98a9477..57b7d3d3 100644 --- a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceProviderTest.java +++ b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/ServiceProviderTest.java @@ -49,7 +49,7 @@ class ServiceProviderTest { private final List>> serviceProviders = Lists.newArrayList(); @BeforeEach - public void startTestCluster() throws Exception { + void startTestCluster() throws Exception { objectMapper = new ObjectMapper(); testingCluster = new TestingCluster(3); testingCluster.start(); @@ -60,7 +60,7 @@ public void startTestCluster() throws Exception { } @AfterEach - public void stopTestCluster() throws Exception { + void stopTestCluster() throws Exception { serviceProviders.forEach(ServiceProvider::stop); if (null != testingCluster) { testingCluster.close(); @@ -75,9 +75,9 @@ void testBasicDiscovery() { .withServiceName("test-service") .withDeserializer(data -> { try { - return objectMapper.readValue(data, new TypeReference>() {}); - } - catch (IOException e) { + return objectMapper.readValue(data, new TypeReference>() { + }); + } catch (IOException e) { e.printStackTrace(); } return null; @@ -148,7 +148,6 @@ void testBasicDiscoveryRR() { Assertions.assertFalse(node.isPresent()); } serviceFinder.stop(); - //while (true); } @Test diff --git a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/SimpleServiceProviderTest.java b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/SimpleServiceProviderTest.java index f774220f..26238b33 100644 --- a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/SimpleServiceProviderTest.java +++ b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/model/SimpleServiceProviderTest.java @@ -40,18 +40,18 @@ class SimpleServiceProviderTest { private ObjectMapper objectMapper; @BeforeEach - public void startTestCluster() throws Exception { + void startTestCluster() throws Exception { objectMapper = new ObjectMapper(); testingCluster = new TestingCluster(3); testingCluster.start(); registerService("localhost-1", 9000); - registerService("localhost-2", 9001 ); + registerService("localhost-2", 9001); registerService("localhost-3", 9002); } @AfterEach - public void stopTestCluster() throws Exception { - if(null != testingCluster) { + void stopTestCluster() throws Exception { + if (null != testingCluster) { testingCluster.close(); } } @@ -99,7 +99,7 @@ void testBasicDiscovery() { Assertions.assertNotNull(node); frequency.add(node.getHost()); }); - System.out.println("1 Million lookups and freq counting took (ms):" + (System.currentTimeMillis() -startTime)); + System.out.println("1 Million lookups and freq counting took (ms):" + (System.currentTimeMillis() - startTime)); System.out.println("Frequency: " + frequency); } diff --git a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/servicehub/ServiceHubTest.java b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/servicehub/ServiceHubTest.java index ffc26164..59411388 100644 --- a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/servicehub/ServiceHubTest.java +++ b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/servicehub/ServiceHubTest.java @@ -57,7 +57,7 @@ class ServiceHubTest { private CuratorFramework curatorFramework; @BeforeEach - public void startTestCluster() throws Exception { + void startTestCluster() throws Exception { objectMapper = new ObjectMapper(); testingCluster = new TestingCluster(3); testingCluster.start(); @@ -72,7 +72,7 @@ public void startTestCluster() throws Exception { } @AfterEach - public void stopTestCluster() throws Exception { + void stopTestCluster() throws Exception { log.debug("Stopping zk subsystem"); curatorFramework.close(); if (null != testingCluster) { @@ -103,16 +103,16 @@ void testHub() { val refreshHubSignal = new ExternalTriggeredSignal(() -> null, Collections.emptyList()); val hub = new ZkServiceFinderHubBuilder>() - .withCuratorFramework(curatorFramework) - .withNamespace("test") - .withRefreshFrequencyMs(1000) - .withServiceDataSource(new ZkServiceDataSource("test", testingCluster.getConnectString(), curatorFramework)) - .withServiceFinderFactory(ZkShardedServiceFinderFactory.builder() - .curatorFramework(curatorFramework) - .deserializer(this::read) - .build()) - .withExtraRefreshSignal(refreshHubSignal) - .build(); + .withCuratorFramework(curatorFramework) + .withNamespace("test") + .withRefreshFrequencyMs(1000) + .withServiceDataSource(new ZkServiceDataSource("test", testingCluster.getConnectString(), curatorFramework)) + .withServiceFinderFactory(ZkShardedServiceFinderFactory.builder() + .curatorFramework(curatorFramework) + .deserializer(this::read) + .build()) + .withExtraRefreshSignal(refreshHubSignal) + .build(); hub.start(); refreshHubSignal.trigger(); @@ -125,9 +125,9 @@ void testHub() { private ServiceNode read(final byte[] data) { try { - return objectMapper.readValue(data, new TypeReference>() {}); - } - catch (IOException e) { + return objectMapper.readValue(data, new TypeReference>() { + }); + } catch (IOException e) { Exceptions.illegalState(e); } return null; @@ -136,8 +136,7 @@ private ServiceNode read(final byte[] data) { private byte[] write(final ServiceNode node) { try { return objectMapper.writeValueAsBytes(node); - } - catch (IOException e) { + } catch (IOException e) { Exceptions.illegalState(e); } return null; diff --git a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/serviceprovider/BaseServiceProviderBuilderTest.java b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/serviceprovider/BaseServiceProviderBuilderTest.java index 0dcb5a1d..963f8adf 100644 --- a/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/serviceprovider/BaseServiceProviderBuilderTest.java +++ b/ranger-zookeeper/src/test/java/io/appform/ranger/zookeeper/serviceprovider/BaseServiceProviderBuilderTest.java @@ -38,15 +38,15 @@ class BaseServiceProviderBuilderTest { private ObjectMapper objectMapper; @BeforeEach - public void startTestCluster() throws Exception { + void startTestCluster() throws Exception { objectMapper = new ObjectMapper(); testingCluster = new TestingCluster(3); testingCluster.start(); } @AfterEach - public void stopTestCluster() throws Exception { - if(null != testingCluster) { + void stopTestCluster() throws Exception { + if (null != testingCluster) { testingCluster.close(); } } diff --git a/ranger-zookeeper/src/test/resources/logback.xml b/ranger-zookeeper/src/test/resources/logback.xml index 907ce4a7..9c25c3f8 100644 --- a/ranger-zookeeper/src/test/resources/logback.xml +++ b/ranger-zookeeper/src/test/resources/logback.xml @@ -23,14 +23,14 @@ - + - + - - + + \ No newline at end of file