From 8a8a5f590a3946945e3b922ad17347b51bc3fd77 Mon Sep 17 00:00:00 2001 From: "shashank.g" Date: Fri, 4 Nov 2016 12:50:38 +0530 Subject: [PATCH 1/6] fabric-manager apis --- .../db-schema/fabric_manager_local.sql | 227 +++++++++++++ fabric-manager/pom.xml | 228 +++++++++++++ .../java/com/olacabs/fabric/manager/App.java | 153 +++++++++ .../bean/ArtifactoryRegistrationRequest.java | 53 +++ .../manager/bean/ComponentVersions.java | 78 +++++ .../fabric/manager/bean/DockerConfig.java | 47 +++ .../fabric/manager/bean/DockerOptions.java | 38 +++ .../fabric/manager/bean/ExecutorConfig.java | 54 +++ .../fabric/manager/bean/NetworkType.java | 24 ++ .../fabric/manager/bean/RuntimeOptions.java | 72 ++++ .../fabric/manager/bean/ShardInfo.java | 40 +++ .../fabric/manager/config/ManagerConfig.java | 67 ++++ .../fabric/manager/config/OpenTsdbConfig.java | 51 +++ .../config/ServiceDiscoveryConfig.java | 66 ++++ .../converter/ComponentSourceConverter.java | 69 ++++ .../manager/converter/JsonListConverter.java | 71 ++++ .../manager/converter/JsonSetConverter.java | 69 ++++ .../fabric/manager/dao/IApplicationDAO.java | 73 ++++ .../fabric/manager/dao/IComponentDAO.java | 68 ++++ .../fabric/manager/dao/IComputationDAO.java | 67 ++++ .../manager/dao/IGlobalPropertyDAO.java | 57 ++++ .../manager/dao/impl/ApplicationDAO.java | 86 +++++ .../fabric/manager/dao/impl/BaseDAO.java | 90 +++++ .../fabric/manager/dao/impl/ComponentDAO.java | 92 ++++++ .../manager/dao/impl/ComputationDAO.java | 87 +++++ .../manager/dao/impl/GlobalPropertyDAO.java | 81 +++++ .../manager/domain/ApplicationDomain.java | 71 ++++ .../fabric/manager/domain/BaseDomain.java | 75 +++++ .../manager/domain/ComponentDomain.java | 126 +++++++ .../domain/ComponentInstanceDomain.java | 92 ++++++ .../manager/domain/ComputationDomain.java | 138 ++++++++ .../manager/domain/ConnectionDomain.java | 61 ++++ .../manager/domain/GlobalPropertyDomain.java | 61 ++++ .../manager/domain/TenantBaseDomain.java | 43 +++ .../exception/FabricManagerException.java | 33 ++ .../exception/ResourceNotFoundException.java | 44 +++ .../exception/UnProcessableException.java | 52 +++ .../mapper/RuntimeExceptionMapper.java | 66 ++++ .../fabric/manager/filter/Context.java | 29 ++ .../fabric/manager/filter/UserContext.java | 50 +++ .../fabric/manager/filter/UserFilter.java | 59 ++++ .../fabric/manager/filter/UserRequired.java | 30 ++ .../managed/OpenTsdbMetricReporter.java | 101 ++++++ .../fabric/manager/managed/ServiceFinder.java | 74 +++++ .../manager/managed/ServiceRegistry.java | 107 ++++++ .../manager/resource/ApplicationResource.java | 186 +++++++++++ .../manager/resource/ComponentResource.java | 195 +++++++++++ .../manager/resource/ComputationResource.java | 143 ++++++++ .../resource/GlobalPropertyResource.java | 81 +++++ .../resource/ServiceRegistryResource.java | 52 +++ .../manager/service/IApplicationService.java | 106 ++++++ .../manager/service/IComponentService.java | 70 ++++ .../manager/service/IComputationService.java | 61 ++++ .../service/IGlobalPropertyService.java | 56 ++++ .../service/impl/ApplicationService.java | 312 ++++++++++++++++++ .../service/impl/ComponentService.java | 76 +++++ .../service/impl/ComputationService.java | 90 +++++ .../service/impl/GlobalPropertyService.java | 55 +++ .../fabric/manager/utils/ComputationUtil.java | 159 +++++++++ .../fabric/manager/utils/GraphUtil.java | 85 +++++ .../manager/utils/graph/DirectedGraph.java | 125 +++++++ .../fabric/manager/utils/graph/Graph.java | 39 +++ .../manager/utils/graph/UndirectedGraph.java | 69 ++++ .../src/main/resources/dev-config.yml | 79 +++++ .../main/resources/docker-compose-config.yml | 78 +++++ .../src/main/resources/prod-config.yml | 77 +++++ .../ComponentSourceConverterTest.java | 52 +++ .../converter/JsonListConverterTest.java | 63 ++++ .../converter/JsonSetConverterTest.java | 67 ++++ .../filter/UserRequiredFilterTest.java | 66 ++++ .../manager/util/graph/DirectedGraphTest.java | 80 +++++ .../util/graph/UndirectedGraphTest.java | 81 +++++ pom.xml | 1 + src/build/checkstyle.xml | 8 +- 74 files changed, 6028 insertions(+), 4 deletions(-) create mode 100644 fabric-manager/db-schema/fabric_manager_local.sql create mode 100644 fabric-manager/pom.xml create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/App.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ArtifactoryRegistrationRequest.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ComponentVersions.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/DockerConfig.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/DockerOptions.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ExecutorConfig.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/NetworkType.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/RuntimeOptions.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ShardInfo.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/config/ManagerConfig.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/config/OpenTsdbConfig.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/config/ServiceDiscoveryConfig.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/ComponentSourceConverter.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/JsonListConverter.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/JsonSetConverter.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IApplicationDAO.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IComponentDAO.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IComputationDAO.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IGlobalPropertyDAO.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/ApplicationDAO.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/BaseDAO.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/ComponentDAO.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/ComputationDAO.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/GlobalPropertyDAO.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ApplicationDomain.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/BaseDomain.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ComponentDomain.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ComponentInstanceDomain.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ComputationDomain.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ConnectionDomain.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/GlobalPropertyDomain.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/TenantBaseDomain.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/FabricManagerException.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/ResourceNotFoundException.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/UnProcessableException.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/mapper/RuntimeExceptionMapper.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/Context.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/UserContext.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/UserFilter.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/UserRequired.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/managed/OpenTsdbMetricReporter.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/managed/ServiceFinder.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/managed/ServiceRegistry.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ApplicationResource.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ComponentResource.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ComputationResource.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/GlobalPropertyResource.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ServiceRegistryResource.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IApplicationService.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IComponentService.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IComputationService.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IGlobalPropertyService.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/ApplicationService.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/ComponentService.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/ComputationService.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/GlobalPropertyService.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/ComputationUtil.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/GraphUtil.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/graph/DirectedGraph.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/graph/Graph.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/graph/UndirectedGraph.java create mode 100644 fabric-manager/src/main/resources/dev-config.yml create mode 100644 fabric-manager/src/main/resources/docker-compose-config.yml create mode 100644 fabric-manager/src/main/resources/prod-config.yml create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/converter/ComponentSourceConverterTest.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/converter/JsonListConverterTest.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/converter/JsonSetConverterTest.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/filter/UserRequiredFilterTest.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/util/graph/DirectedGraphTest.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/util/graph/UndirectedGraphTest.java diff --git a/fabric-manager/db-schema/fabric_manager_local.sql b/fabric-manager/db-schema/fabric_manager_local.sql new file mode 100644 index 0000000..9988a23 --- /dev/null +++ b/fabric-manager/db-schema/fabric_manager_local.sql @@ -0,0 +1,227 @@ +--Copyright 2016 ANI Technologies 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. + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `applications` +-- + +DROP TABLE IF EXISTS `applications`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `applications` ( + `internalId` int(11) NOT NULL AUTO_INCREMENT, + `createdAt` datetime DEFAULT NULL, + `createdBy` varchar(255) DEFAULT NULL, + `updatedAt` datetime DEFAULT NULL, + `updatedBy` varchar(255) DEFAULT NULL, + `tenant` varchar(255) DEFAULT NULL, + `active` bit(1) DEFAULT NULL, + `executorConfig` varchar(255) DEFAULT NULL, + `instances` int(11) DEFAULT NULL, + `name` varchar(255) DEFAULT NULL, + `computationId` int(11) DEFAULT NULL, + `runtimeOptions` text, + PRIMARY KEY (`internalId`), + KEY `FK_eurgh9se1wmg3t8sec838ktg4` (`computationId`), + CONSTRAINT `FK_eurgh9se1wmg3t8sec838ktg4` FOREIGN KEY (`computationId`) REFERENCES `computations` (`internalId`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `component_instance_properties` +-- + +DROP TABLE IF EXISTS `component_instance_properties`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `component_instance_properties` ( + `componentInstanceId` int(11) NOT NULL, + `id` varchar(255) NOT NULL, + `value` longtext, + PRIMARY KEY (`componentInstanceId`,`id`), + CONSTRAINT `FK_115flepnf4udbgfnfoysdv6r0` FOREIGN KEY (`componentInstanceId`) REFERENCES `component_instances` (`internalId`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `component_instances` +-- + +DROP TABLE IF EXISTS `component_instances`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `component_instances` ( + `internalId` int(11) NOT NULL AUTO_INCREMENT, + `createdAt` datetime DEFAULT NULL, + `createdBy` varchar(255) DEFAULT NULL, + `updatedAt` datetime DEFAULT NULL, + `updatedBy` varchar(255) DEFAULT NULL, + `id` varchar(255) NOT NULL, + `type` varchar(255) DEFAULT NULL, + `componentId` int(11) DEFAULT NULL, + `computationId` int(11) DEFAULT NULL, + PRIMARY KEY (`internalId`), + KEY `FK_4clo6td5n91vlffjkbf8uth00` (`componentId`), + KEY `FK_30989sg2syeh2kv2sbmdwqloe` (`computationId`), + CONSTRAINT `FK_30989sg2syeh2kv2sbmdwqloe` FOREIGN KEY (`computationId`) REFERENCES `computations` (`internalId`), + CONSTRAINT `FK_4clo6td5n91vlffjkbf8uth00` FOREIGN KEY (`componentId`) REFERENCES `components` (`internalId`) +) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `components` +-- + +DROP TABLE IF EXISTS `components`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `components` ( + `internalId` int(11) NOT NULL AUTO_INCREMENT, + `createdAt` datetime DEFAULT NULL, + `createdBy` varchar(255) DEFAULT NULL, + `updatedAt` datetime DEFAULT NULL, + `updatedBy` varchar(255) DEFAULT NULL, + `cpu` double NOT NULL, + `deleted` bit(1) NOT NULL, + `memory` double NOT NULL, + `name` varchar(255) NOT NULL, + `namespace` varchar(255) NOT NULL, + `processorType` varchar(255) DEFAULT NULL, + `source` varchar(255) NOT NULL, + `type` varchar(255) NOT NULL, + `version` varchar(255) NOT NULL, + `description` longtext, + `optionalProperties` longtext, + `requiredProperties` longtext, + PRIMARY KEY (`internalId`) +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `computation_attributes` +-- + +DROP TABLE IF EXISTS `computation_attributes`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `computation_attributes` ( + `computationId` int(11) NOT NULL, + `value` varchar(255) DEFAULT NULL, + `id` varchar(255) NOT NULL, + PRIMARY KEY (`computationId`,`id`), + CONSTRAINT `FK_b8u41lxfyicp4ba0oys6o23pt` FOREIGN KEY (`computationId`) REFERENCES `computations` (`internalId`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `computation_properties` +-- + +DROP TABLE IF EXISTS `computation_properties`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `computation_properties` ( + `computationId` int(11) NOT NULL, + `value` varchar(255) DEFAULT NULL, + `id` varchar(255) NOT NULL, + PRIMARY KEY (`computationId`,`id`), + CONSTRAINT `FK_8nbtsd50dcmaba7rjw4wikkui` FOREIGN KEY (`computationId`) REFERENCES `computations` (`internalId`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `computations` +-- + +DROP TABLE IF EXISTS `computations`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `computations` ( + `internalId` int(11) NOT NULL AUTO_INCREMENT, + `createdAt` datetime DEFAULT NULL, + `createdBy` varchar(255) DEFAULT NULL, + `updatedAt` datetime DEFAULT NULL, + `updatedBy` varchar(255) DEFAULT NULL, + `tenant` varchar(255) DEFAULT NULL, + `deleted` bit(1) NOT NULL, + `name` varchar(255) NOT NULL, + `ownerEmail` varchar(255) NOT NULL, + `description` longtext, + `version` int(11) NOT NULL, + PRIMARY KEY (`internalId`) +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `connections` +-- + +DROP TABLE IF EXISTS `connections`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `connections` ( + `internalId` int(11) NOT NULL AUTO_INCREMENT, + `createdAt` datetime DEFAULT NULL, + `createdBy` varchar(255) DEFAULT NULL, + `updatedAt` datetime DEFAULT NULL, + `updatedBy` varchar(255) DEFAULT NULL, + `fromLink` varchar(255) DEFAULT NULL, + `fromType` varchar(255) NOT NULL, + `toLink` varchar(255) DEFAULT NULL, + `computationId` int(11) DEFAULT NULL, + PRIMARY KEY (`internalId`), + KEY `FK_k9c6jc8kf6xqym2gmtpswgnpu` (`computationId`), + CONSTRAINT `FK_k9c6jc8kf6xqym2gmtpswgnpu` FOREIGN KEY (`computationId`) REFERENCES `computations` (`internalId`) +) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `global_properties` +-- + +DROP TABLE IF EXISTS `global_properties`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `global_properties` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `deleted` bit(1) NOT NULL, + `description` varchar(255) DEFAULT NULL, + `name` varchar(255) NOT NULL, + `type` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_tqqwe6s7avhd581j89iro56j5` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2016-11-03 17:09:46 diff --git a/fabric-manager/pom.xml b/fabric-manager/pom.xml new file mode 100644 index 0000000..f19ed56 --- /dev/null +++ b/fabric-manager/pom.xml @@ -0,0 +1,228 @@ + + + + + + fabric-compute + com.olacabs.fabric + 1.0.0-SNAPSHOT + + 4.0.0 + + fabric-manager + + + + clojars + Clojars repository + https://clojars.org/repo + + + + + UTF-8 + 0.8.4 + 0.4.3-rc1-1 + 0.0.1 + 1.0.7 + 0.2.1 + 1.0.0.Final + 4.3.10.Final + 5.1.26 + 0.9.1.2 + 1.9.5 + 2.5.3 + + + + + + io.federecio + dropwizard-swagger + 0.7.0 + + + + + javax.validation + validation-api + 1.1.0.Final + + + + + io.dropwizard + dropwizard-hibernate + ${dropwizard.version} + + + + + mysql + mysql-connector-java + ${mysql.connector.version} + + + + io.dropwizard + dropwizard-core + ${dropwizard.version} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson.version} + + + + org.mockito + mockito-all + ${mockito.version} + test + + + + com.github.mohitsoni + marathon-client + ${marathon.client.version} + + + + io.dropwizard + dropwizard-assets + ${dropwizard.version} + + + + com.olacabs.fabric + fabric-compute-framework + ${project.version} + + + + com.flipkart.ranger + ranger + ${ranger.version} + + + org.slf4j + slf4j-log4j12 + + + + + + com.shash + envvar-interpolation + ${envvar.interpolation.version} + + + + com.github.sps.metrics + metrics-opentsdb + ${metric.opentsdb.version} + + + com.fasterxml.jackson.core + jackson-annotations + + + org.glassfish.jersey.core + jersey-client + + + org.glassfish.jersey.core + jersey-common + + + + + + + + + org.projectlombok + lombok-maven-plugin + 1.16.4.1 + + + generate-sources + + delombok + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + true + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + package + + shade + + + + + + com.olacabs.fabric.manager.App + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + + diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/App.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/App.java new file mode 100644 index 0000000..76af937 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/App.java @@ -0,0 +1,153 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.olacabs.fabric.compute.builder.impl.JarScanner; +import com.olacabs.fabric.manager.config.ManagerConfig; +import com.olacabs.fabric.manager.dao.IApplicationDAO; +import com.olacabs.fabric.manager.dao.IComponentDAO; +import com.olacabs.fabric.manager.dao.IComputationDAO; +import com.olacabs.fabric.manager.dao.IGlobalPropertyDAO; +import com.olacabs.fabric.manager.dao.impl.ApplicationDAO; +import com.olacabs.fabric.manager.dao.impl.ComponentDAO; +import com.olacabs.fabric.manager.dao.impl.ComputationDAO; +import com.olacabs.fabric.manager.dao.impl.GlobalPropertyDAO; +import com.olacabs.fabric.manager.domain.*; +import com.olacabs.fabric.manager.exception.mapper.RuntimeExceptionMapper; +import com.olacabs.fabric.manager.filter.UserFilter; +import com.olacabs.fabric.manager.managed.OpenTsdbMetricReporter; +import com.olacabs.fabric.manager.managed.ServiceFinder; +import com.olacabs.fabric.manager.managed.ServiceRegistry; +import com.olacabs.fabric.manager.resource.ApplicationResource; +import com.olacabs.fabric.manager.resource.ComponentResource; +import com.olacabs.fabric.manager.resource.*; +import com.olacabs.fabric.manager.service.IApplicationService; +import com.olacabs.fabric.manager.service.IComponentService; +import com.olacabs.fabric.manager.service.IComputationService; +import com.olacabs.fabric.manager.service.IGlobalPropertyService; +import com.olacabs.fabric.manager.service.impl.ApplicationService; +import com.olacabs.fabric.manager.service.impl.ComponentService; +import com.olacabs.fabric.manager.service.impl.ComputationService; +import com.olacabs.fabric.manager.service.impl.GlobalPropertyService; + +import io.dropwizard.Application; +import io.dropwizard.db.DataSourceFactory; +import io.dropwizard.hibernate.HibernateBundle; +import io.dropwizard.setup.Bootstrap; +import io.dropwizard.setup.Environment; +import io.federecio.dropwizard.swagger.SwaggerBundle; +import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration; +import mesosphere.marathon.client.MarathonClient; +import minisu.dropwizard.interpolation.EnvironmentVariableInterpolationBundle; + +/** + * Todo . + */ +public class App extends Application { + + public static final String APP_NAME = "fabric-manager"; + + /* + * Hibernate bundle + */ + private final HibernateBundle hibernate = new HibernateBundle(ConnectionDomain.class, + ComputationDomain.class, ComponentInstanceDomain.class, ComponentDomain.class, GlobalPropertyDomain.class, + ApplicationDomain.class) { + @Override + public DataSourceFactory getDataSourceFactory(final ManagerConfig configuration) { + return configuration.getDatabase(); + } + }; + + /* + * Swagger bundle + */ + private final SwaggerBundle swaggerBundle = new SwaggerBundle() { + @Override + protected SwaggerBundleConfiguration getSwaggerBundleConfiguration(ManagerConfig configuration) { + return configuration.getSwaggerBundleConfiguration(); + } + }; + + @Override + public void initialize(final Bootstrap bootstrap) { + super.initialize(bootstrap); + bootstrap.addBundle(new EnvironmentVariableInterpolationBundle()); + bootstrap.addBundle(hibernate); + bootstrap.addBundle(swaggerBundle); + } + + @Override + public void run(final ManagerConfig config, final Environment environment) throws Exception { + environment.getObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_EMPTY); + environment.getObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); + + final IComponentDAO componentDAO = new ComponentDAO(hibernate.getSessionFactory()); + final IApplicationDAO applicationDAO = new ApplicationDAO(hibernate.getSessionFactory()); + final IGlobalPropertyDAO globalPropertyDAO = new GlobalPropertyDAO(hibernate.getSessionFactory()); + final IComputationDAO computationDAO = new ComputationDAO(hibernate.getSessionFactory()); + + final IComponentService componentService = new ComponentService(componentDAO); + final IComputationService computationService = new ComputationService(computationDAO, componentDAO); + final IGlobalPropertyService globalPropertyService = new GlobalPropertyService(globalPropertyDAO); + final IApplicationService applicationService = new ApplicationService(applicationDAO, + MarathonClient.getInstance(config.getMarathonEndpoint()), config); + + final ComponentResource componentResource = + new ComponentResource(componentService, config.getArtifactoryPath(), new JarScanner()); + final ComputationResource computationResource = new ComputationResource(computationService); + final GlobalPropertyResource globalPropertyResource = new GlobalPropertyResource(globalPropertyService); + + final ApplicationResource appResource = + new ApplicationResource(applicationService, computationService, config.getExecutor()); + final OpenTsdbMetricReporter openTsdb = new OpenTsdbMetricReporter(config, environment.metrics()); + + final ServiceRegistry serviceRegistry = + new ServiceRegistry(environment.getObjectMapper(), config, config.getServiceDiscovery()); + final ServiceFinder serviceFinder = + new ServiceFinder(environment.getObjectMapper(), config.getServiceDiscovery()); + final ServiceRegistryResource serviceRegistryResource = new ServiceRegistryResource(serviceFinder); + + /** + * Register managed, resources, exception mapper, filters + */ + environment.lifecycle().manage(openTsdb); + environment.lifecycle().manage(serviceRegistry); + environment.lifecycle().manage(serviceFinder); + + environment.jersey().register(componentResource); + environment.jersey().register(computationResource); + environment.jersey().register(serviceRegistryResource); + environment.jersey().register(appResource); + environment.jersey().register(globalPropertyResource); + + environment.jersey().register(RuntimeExceptionMapper.class); +// environment.jersey().register(HttpExceptionMapper.class); + + environment.jersey().register(UserFilter.class); + } + + /** + * @param args to start java process + * @throws Exception + */ + public static void main(final String[] args) throws Exception { + final App app = new App(); + app.run(args); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ArtifactoryRegistrationRequest.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ArtifactoryRegistrationRequest.java new file mode 100644 index 0000000..3dcbf88 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ArtifactoryRegistrationRequest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.bean; + +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.NotEmpty; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * ArtifactoryRegistrationRequest . Class used for request body serialization, de-serialization + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class ArtifactoryRegistrationRequest { + + private String artifactory; + + @NotNull + @NotEmpty + private String groupId; + + @NotNull + @NotEmpty + private String artifactId; + + @NotEmpty + @NotNull + private String version; +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ComponentVersions.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ComponentVersions.java new file mode 100644 index 0000000..290fb3f --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ComponentVersions.java @@ -0,0 +1,78 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.bean; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.google.common.collect.Lists; +import com.olacabs.fabric.manager.domain.ComponentDomain; + +import lombok.*; + +/** + * Component versions class bean. + */ +@Builder +@Data +@AllArgsConstructor +@ToString +@JsonIgnoreProperties(ignoreUnknown = true) +public class ComponentVersions { + + @NotNull + private String namespace; + + @NotNull + private String name; + + @Singular + private List versions = Lists.newArrayList(); + + /** + * Resolves list of computation versions from meta . + * + * @param components to resolve + * @return list of component versions + */ + @JsonIgnore + public static List resolve(final Set components) { + final List componentVersions = Lists.newArrayList(); + components.stream() + .collect(Collectors.groupingBy(componentMetadata -> + componentMetadata.getNamespace() + "." + componentMetadata.getName())) + .entrySet() + .stream() + .forEach(entry -> { + final String[] parts = entry.getKey().split("\\."); + if (parts.length < 2) { + return; + } + final List metadataList = entry.getValue(); + final ComponentVersionsBuilder builder = + ComponentVersions.builder().namespace(parts[0]).name(parts[1]); + metadataList.forEach(componentMetadata -> builder.version(componentMetadata.getVersion())); + componentVersions.add(builder.build()); + }); + return componentVersions; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/DockerConfig.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/DockerConfig.java new file mode 100644 index 0000000..6302ea4 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/DockerConfig.java @@ -0,0 +1,47 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.bean; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.google.common.collect.Lists; + +import lombok.*; +import mesosphere.marathon.client.model.v2.Volume; + +/** + * Docker Config bean. + */ +@Builder +@AllArgsConstructor +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class DockerConfig { + + @Getter + @Setter + private DockerOptions dockerOpts = new DockerOptions(); + + @Getter + @Setter + private NetworkType networkType = NetworkType.BRIDGE; + + @Getter + @Setter + private List volumes = Lists.newArrayList(); +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/DockerOptions.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/DockerOptions.java new file mode 100644 index 0000000..2e802d9 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/DockerOptions.java @@ -0,0 +1,38 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.bean; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import lombok.*; +import mesosphere.marathon.client.model.v2.Parameter; + +/** + * Todo . + */ +@Builder +@AllArgsConstructor +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class DockerOptions { + @Getter + @Setter + private List parameters = new ArrayList<>(); +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ExecutorConfig.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ExecutorConfig.java new file mode 100644 index 0000000..900971a --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ExecutorConfig.java @@ -0,0 +1,54 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.bean; + +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.NotEmpty; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import lombok.*; + +/** + * Executor config bean. + */ +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class ExecutorConfig { + + @NotNull + @NotEmpty + @Getter + @Setter + private String executorDockerImage; + + @Getter + @Setter + private double minCpu = 0.5; + + @Getter + @Setter + private double minMemory = 1024.0; + + @Getter + @Setter + // jvm heap to total container memory ratio + private double alpha = 0.5; +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/NetworkType.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/NetworkType.java new file mode 100644 index 0000000..4886baa --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/NetworkType.java @@ -0,0 +1,24 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.bean; + +/** + * Network type. + */ +public enum NetworkType { + HOST, BRIDGE, CONTAINER, NONE +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/RuntimeOptions.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/RuntimeOptions.java new file mode 100644 index 0000000..72cf84e --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/RuntimeOptions.java @@ -0,0 +1,72 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.bean; + +import java.util.Collections; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.*; + +/** + * Runtime options bean. + */ +@Builder +@AllArgsConstructor +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class RuntimeOptions { + + @Getter + @Setter + private String jvmOpts = ""; + + @Getter + @Setter + private List uris = Collections.singletonList("file:///root/.dockercfg"); + + @Getter + @Setter + private String logLevel = "INFO"; + + @Getter + @Setter + private boolean metricsDisabled = false; + + @Getter + @Setter + @JsonProperty("docker") + private DockerConfig dockerConfig = new DockerConfig(); + + @Getter + @Setter + private String executorDockerImage = ""; + + @Getter + @Setter + private double topologyCpu = 0.0; + + @Getter + @Setter + private double topologyMemory = 0.0; + + @Getter + @Setter + private int instances = 1; +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ShardInfo.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ShardInfo.java new file mode 100644 index 0000000..ffa30cd --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/bean/ShardInfo.java @@ -0,0 +1,40 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.bean; + +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * ShardInfo bean. + */ +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ShardInfo { + + @NotNull + private String shardId; +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/config/ManagerConfig.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/config/ManagerConfig.java new file mode 100644 index 0000000..3cc2171 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/config/ManagerConfig.java @@ -0,0 +1,67 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.config; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.olacabs.fabric.manager.bean.ExecutorConfig; + +import io.dropwizard.Configuration; +import io.dropwizard.db.DataSourceFactory; +import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration; +import lombok.*; + +/** + * Todo . + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ManagerConfig extends Configuration { + + @Getter + @Setter + @JsonProperty("swagger") + private SwaggerBundleConfiguration swaggerBundleConfiguration = new SwaggerBundleConfiguration(); + @NotNull + @Getter + private String artifactoryPath; + @Valid + @Getter + private ServiceDiscoveryConfig serviceDiscovery = new ServiceDiscoveryConfig(); + @Valid + @Getter + @JsonProperty("opentsdb") + private OpenTsdbConfig openTsdbConfig = new OpenTsdbConfig(); + @NotNull + @Valid + @Getter + private ExecutorConfig executor = new ExecutorConfig(); + @NotNull + @Getter + private String marathonEndpoint; + @Getter + private String fabricManagerConnectionString; + @NotNull + @Valid + @Getter + private DataSourceFactory database = new DataSourceFactory(); +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/config/OpenTsdbConfig.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/config/OpenTsdbConfig.java new file mode 100644 index 0000000..68ed797 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/config/OpenTsdbConfig.java @@ -0,0 +1,51 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.config; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Opentsdb config . + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +public class OpenTsdbConfig { + + private boolean enabled = true; + private String openTsdbUrl; + + @NotNull + private String appName = "fabric-manager"; + private String namespace; + private String platform; + + @Min(1) + @Max(300) + private long periodInSeconds = 30; +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/config/ServiceDiscoveryConfig.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/config/ServiceDiscoveryConfig.java new file mode 100644 index 0000000..7ca5ac3 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/config/ServiceDiscoveryConfig.java @@ -0,0 +1,66 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.config; + +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.NotEmpty; + +import lombok.Data; + +/** + * Registry configuration. + */ +@Data +public class ServiceDiscoveryConfig { + + @NotNull + @NotEmpty + private String zkConnectionString; + + /** + * Service name to be used by clients for discovery. + */ + @NotNull + @NotEmpty + private String serviceName; + + @NotNull + @NotEmpty + private String namespace = "fabric"; + + /** + * Set environment to dev/stage/qa/prod etc. + */ + @NotNull + @NotEmpty + private String environment; + + /** + * Using this is not recommended. + * It is used by services that get deployed through docker/mesos etc. + * This will default to the localhost name as derived from InetAdderss.getLocalHost().getCanonicalName() + */ + private String hostname; + + /** + * Using this is not recommended. + * It is used by services that get deployed through docker/mesos etc. + * This is read in by default from port settings in config.yml connector configuration. + */ + private int port = -1; +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/ComponentSourceConverter.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/ComponentSourceConverter.java new file mode 100644 index 0000000..4df0a25 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/ComponentSourceConverter.java @@ -0,0 +1,69 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.converter; + +import java.io.IOException; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.olacabs.fabric.manager.exception.FabricManagerException; +import com.olacabs.fabric.model.common.ComponentSource; + +import lombok.extern.slf4j.Slf4j; + +/** + * ComponentSourceConverter . + * JPA converter for component source bean. + * + */ +@Converter +@Slf4j +public class ComponentSourceConverter implements AttributeConverter { + + private final ObjectMapper mapper; + + public ComponentSourceConverter() { + this(new ObjectMapper()); + } + + public ComponentSourceConverter(final ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public String convertToDatabaseColumn(final ComponentSource componentSource) { + try { + return mapper.writeValueAsString(componentSource); + } catch (final JsonProcessingException e) { + log.error("Unable to parse component source - {}", e.getMessage(), e); + throw new FabricManagerException(e); + } + } + + @Override + public ComponentSource convertToEntityAttribute(final String source) { + try { + return mapper.readValue(source, ComponentSource.class); + } catch (final IOException e) { + log.error("Unable to parse component source - {}", e.getMessage(), e); + throw new FabricManagerException(e); + } + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/JsonListConverter.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/JsonListConverter.java new file mode 100644 index 0000000..99a5825 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/JsonListConverter.java @@ -0,0 +1,71 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.converter; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.olacabs.fabric.manager.exception.FabricManagerException; + +import lombok.extern.slf4j.Slf4j; + +/** + * TODO . + */ +@Converter +@Slf4j +public class JsonListConverter implements AttributeConverter { + + private final ObjectMapper serializer; + + public JsonListConverter() { + this(new ObjectMapper()); + } + + public JsonListConverter(final ObjectMapper serializer) { + this.serializer = serializer; + } + + @Override + public String convertToDatabaseColumn(final List value) { + try { + return serializer.writeValueAsString(value); + } catch (final JsonProcessingException e) { + log.error("Unable to parse list - {}. Error - {}", value, e.getMessage(), e); + throw new FabricManagerException(e); + } + } + + @Override + public List convertToEntityAttribute(final String value) { + try { + if (value == null) { + return Collections.emptyList(); + } + return serializer.readValue(value, List.class); + } catch (final IOException e) { + log.error("Unable to parse value to list - {}. Error - {}", value, e.getMessage(), e); + throw new FabricManagerException(e); + } + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/JsonSetConverter.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/JsonSetConverter.java new file mode 100644 index 0000000..d619e3b --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/JsonSetConverter.java @@ -0,0 +1,69 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.converter; + +import java.io.IOException; +import java.util.Collections; +import java.util.Set; + +import javax.persistence.AttributeConverter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.olacabs.fabric.manager.exception.FabricManagerException; + +import lombok.extern.slf4j.Slf4j; + +/** + * Todo . + */ +@Slf4j +public class JsonSetConverter implements AttributeConverter { + + private final ObjectMapper serializer; + + public JsonSetConverter() { + this(new ObjectMapper()); + } + + public JsonSetConverter(final ObjectMapper serializer) { + this.serializer = serializer; + } + + @Override + public String convertToDatabaseColumn(final Set value) { + try { + return serializer.writeValueAsString(value); + } catch (final JsonProcessingException e) { + log.error("Unable to parse Set - {}. Error - {}", value, e.getMessage(), e); + throw new FabricManagerException(e); + } + } + + @Override + public Set convertToEntityAttribute(final String value) { + try { + if (value == null) { + return Collections.emptySet(); + } + return serializer.readValue(value, Set.class); + } catch (final IOException e) { + log.error("Unable to parse value to Set - {}. Error - {}", value, e.getMessage(), e); + throw new FabricManagerException(e); + } + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IApplicationDAO.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IApplicationDAO.java new file mode 100644 index 0000000..5a95c84 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IApplicationDAO.java @@ -0,0 +1,73 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.dao; + +import java.util.Set; + +import com.olacabs.fabric.manager.domain.ApplicationDomain; + +/** + * Todo . + */ +public interface IApplicationDAO { + + /** + * Save application. + * + * @param application :: + * @return created application + */ + ApplicationDomain save(final ApplicationDomain application); + + /** + * Get application. + * + * @param internalId :: + * @return application + */ + ApplicationDomain get(final Long internalId); + + /** + * Soft delete application. + * + * @param application :: + */ + void delete(final ApplicationDomain application); + + /** + * Revive the application. + * + * @param application :: + */ + void revive(final ApplicationDomain application); + + /** + * Search application. + * + * @param appName to search + * @param tenant to search + * @return set of application + */ + Set search(final String appName, final String tenant); + + /** + * modify application. + * + * @param application :: + */ + void modify(final ApplicationDomain application); +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IComponentDAO.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IComponentDAO.java new file mode 100644 index 0000000..29fb88d --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IComponentDAO.java @@ -0,0 +1,68 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.dao; + +import java.util.Set; + +import com.olacabs.fabric.manager.domain.ComponentDomain; + +/** + * Todo . + */ +public interface IComponentDAO { + + /** + * Save a component. + * + * @param component :: to saveOrUpdate + * @return created component + */ + ComponentDomain save(final ComponentDomain component); + + /** + * Reads a component. + * + * @param componentId to read + * @return read component + */ + ComponentDomain read(final int componentId); + + /** + * Search component based on params. + * + * @param namespace to search + * @param name to search + * @param version to search + * @return set of searched components + */ + Set search(final String namespace, final String name, final String version); + + /** + * Update component. + * + * @param componentId to saveOrUpdate + * @param component to saveOrUpdate + */ + void update(final int componentId, final ComponentDomain component); + + /** + * Soft Delete component. + * + * @param componentId to deleteApp + */ + void delete(final int componentId); +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IComputationDAO.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IComputationDAO.java new file mode 100644 index 0000000..8b972a0 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IComputationDAO.java @@ -0,0 +1,67 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.dao; + +import java.util.Set; + +import com.olacabs.fabric.manager.domain.ComputationDomain; + +/** + * Todo . + */ +public interface IComputationDAO { + + /** + * Saves a computation. + * + * @param computation :: + * @return saved entity + */ + ComputationDomain save(final ComputationDomain computation); + + /** + * Get by id. + * + * @param computationId :: + * @return entity + */ + ComputationDomain get(final int computationId); + + /** + * Updates entity. + * + * @param computation :: + */ + void modify(final ComputationDomain computation); + + /** + * Deletes entity. + * + * @param computation :: + */ + void delete(final ComputationDomain computation); + + /** + * Searches entity given params. + * + * @param tenant :: + * @param name :: + * @param version :: + * @return set of entities + */ + Set search(final String tenant, final String name, final Integer version); +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IGlobalPropertyDAO.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IGlobalPropertyDAO.java new file mode 100644 index 0000000..946d43e --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/IGlobalPropertyDAO.java @@ -0,0 +1,57 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.dao; + +import java.util.Set; + +import com.olacabs.fabric.manager.domain.GlobalPropertyDomain; + +/** + * Todo . + */ +public interface IGlobalPropertyDAO { + + /** + * Saves property. + * + * @param property to saveOrUpdate + * @return saved property + */ + GlobalPropertyDomain save(final GlobalPropertyDomain property); + + /** + * Gets all properties. + * + * @return list of global properties + */ + Set search(final String name, final String propertyType); + + /** + * Get by id. + * + * @param id of property + * @return property + */ + GlobalPropertyDomain get(final int id); + + /** + * Delete property. + * + * @param property to delete + */ + void delete(final GlobalPropertyDomain property); +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/ApplicationDAO.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/ApplicationDAO.java new file mode 100644 index 0000000..08888cc --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/ApplicationDAO.java @@ -0,0 +1,86 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.dao.impl; + +import java.util.Set; + +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.criterion.Restrictions; + +import com.google.common.base.Strings; +import com.google.common.collect.Sets; +import com.olacabs.fabric.manager.dao.IApplicationDAO; +import com.olacabs.fabric.manager.domain.ApplicationDomain; + +/** + * Todo . + */ +public class ApplicationDAO extends BaseDAO implements IApplicationDAO { + + private final SessionFactory sessionFactory; + + public ApplicationDAO(final SessionFactory sessionFactory) { + super(sessionFactory); + this.sessionFactory = sessionFactory; + } + + @Override + public ApplicationDomain save(final ApplicationDomain application) { + application.setActive(true); + return super.persist(application); + } + + @Override + public ApplicationDomain get(final Long internalId) { + return super.get(internalId); + } + + @Override + public void delete(final ApplicationDomain application) { + application.setActive(false); + application.setInstances(0); + super.update(application); + } + + @Override + public void revive(final ApplicationDomain application) { + application.setActive(true); + super.update(application); + } + + @Override + public Set search(final String appName, final String tenant) { + final Session session = sessionFactory.getCurrentSession(); + final Criteria criteria = session.createCriteria(ApplicationDomain.class); + + if (!Strings.isNullOrEmpty(appName)) { + criteria.add(Restrictions.eq("name", appName)); + } + if (!Strings.isNullOrEmpty(tenant)) { + criteria.add(Restrictions.eq("tenant", tenant)); + } + + return Sets.newHashSet(super.list(criteria)); + } + + @Override + public void modify(final ApplicationDomain application) { + super.update(application); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/BaseDAO.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/BaseDAO.java new file mode 100644 index 0000000..be39916 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/BaseDAO.java @@ -0,0 +1,90 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.dao.impl; + +import java.io.Serializable; +import java.util.List; + +import org.hibernate.*; + +import com.olacabs.fabric.manager.domain.BaseDomain; + +import io.dropwizard.hibernate.AbstractDAO; + +/** + * Extending abstract dao. + * to execute entity pre-persist and pre-update Dropwizard-hibernate doesn't execute it by + * default apparently TODO - find a cleaner solution for @PrePersist & @PreUpdate + * + * @param + */ +public class BaseDAO extends AbstractDAO { + + public BaseDAO(final SessionFactory sessionFactory) { + super(sessionFactory); + } + + protected Session currentSession() { + return super.currentSession(); + } + + protected Criteria criteria() { + return super.criteria(); + } + + protected Query namedQuery(final String queryName) throws HibernateException { + return super.namedQuery(queryName); + } + + public Class getEntityClass() { + return super.getEntityClass(); + } + + protected E uniqueResult(Criteria criteria) throws HibernateException { + return super.uniqueResult(criteria); + } + + protected E uniqueResult(Query query) throws HibernateException { + return super.uniqueResult(query); + } + + protected List list(Criteria criteria) throws HibernateException { + return super.list(criteria); + } + + protected List list(Query query) throws HibernateException { + return super.list(query); + } + + protected E get(Serializable id) { + return super.get(id); + } + + protected E persist(E entity) throws HibernateException { + entity.prePersist(); + return super.persist(entity); + } + + protected E update(E entity) throws HibernateException { + entity.preUpdate(); + return super.persist(entity); + } + + protected T initialize(T proxy) throws HibernateException { + return super.initialize(proxy); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/ComponentDAO.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/ComponentDAO.java new file mode 100644 index 0000000..cad66e6 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/ComponentDAO.java @@ -0,0 +1,92 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.dao.impl; + +import java.util.Set; + +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.criterion.Restrictions; + +import com.google.common.base.Strings; +import com.google.common.collect.Sets; +import com.olacabs.fabric.manager.dao.IComponentDAO; +import com.olacabs.fabric.manager.domain.ComponentDomain; +import com.olacabs.fabric.manager.exception.ResourceNotFoundException; + +/** + * Todo . + */ +public class ComponentDAO extends BaseDAO implements IComponentDAO { + + private final SessionFactory sessionFactory; + + public ComponentDAO(final SessionFactory sessionFactory) { + super(sessionFactory); + this.sessionFactory = sessionFactory; + } + + @Override + public ComponentDomain save(final ComponentDomain component) { + return super.persist(component); + } + + @Override + public ComponentDomain read(final int componentId) { + final ComponentDomain component = super.get(componentId); + if (component == null || component.isDeleted()) { + throw new ResourceNotFoundException(String.format("Component not found with id - %d", componentId)); + } + return super.get(componentId); + } + + @Override + public Set search(final String namespace, final String name, final String version) { + final Session session = sessionFactory.getCurrentSession(); + final Criteria criteria = session.createCriteria(ComponentDomain.class); + criteria.add(Restrictions.eq("deleted", false)); + + if (!Strings.isNullOrEmpty(namespace)) { + criteria.add(Restrictions.eq("namespace", namespace)); + } + if (!Strings.isNullOrEmpty(name)) { + criteria.add(Restrictions.eq("name", name)); + } + if (!Strings.isNullOrEmpty(version)) { + criteria.add(Restrictions.eq("version", version)); + } + + final Set result = Sets.newHashSet(); + result.addAll(super.list(criteria)); + return result; + } + + @Override + public void update(final int componentId, final ComponentDomain component) { + final ComponentDomain readComp = read(componentId); + readComp.update(component); + super.update(readComp); + } + + @Override + public void delete(final int componentId) { + final ComponentDomain component = read(componentId); + component.setDeleted(true); + super.persist(component); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/ComputationDAO.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/ComputationDAO.java new file mode 100644 index 0000000..d05073d --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/ComputationDAO.java @@ -0,0 +1,87 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.dao.impl; + +import java.util.Set; + +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.criterion.Order; +import org.hibernate.criterion.Restrictions; + +import com.google.common.base.Strings; +import com.google.common.collect.Sets; +import com.olacabs.fabric.manager.dao.IComputationDAO; +import com.olacabs.fabric.manager.domain.ComputationDomain; + +/** + * Todo . + */ +public class ComputationDAO extends BaseDAO implements IComputationDAO { + + private final SessionFactory sessionFactory; + + public ComputationDAO(final SessionFactory sessionFactory) { + super(sessionFactory); + this.sessionFactory = sessionFactory; + } + + @Override + public ComputationDomain save(final ComputationDomain computation) { + return super.persist(computation); + } + + @Override + public ComputationDomain get(final int computationId) { + return super.get(computationId); + } + + @Override + public void modify(final ComputationDomain computation) { + super.update(computation); + } + + @Override + public void delete(final ComputationDomain computation) { + computation.setDeleted(true); + super.persist(computation); + } + + @Override + public Set search(final String tenant, final String name, final Integer version) { + final Session session = sessionFactory.getCurrentSession(); + final Criteria criteria = session.createCriteria(ComputationDomain.class); + criteria.add(Restrictions.eq("deleted", false)); + + criteria.addOrder(Order.desc("version")); + + if (!Strings.isNullOrEmpty(tenant)) { + criteria.add(Restrictions.eq("tenant", tenant)); + } + if (!Strings.isNullOrEmpty(name)) { + criteria.add(Restrictions.eq("name", name)); + } + if (version != null) { + criteria.add(Restrictions.eq("version", version)); + } + + final Set result = Sets.newHashSet(); + result.addAll(super.list(criteria)); + return result; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/GlobalPropertyDAO.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/GlobalPropertyDAO.java new file mode 100644 index 0000000..38acf8c --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/dao/impl/GlobalPropertyDAO.java @@ -0,0 +1,81 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.dao.impl; + +import java.util.Set; + +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.criterion.Restrictions; + +import com.google.common.base.Strings; +import com.google.common.collect.Sets; +import com.olacabs.fabric.manager.dao.IGlobalPropertyDAO; +import com.olacabs.fabric.manager.domain.GlobalPropertyDomain; +import com.olacabs.fabric.manager.exception.ResourceNotFoundException; + +import io.dropwizard.hibernate.AbstractDAO; + +/** + * Todo . + */ +public class GlobalPropertyDAO extends AbstractDAO implements IGlobalPropertyDAO { + + private final SessionFactory sessionFactory; + + public GlobalPropertyDAO(final SessionFactory sessionFactory) { + super(sessionFactory); + this.sessionFactory = sessionFactory; + } + + @Override + public GlobalPropertyDomain save(final GlobalPropertyDomain properties) { + return super.persist(properties); + } + + @Override + public Set search(final String name, final String propertyType) { + final Session session = sessionFactory.getCurrentSession(); + final Criteria criteria = session.createCriteria(GlobalPropertyDomain.class); + criteria.add(Restrictions.eq("deleted", false)); + + if (!Strings.isNullOrEmpty(name)) { + criteria.add(Restrictions.eq("name", name)); + } + + if (!Strings.isNullOrEmpty(propertyType)) { + criteria.add(Restrictions.eq("type", propertyType)); + } + return Sets.newHashSet(super.list(criteria)); + } + + @Override + public GlobalPropertyDomain get(final int id) { + final GlobalPropertyDomain property = super.get(id); + if (property.isDeleted()) { + throw new ResourceNotFoundException("Global property not found with id - " + id); + } + return property; + } + + @Override + public void delete(final GlobalPropertyDomain property) { + property.setDeleted(true); + super.persist(property); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ApplicationDomain.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ApplicationDomain.java new file mode 100644 index 0000000..96e9e1a --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ApplicationDomain.java @@ -0,0 +1,71 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.domain; + +import javax.persistence.*; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.olacabs.fabric.manager.bean.ExecutorConfig; +import com.olacabs.fabric.manager.bean.RuntimeOptions; + +import lombok.*; + +/** + * Application domain. + */ +@Getter +@Setter +@Entity +@Table(name = "applications") +@Access(AccessType.FIELD) +@JsonIgnoreProperties(ignoreUnknown = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ApplicationDomain extends TenantBaseDomain { + + private String name; + + @OneToOne + @JoinColumn(name = "computationId") + private ComputationDomain computation; + +// @Convert(converter = ExecutorConfigConverter.class) + private ExecutorConfig executorConfig; + +// @Convert(converter = RuntimeOptionsConverter.class) + private RuntimeOptions runtimeOptions; + + private Boolean active = true; + + private Integer instances; + + @JsonIgnore + public ApplicationDomain update(final ApplicationDomain application) { + if (application.getRuntimeOptions() != null) { + this.runtimeOptions = application.getRuntimeOptions(); + } + if (application.getActive() != null) { + this.active = application.getActive(); + } + if (application.getInstances() != null) { + this.instances = application.getInstances(); + } + return this; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/BaseDomain.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/BaseDomain.java new file mode 100644 index 0000000..82265de --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/BaseDomain.java @@ -0,0 +1,75 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.domain; + +import java.sql.Timestamp; + +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; + +import com.olacabs.fabric.manager.filter.UserContext; + +import lombok.Getter; +import lombok.Setter; + +/** + * Base domain . + */ +@MappedSuperclass +public class BaseDomain { + + @Id + @Getter + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int internalId; + + @Getter + @Setter + private String createdBy; + + @Getter + @Setter + private String updatedBy; + + @Getter + @Setter + private Timestamp createdAt = new Timestamp(System.currentTimeMillis()); + + @Getter + @Setter + private Timestamp updatedAt = new Timestamp(System.currentTimeMillis()); + + /** + * Sets created and updated timestamp before persisting. + */ + public void prePersist() { + final Timestamp currentTime = new Timestamp(System.currentTimeMillis()); + this.setCreatedAt(currentTime); + this.setUpdatedAt(currentTime); + this.setCreatedBy(UserContext.instance().getUser()); + } + + /** + * Sets created and updated timestamp before saveOrUpdate. + */ + public void preUpdate() { + this.setUpdatedBy(UserContext.instance().getUser()); + this.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ComponentDomain.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ComponentDomain.java new file mode 100644 index 0000000..0783b8d --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ComponentDomain.java @@ -0,0 +1,126 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.domain; + +import java.util.List; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +import org.hibernate.annotations.Where; +import org.hibernate.validator.constraints.NotEmpty; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import com.olacabs.fabric.manager.converter.ComponentSourceConverter; +import com.olacabs.fabric.manager.converter.JsonListConverter; +import com.olacabs.fabric.model.common.ComponentSource; +import com.olacabs.fabric.model.common.ComponentType; +import com.olacabs.fabric.model.processor.ProcessorType; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * Todo . + */ +@Entity +@Table(name = "components") +@Access(AccessType.FIELD) +@JsonIgnoreProperties(ignoreUnknown = true) +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +public class ComponentDomain extends BaseDomain { + + @NotNull + @NotEmpty + private String namespace; + + @NotNull + @NotEmpty + private String name; + + @NotNull + @NotEmpty + private String version; + + @JsonIgnore + @Where(clause = "deleted = 0") + private boolean deleted = false; + + @NotNull + @Enumerated(EnumType.STRING) + private ComponentType type = ComponentType.PROCESSOR; + + private String description; + + @Enumerated(EnumType.STRING) + private ProcessorType processorType = ProcessorType.EVENT_DRIVEN; + + @Convert(converter = JsonListConverter.class) + private List requiredProperties = Lists.newArrayList(); + + @Convert(converter = JsonListConverter.class) + private List optionalProperties = Lists.newArrayList(); + + private double cpu; + + private double memory; + + @NotNull + @Convert(converter = ComponentSourceConverter.class) + private ComponentSource source; + + @JsonIgnore + public ComponentDomain update(final ComponentDomain component) { + if (!Strings.isNullOrEmpty(component.getNamespace())) { + this.namespace = component.getNamespace(); + } + if (!Strings.isNullOrEmpty(component.getName())) { + this.name = component.getName(); + } + if (!Strings.isNullOrEmpty(component.getVersion())) { + this.version = component.getVersion(); + } + if (component.getVersion() != null) { + this.type = component.getType(); + } + if (!Strings.isNullOrEmpty(component.getDescription())) { + this.description = component.getDescription(); + } + if (component.getProcessorType() != null) { + this.processorType = component.getProcessorType(); + } + if (component.getRequiredProperties() != null) { + requiredProperties.addAll(component.getRequiredProperties()); + } + if (component.getOptionalProperties() != null) { + optionalProperties.addAll(component.getOptionalProperties()); + } + if (this.cpu > 0) { + this.cpu = component.getCpu(); + } + if (this.memory > 0) { + this.memory = component.getMemory(); + } + return this; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ComponentInstanceDomain.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ComponentInstanceDomain.java new file mode 100644 index 0000000..3638995 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ComponentInstanceDomain.java @@ -0,0 +1,92 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.domain; + +import java.util.Map; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.NotEmpty; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.collect.Maps; +import com.olacabs.fabric.model.common.ComponentType; + +import lombok.Getter; +import lombok.Setter; + +/** + * Todo . + */ +@Entity +@Table(name = "component_instances") +@Access(AccessType.FIELD) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ComponentInstanceDomain extends BaseDomain { + + @Getter + @Setter + @NotNull + @NotEmpty + private String id; + + @JsonBackReference + @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) + @JoinColumn(name = "computationId") + @Getter + @Setter + private ComputationDomain computation; + + @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) + @Getter + @Setter + @JoinColumn(name = "componentId") + @JsonProperty("meta") + private ComponentDomain component; + + @Transient + @NotNull + private int componentId; + + @JsonIgnore + @Getter + @Setter + @Enumerated(EnumType.STRING) + private ComponentType type = ComponentType.SOURCE; + + @Getter + @Setter + @ElementCollection(fetch = FetchType.EAGER) + @MapKeyColumn(name = "id") + @Column(name = "value") + @CollectionTable(name = "component_instance_properties", joinColumns = {@JoinColumn(name = "componentInstanceId")}) + private Map properties = Maps.newHashMap(); + + @JsonIgnore + public int getComponentId() { + return component != null ? component.getInternalId() : componentId; + } + + @JsonProperty + public void setComponentId(final int componentId) { + this.componentId = componentId; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ComputationDomain.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ComputationDomain.java new file mode 100644 index 0000000..2d2fd53 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ComputationDomain.java @@ -0,0 +1,138 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.domain; + +import java.util.Map; +import java.util.Set; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +import org.hibernate.annotations.Where; +import org.hibernate.validator.constraints.Email; +import org.hibernate.validator.constraints.NotEmpty; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonManagedReference; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + +import lombok.Getter; +import lombok.Setter; + +/** + * Todo . + */ +@Entity +@Table(name = "computations") +@Access(AccessType.FIELD) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ComputationDomain extends TenantBaseDomain { + + @NotNull + @NotEmpty + @Getter + @Setter + private String name; + + @NotNull + @Email + @Getter + @Setter + private String ownerEmail; + + @NotNull + @Getter + @Setter + private String description; + + @Getter + @ElementCollection(fetch = FetchType.EAGER) + @MapKeyColumn(name = "id") + @Column(name = "value") + @CollectionTable(name = "computation_attributes", joinColumns = {@JoinColumn(name = "computationId")}) + @Setter + private Map attributes = Maps.newHashMap(); + + @Getter + @NotNull + @Setter + @NotEmpty + @JsonManagedReference + @OrderBy(value = "id") + @OneToMany(mappedBy = "computation", cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @Where(clause = "type = 'SOURCE'") + private Set sources = Sets.newHashSet(); + + @NotNull + @NotEmpty + @Getter + @Setter + @JsonManagedReference + @OrderBy(value = "id") + @OneToMany(mappedBy = "computation", cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @Where(clause = "type = 'PROCESSOR'") + private Set processors = Sets.newHashSet(); + + @NotNull + @NotEmpty + @Getter + @Setter + @JsonManagedReference + @OneToMany(mappedBy = "computation", cascade = CascadeType.ALL, fetch = FetchType.EAGER) + private Set connections = Sets.newHashSet(); + + @Setter + @Getter + @ElementCollection(fetch = FetchType.EAGER) + @MapKeyColumn(name = "id") + @Column(name = "value") + @CollectionTable(name = "computation_properties", joinColumns = {@JoinColumn(name = "computationId")}) + private Map properties = Maps.newHashMap(); + + @JsonIgnore + @Getter + @Setter + private boolean deleted = false; + + @Getter + @Setter + private int version = 1; + + @JsonIgnore + public ComputationDomain update(final ComputationDomain computation) { + this.ownerEmail = computation.getOwnerEmail(); + this.description = computation.getDescription(); + if (computation.getAttributes() != null) { + this.attributes.putAll(computation.getAttributes()); + } + if (computation.getSources() != null) { + this.sources.addAll(computation.getSources()); + } + if (computation.getProcessors() != null) { + this.processors.addAll(computation.getProcessors()); + } + if (computation.getConnections() != null) { + this.connections.addAll(computation.getConnections()); + } + if (computation.getProperties() != null) { + this.properties.putAll(computation.getProperties()); + } + return this; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ConnectionDomain.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ConnectionDomain.java new file mode 100644 index 0000000..1982d29 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ConnectionDomain.java @@ -0,0 +1,61 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.domain; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.olacabs.fabric.model.common.ComponentType; + +import lombok.Getter; +import lombok.Setter; + +/** + * Todo . + */ +@Entity +@Table(name = "connections") +@Access(AccessType.FIELD) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ConnectionDomain extends BaseDomain { + + @JsonBackReference + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "computationId") + @Getter + @Setter + private ComputationDomain computation; + + @Enumerated(EnumType.STRING) + @NotNull + @Getter + @Setter + private ComponentType fromType; + + @Getter + @Setter + @JsonProperty("from") + private String fromLink; + + @Getter + @Setter + @JsonProperty("to") + private String toLink; +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/GlobalPropertyDomain.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/GlobalPropertyDomain.java new file mode 100644 index 0000000..e81b4db --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/GlobalPropertyDomain.java @@ -0,0 +1,61 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.domain; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import lombok.Getter; +import lombok.Setter; + +/** + * Todo . + */ +@Entity +@Table(name = "global_properties") +@Access(AccessType.FIELD) +@JsonIgnoreProperties(ignoreUnknown = true) +public class GlobalPropertyDomain { + + @Id + @Getter + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @Getter + @Setter + @Column(unique = true) + @NotNull + private String name; + + @Getter + @Setter + @NotNull + private String type = "default"; + + @Getter + @Setter + private String description; + + @JsonIgnore + @Getter + @Setter + private boolean deleted = false; +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/TenantBaseDomain.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/TenantBaseDomain.java new file mode 100644 index 0000000..3a86061 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/TenantBaseDomain.java @@ -0,0 +1,43 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.domain; + +import javax.persistence.MappedSuperclass; + +import lombok.Getter; +import lombok.Setter; + +/** + * Todo . + */ +@MappedSuperclass +class TenantBaseDomain extends BaseDomain { + + @Getter + @Setter + private String tenant; + + // @PrePersist + public void prePersist() { + super.prePersist(); + } + + // @PreUpdate + public void preUpdate() { + super.preUpdate(); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/FabricManagerException.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/FabricManagerException.java new file mode 100644 index 0000000..407959e --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/FabricManagerException.java @@ -0,0 +1,33 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.exception; + +/** + * Todo . + */ +public class FabricManagerException extends RuntimeException { + + private static final long serialVersionUID = 1L; + private static final String DEFAULT_MSG = "Something went wrong..."; + + /** + * @param cause to throw + */ + public FabricManagerException(final Throwable cause) { + super(cause.getMessage(), cause); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/ResourceNotFoundException.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/ResourceNotFoundException.java new file mode 100644 index 0000000..0d3d301 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/ResourceNotFoundException.java @@ -0,0 +1,44 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.exception; + +/** + * Todo . + */ +public class ResourceNotFoundException extends RuntimeException { + + private static final long serialVersionUID = 1L; + private static final String DEFAULT_MSG = "Resource Not Found"; + + public ResourceNotFoundException() { + super(DEFAULT_MSG); + } + + /** + * @param message to throw + */ + public ResourceNotFoundException(final String message) { + super(message); + } + + /** + * @param cause to throw + */ + public ResourceNotFoundException(final Throwable cause) { + super(DEFAULT_MSG, cause); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/UnProcessableException.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/UnProcessableException.java new file mode 100644 index 0000000..1dd2510 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/UnProcessableException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.exception; + +/** + * Todo . + */ +public class UnProcessableException extends RuntimeException { + + private static final long serialVersionUID = 1L; + private static final String DEFAULT_MSG = "Unable to process...Something invalid here ?"; + + public UnProcessableException() { + super(DEFAULT_MSG); + } + + /** + * @param message to throw + * @param cause to throw + */ + public UnProcessableException(final String message, final Throwable cause) { + super(message, cause); + } + + /** + * @param message to throw + */ + public UnProcessableException(final String message) { + super(message); + } + + /** + * @param cause to throw + */ + public UnProcessableException(final Throwable cause) { + super(DEFAULT_MSG, cause); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/mapper/RuntimeExceptionMapper.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/mapper/RuntimeExceptionMapper.java new file mode 100644 index 0000000..db8fc56 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/mapper/RuntimeExceptionMapper.java @@ -0,0 +1,66 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.exception.mapper; + +import javax.validation.ConstraintViolationException; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.olacabs.fabric.manager.exception.ResourceNotFoundException; +import com.olacabs.fabric.manager.exception.UnProcessableException; + +import lombok.extern.slf4j.Slf4j; + +/** + * Todo . + */ +@Slf4j +public class RuntimeExceptionMapper implements ExceptionMapper { + + private static final int UN_PROCESSABLE_STATUS = 422; + + @Override + public Response toResponse(final RuntimeException e) { + + final Response defaultResponse = + Response.serverError().entity(ImmutableMap.of("errors", ImmutableList.of(e.getMessage()))).build(); + + log.error("Error - {}", e.getMessage()); + + if (e instanceof ResourceNotFoundException) { + return Response.status(Response.Status.NOT_FOUND) + .entity(ImmutableMap.of("errors", ImmutableList.of(e.getMessage()))).build(); + } else if (e instanceof ConstraintViolationException) { + return Response.status(UN_PROCESSABLE_STATUS) + .entity(ImmutableMap.of("errors", ImmutableList.of(e.getMessage()))).build(); + } else if (e instanceof IllegalArgumentException) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(ImmutableMap.of("errors", ImmutableList.of(e.getMessage()))).build(); + } else if (e instanceof UnProcessableException) { + return Response.status(UN_PROCESSABLE_STATUS) + .entity(ImmutableMap.of("errors", ImmutableList.of(e.getMessage()))).build(); + } else if (e instanceof org.hibernate.exception.ConstraintViolationException) { + return Response.status(UN_PROCESSABLE_STATUS) + .entity(ImmutableMap.of("errors", ImmutableList.of(e.getMessage()))).build(); + } + + log.error("Stack trace - ", e); + return defaultResponse; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/Context.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/Context.java new file mode 100644 index 0000000..46b27da --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/Context.java @@ -0,0 +1,29 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.filter; + +import lombok.Getter; +import lombok.Setter; + +/** + * Context. + */ +class Context { + @Getter + @Setter + private String item; +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/UserContext.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/UserContext.java new file mode 100644 index 0000000..0f25b7f --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/UserContext.java @@ -0,0 +1,50 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.filter; + +/** + * Todo . + */ +public final class UserContext { + + private static final UserContext INSTANCE = new UserContext(); + + private ThreadLocal contextThreadLocal = new ThreadLocal<>(); + + private UserContext() {} + + public static UserContext instance() { + return INSTANCE; + } + + void clear() { + this.contextThreadLocal.remove(); + } + + Context getContextThreadLocal() { + Context context = this.contextThreadLocal.get(); + if (context == null) { + context = new Context(); + this.contextThreadLocal.set(context); + } + return context; + } + + public String getUser() { + return getContextThreadLocal().getItem(); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/UserFilter.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/UserFilter.java new file mode 100644 index 0000000..50ddb2d --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/UserFilter.java @@ -0,0 +1,59 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.filter; + +import java.io.IOException; + +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; + +import com.google.common.base.Strings; +import com.olacabs.fabric.manager.exception.UnProcessableException; + +import lombok.extern.slf4j.Slf4j; + +/** + * Todo . + */ +@UserRequired +@Slf4j +public class UserFilter implements ContainerRequestFilter, ContainerResponseFilter { + + static final String X_USER = "X-User"; + + @Override + public void filter(final ContainerRequestContext requestContext) throws IOException { + final Context context = UserContext.instance().getContextThreadLocal(); + final String userKey = requestContext.getHeaderString(X_USER); + log.debug(X_USER + " - {}", userKey); + + if (Strings.isNullOrEmpty(userKey)) { + log.error("X-User: {}, X-User can't be null/empty", userKey); + throw new UnProcessableException("X-User can't be null/empty, X-USER: " + userKey); + } + context.setItem(userKey); + } + + @Override + public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) + throws IOException { + log.trace("Clearing the user context information for the request {}", responseContext); + UserContext.instance().clear(); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/UserRequired.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/UserRequired.java new file mode 100644 index 0000000..c635e8f --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/filter/UserRequired.java @@ -0,0 +1,30 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.filter; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.ws.rs.NameBinding; + +/** + * Todo . + */ +@NameBinding +@Retention(RetentionPolicy.RUNTIME) +public @interface UserRequired { +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/managed/OpenTsdbMetricReporter.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/managed/OpenTsdbMetricReporter.java new file mode 100644 index 0000000..e5c5408 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/managed/OpenTsdbMetricReporter.java @@ -0,0 +1,101 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.managed; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.concurrent.TimeUnit; + +import com.codahale.metrics.MetricRegistry; +import com.github.sps.metrics.OpenTsdbReporter; +import com.github.sps.metrics.opentsdb.OpenTsdb; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMap; +import com.olacabs.fabric.manager.config.ManagerConfig; +import com.olacabs.fabric.manager.config.OpenTsdbConfig; + +import io.dropwizard.lifecycle.Managed; +import lombok.extern.slf4j.Slf4j; + +/** + * Todo . + */ +@Slf4j +public class OpenTsdbMetricReporter implements Managed { + + private final OpenTsdbConfig openTsdbConfig; + private final MetricRegistry metricRegistry; + + private OpenTsdbReporter reporter; + private String host; + + public OpenTsdbMetricReporter(final ManagerConfig managerConfig, final MetricRegistry metricRegistry) { + this.openTsdbConfig = managerConfig.getOpenTsdbConfig(); + this.host = managerConfig.getServiceDiscovery().getHostname(); + if (Strings.isNullOrEmpty(host)) { + try { + host = InetAddress.getLocalHost().getCanonicalHostName(); + } catch (final UnknownHostException ignore) { + log.error("Unable to get the hostname...", ignore); + host = "localhost"; + } + } + this.metricRegistry = metricRegistry; + } + + @Override + public void start() throws Exception { + if (!openTsdbConfig.isEnabled()) { + log.info("OpenTSDB reporter is disabled..."); + return; + } + + final ImmutableMap.Builder tagMapBuilder = ImmutableMap.builder(); + final String appName = openTsdbConfig.getAppName(); + final String namespace = openTsdbConfig.getNamespace(); + final String module = openTsdbConfig.getPlatform(); + + Preconditions.checkArgument(!Strings.isNullOrEmpty(appName), "Please provide non empty app name"); + Preconditions.checkArgument(!Strings.isNullOrEmpty(host), "Please provide non empty host name"); + + tagMapBuilder.put("host", host); + tagMapBuilder.put("service", appName); + + if (Strings.isNullOrEmpty(namespace)) { + tagMapBuilder.put("namespace", namespace); + } + + if (Strings.isNullOrEmpty(module)) { + tagMapBuilder.put("module", module); + } + + this.reporter = OpenTsdbReporter.forRegistry(metricRegistry).prefixedWith(appName) + .withTags(tagMapBuilder.build()).build(OpenTsdb.forService(openTsdbConfig.getOpenTsdbUrl()).create()); + + this.reporter.start(openTsdbConfig.getPeriodInSeconds(), TimeUnit.SECONDS); + log.info("OpenTSDB reporter started..."); + } + + @Override + public void stop() throws Exception { + if (openTsdbConfig.isEnabled()) { + reporter.stop(); + log.info("OpenTSDB reporter stopped..."); + } + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/managed/ServiceFinder.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/managed/ServiceFinder.java new file mode 100644 index 0000000..92cf584 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/managed/ServiceFinder.java @@ -0,0 +1,74 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.managed; + +import java.io.IOException; +import java.util.List; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.flipkart.ranger.ServiceFinderBuilders; +import com.flipkart.ranger.finder.sharded.SimpleShardedServiceFinder; +import com.flipkart.ranger.model.ServiceNode; +import com.olacabs.fabric.manager.bean.ShardInfo; +import com.olacabs.fabric.manager.config.ServiceDiscoveryConfig; + +import io.dropwizard.lifecycle.Managed; +import lombok.extern.slf4j.Slf4j; + +/** + * Todo . + */ +@Slf4j +public class ServiceFinder implements Managed { + + private final ObjectMapper mapper; + private final ServiceDiscoveryConfig registryConfig; + private SimpleShardedServiceFinder serviceFinder; + + public ServiceFinder(final ObjectMapper mapper, final ServiceDiscoveryConfig registryConfig) { + this.mapper = mapper; + this.registryConfig = registryConfig; + } + + @Override + public void start() throws Exception { + this.serviceFinder = ServiceFinderBuilders.shardedFinderBuilder() + .withConnectionString(registryConfig.getZkConnectionString()) + .withNamespace(registryConfig.getNamespace()).withServiceName(registryConfig.getServiceName()) + .withDeserializer(data -> { + try { + return mapper.readValue(data, new TypeReference>() {}); + } catch (final IOException ignore) { + log.error("Error - ", ignore); + } + return null; + }).build(); + this.serviceFinder.start(); + log.info("Started service finder..."); + } + + @Override + public void stop() throws Exception { + this.serviceFinder.stop(); + log.info("Stopped service finder..."); + } + + public List> getAllNodes() { + return serviceFinder.getAll(new ShardInfo(registryConfig.getEnvironment())); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/managed/ServiceRegistry.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/managed/ServiceRegistry.java new file mode 100644 index 0000000..2313e59 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/managed/ServiceRegistry.java @@ -0,0 +1,107 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.managed; + +import java.net.InetAddress; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.flipkart.ranger.ServiceProviderBuilders; +import com.flipkart.ranger.healthcheck.HealthcheckStatus; +import com.flipkart.ranger.serviceprovider.ServiceProvider; +import com.google.common.base.Strings; +import com.olacabs.fabric.manager.bean.ShardInfo; +import com.olacabs.fabric.manager.config.ServiceDiscoveryConfig; + +import io.dropwizard.Configuration; +import io.dropwizard.jetty.HttpConnectorFactory; +import io.dropwizard.lifecycle.Managed; +import io.dropwizard.server.SimpleServerFactory; +import lombok.extern.slf4j.Slf4j; + +/** + * Todo . + */ +@Slf4j +public class ServiceRegistry implements Managed { + + private final ObjectMapper mapper; + private final ServiceDiscoveryConfig registryConfig; + private final String host; + private final int port; + private ServiceProvider serviceProvider; + + public ServiceRegistry(final ObjectMapper objectMapper, final Configuration dropwizardConfiguration, + final ServiceDiscoveryConfig registryConfig) throws Exception { + this.mapper = objectMapper; + this.registryConfig = registryConfig; + this.host = Strings.isNullOrEmpty(registryConfig.getHostname()) ? getHost() : registryConfig.getHostname(); + this.port = 0 >= registryConfig.getPort() ? getPort(dropwizardConfiguration) : registryConfig.getPort(); + } + + @Override + public void start() throws Exception { + // Register + this.serviceProvider = ServiceProviderBuilders.shardedServiceProviderBuilder() + .withConnectionString(registryConfig.getZkConnectionString()) + .withNamespace(registryConfig.getNamespace()).withServiceName(registryConfig.getServiceName()) + .withSerializer(data -> { + try { + return mapper.writeValueAsBytes(data); + } catch (final JsonProcessingException ignore) { + log.error("Error - ", ignore); + } + return null; + }).withHostname(host).withPort(port).withNodeData(new ShardInfo(registryConfig.getEnvironment())) + .withHealthcheck(() -> HealthcheckStatus.healthy).buildServiceDiscovery(); + + // Start + this.serviceProvider.start(); + log.info( + "Service registered to ranger with namespace - '{}', service - '{}', " + + "host - '{}', port - '{}', environment - '{}'", + registryConfig.getNamespace(), registryConfig.getServiceName(), host, port, + registryConfig.getEnvironment()); + } + + @Override + public void stop() throws Exception { + // Stop + this.serviceProvider.stop(); + log.info("Service registry stopped..."); + } + + /* + * @return host + */ + private String getHost() throws Exception { + return InetAddress.getLocalHost().getHostAddress(); + } + + /* + * @return port + */ + private int getPort(Configuration config) { + int httpPort = 0; + final SimpleServerFactory serverFactory = (SimpleServerFactory) config.getServerFactory(); + final HttpConnectorFactory connector = (HttpConnectorFactory) serverFactory.getConnector(); + if (connector.getClass().isAssignableFrom(HttpConnectorFactory.class)) { + httpPort = connector.getPort(); + } + return httpPort; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ApplicationResource.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ApplicationResource.java new file mode 100644 index 0000000..0db44a4 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ApplicationResource.java @@ -0,0 +1,186 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.resource; + +import com.codahale.metrics.annotation.Timed; +import com.google.common.base.Preconditions; +import com.olacabs.fabric.manager.bean.ExecutorConfig; +import com.olacabs.fabric.manager.bean.RuntimeOptions; +import com.olacabs.fabric.manager.domain.ApplicationDomain; +import com.olacabs.fabric.manager.domain.ComputationDomain; +import com.olacabs.fabric.manager.exception.ResourceNotFoundException; +import com.olacabs.fabric.manager.filter.UserRequired; +import com.olacabs.fabric.manager.service.IApplicationService; +import com.olacabs.fabric.manager.service.IComputationService; +import com.wordnik.swagger.annotations.Api; +import com.wordnik.swagger.annotations.ApiOperation; +import io.dropwizard.hibernate.UnitOfWork; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.Map; +import java.util.Set; + +/** + * Todo . + */ +@Produces(MediaType.APPLICATION_JSON) +@Path("/v1/applications") +@Slf4j +@AllArgsConstructor +@Api("/v1/applications") +public class ApplicationResource { + + private final IApplicationService applicationService; + private final IComputationService computationService; + private final ExecutorConfig executorConfig; + + @POST + @UserRequired + @Consumes(MediaType.APPLICATION_JSON) + @Timed + @UnitOfWork + @Path("{tenant}/{name}") + @ApiOperation(value = "Creates and deploys an application for a computation given tenant and name", + response = ApplicationDomain.class) + public Response create(@PathParam("tenant") final String tenant, @PathParam("name") final String computationName, + @QueryParam("version") final Integer computationVersion, + @NotNull final RuntimeOptions runtimeOptions) { + + final ComputationDomain computation = search(tenant, computationName, computationVersion); + if (!runtimeOptions.getExecutorDockerImage().isEmpty()) { + executorConfig.setExecutorDockerImage(runtimeOptions.getExecutorDockerImage()); + } + + computation.setTenant(tenant); + final ApplicationDomain createdApp = create(runtimeOptions, executorConfig, computation); + return Response.status(Response.Status.CREATED).entity(createdApp).build(); + } + + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Timed + @UnitOfWork(transactional = false) + @Path("{tenant}/{name}") + @ApiOperation(value = "Get application(only metadata from db)", response = ApplicationDomain.class) + public Response get(@PathParam("tenant") final String tenant, @PathParam("name") final String computationName) { + final String appName = applicationService.name(tenant, computationName); + final ApplicationDomain applicationDomain = applicationService.get(appName, tenant); + return Response.ok().entity(applicationDomain).build(); + } + + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Timed + @UnitOfWork(transactional = false) + @Path("{tenant}/{name}/marathon") + @ApiOperation(value = "Get application details from marathon", response = Map.class) + public Response getFromMarathon(@PathParam("tenant") final String tenant, + @PathParam("name") final String computationName) { + final String appName = applicationService.name(tenant, computationName); + final Map result = applicationService.getAppFromDeploymentEnv(appName); + return Response.ok().entity(result).build(); + } + + @DELETE + @Consumes(MediaType.APPLICATION_JSON) + @Timed + @UserRequired + @UnitOfWork + @Path("{tenant}/{name}") + @ApiOperation(value = "Delete application details from marathon and soft deletes the meta") + public Response delete(@PathParam("tenant") final String tenant, @PathParam("name") final String computationName) { + final String appName = applicationService.name(tenant, computationName); + applicationService.delete(appName, tenant); + return Response.ok().build(); + } + + @PUT + @Consumes(MediaType.APPLICATION_JSON) + @Timed + @UserRequired + @UnitOfWork + @Path("{tenant}/{name}/scale") + @ApiOperation(value = "Scales application on marathon") + public Response scale(@PathParam("tenant") final String tenant, @PathParam("name") final String computationName, + @NotNull final Map request) { + final Integer instances = request.get("instances"); + Preconditions.checkNotNull(instances, "No of instances can't be null"); + Preconditions.checkArgument(instances > 0, "Num of instances should be greater than zero", computationName); + final String appName = applicationService.name(tenant, computationName); + applicationService.scale(appName, tenant, instances); + return Response.noContent().build(); + } + + @PUT + @Consumes(MediaType.APPLICATION_JSON) + @Timed + @UserRequired + @UnitOfWork + @Path("{tenant}/{name}/suspend") + @ApiOperation(value = "Suspends application on marathon") + public Response suspend(@PathParam("tenant") final String tenant, @PathParam("name") final String computationName) { + final String appName = applicationService.name(tenant, computationName); + applicationService.scale(appName, tenant, 0); + return Response.noContent().build(); + } + + @PUT + @Consumes(MediaType.APPLICATION_JSON) + @Timed + @UnitOfWork + @UserRequired + @Path("{tenant}/{name}/restart") + @ApiOperation(value = "Restart application on marathon") + public Response restart(@PathParam("tenant") final String tenant, @PathParam("name") final String computationName, + @QueryParam("forcefully") @DefaultValue("false") final boolean forcefully) { + final String appName = applicationService.name(tenant, computationName); + applicationService.restart(appName, tenant, forcefully); + return Response.noContent().build(); + } + + /* + * Search computation + */ + private ComputationDomain search(final String tenant, final String name, final Integer version) { + final Set computations = computationService.search(tenant, name, version); + if (computations.isEmpty()) { + throw new ResourceNotFoundException( + String.format("No computation found with name %s, for tenant %s", name, tenant)); + } + return computations.iterator().next(); + } + + /* + * create application + */ + private ApplicationDomain create(final RuntimeOptions runtimeOptions, final ExecutorConfig execConf, + final ComputationDomain computation) { + final ApplicationDomain application = new ApplicationDomain(); + application.setComputation(computation); + application.setExecutorConfig(execConf); + application.setInstances(runtimeOptions.getInstances()); + application.setRuntimeOptions(runtimeOptions); + application.setName(applicationService.name(computation.getTenant(), computation.getName())); + application.setTenant(computation.getTenant()); + return applicationService.create(application, computation.getTenant(), runtimeOptions.getInstances()); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ComponentResource.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ComponentResource.java new file mode 100644 index 0000000..5fb6900 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ComponentResource.java @@ -0,0 +1,195 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.resource; + +import com.codahale.metrics.annotation.Timed; +import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import com.olacabs.fabric.compute.builder.impl.ArtifactoryJarPathResolver; +import com.olacabs.fabric.compute.builder.impl.JarScanner; +import com.olacabs.fabric.manager.bean.ArtifactoryRegistrationRequest; +import com.olacabs.fabric.manager.bean.ComponentVersions; +import com.olacabs.fabric.manager.domain.ComponentDomain; +import com.olacabs.fabric.manager.filter.UserRequired; +import com.olacabs.fabric.manager.service.IComponentService; +import com.olacabs.fabric.model.common.ComponentMetadata; +import com.olacabs.fabric.model.common.ComponentType; +import com.olacabs.fabric.model.common.sources.ArtifactoryComponentSource; +import com.olacabs.fabric.model.common.sources.JarComponentSource; +import com.wordnik.swagger.annotations.Api; +import com.wordnik.swagger.annotations.ApiOperation; +import io.dropwizard.hibernate.UnitOfWork; +import lombok.AllArgsConstructor; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * Components resource. + */ +@AllArgsConstructor +@Produces(MediaType.APPLICATION_JSON) +@Path("/v1/components") +@Api("/v1/components") +public class ComponentResource { + + private final IComponentService service; + private final String artifactoryPath; + private final JarScanner scanner; + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Timed + @UnitOfWork + @UserRequired + @ApiOperation(value = "Save computation", response = ComponentDomain.class) + public Response save(@NotNull @Valid final ComponentDomain component) { + final ComponentDomain savedComponent = service.save(component); + return Response.status(Response.Status.CREATED).entity(savedComponent).build(); + } + + @GET + @Path("/versions") + @Timed + @UnitOfWork(transactional = false) + @ApiOperation(value = "Get all computation grouped by version", response = ComponentDomain.class) + public Response getAllGroupedByVersion(@QueryParam("namespace") final String namespace, + @QueryParam("name") final String name) { + return Response.ok().entity(ComponentVersions.resolve(service.search(namespace, name, null))).build(); + } + + @GET + @Path("/{namespace}/{name}/{version}") + @Timed + @UnitOfWork(transactional = false) + @ApiOperation(value = "Get component based on namespace, name and version", response = ComponentDomain.class) + public Response get(@PathParam("namespace") final String namespace, @PathParam("name") final String name, + @PathParam("version") final String version) { + final Set components = service.search(namespace, name, version); + if (components.isEmpty()) { + throw new NotFoundException(String.format("Component with namespace: %s, name: %s, version: %s not found", + namespace, name, version)); + } + return Response.ok().entity(components.iterator().next()).build(); + } + + @GET + @Timed + @UnitOfWork(transactional = false) + @ApiOperation(value = "Searches component based on param", response = Set.class) + public Response search(@QueryParam("namespace") final String namespace, @QueryParam("name") final String name, + @QueryParam("version") final String version) { + return Response.ok().entity(service.search(namespace, name, version)).build(); + } + + @GET + @Path("/{id}") + @UnitOfWork(transactional = false) + @ApiOperation(value = "Get component by id", response = ComponentDomain.class) + public Response get(@PathParam("id") final int internalId) { + return Response.ok().entity(service.get(internalId)).build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Path("/register") + @Timed + @UnitOfWork + @UserRequired + @ApiOperation(value = "Registers a processor/source jar from url", response = List.class) + public Response register(@Context final UriInfo uriinfo, @QueryParam("url") final String url) throws Exception { + final List registeredComponents = Lists.newArrayList(); + final List scanResults = + scanner.loadJars(Collections.singletonList(url), this.getClass().getClassLoader()); + scanResults.stream().map(JarScanner.ScanResult::getMetadata).forEach((componentMetadata) -> { + final ComponentDomain component = transform(componentMetadata); + component.setSource(JarComponentSource.builder().url(url).build()); + registeredComponents.add(service.save(component)); + }); + + final URI uri = (!registeredComponents.isEmpty() && registeredComponents.size() < 2) + ? uriinfo.getBaseUriBuilder().path("v1/components") + .path(String.valueOf(registeredComponents.get(0).getInternalId())).build() + : uriinfo.getBaseUriBuilder().path("v1/components").build(); + + return Response.created(uri).status(Response.Status.CREATED).entity(registeredComponents).build(); + } + + @UserRequired + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Path("/artifact") + @Timed + @UnitOfWork + @ApiOperation(value = "Registers a processor/source jar from artifactory", response = List.class) + public Response registerFromArtifactory(@Context UriInfo uriinfo, + @NotNull final ArtifactoryRegistrationRequest request) throws Exception { + final List registeredComponents = Lists.newArrayList(); + if (Strings.isNullOrEmpty(request.getArtifactory())) { + request.setArtifactory(artifactoryPath); + } + + final String url = ArtifactoryJarPathResolver.resolve(request.getArtifactory(), request.getGroupId(), + request.getArtifactId(), request.getVersion()); + final List scanResults = + scanner.loadJars(Collections.singletonList(url), this.getClass().getClassLoader()); + scanResults.stream().map(JarScanner.ScanResult::getMetadata).forEach((componentMetadata) -> { + final ComponentDomain component = transform(componentMetadata); + component.setSource(ArtifactoryComponentSource.builder().artifactoryUrl(request.getArtifactory()) + .groupId(request.getGroupId()).artifactId(request.getArtifactId()).version(request.getVersion()) + .build()); + registeredComponents.add(service.save(component)); + }); + + final URI uri = (!registeredComponents.isEmpty() && registeredComponents.size() < 2) + ? uriinfo.getBaseUriBuilder().path("v1/components") + .path(String.valueOf(registeredComponents.get(0).getInternalId())).build() + : uriinfo.getBaseUriBuilder().path("v1/components").build(); + + return Response.created(uri).status(Response.Status.CREATED).entity(registeredComponents).build(); + } + + /* + * Transform from model to component domain + */ + private ComponentDomain transform(final ComponentMetadata metadata) { + final ComponentDomain component = new ComponentDomain(); + component.setCpu(metadata.getCpu()); + component.setDescription(metadata.getDescription()); + component.setMemory(metadata.getMemory()); + component.setName(metadata.getName()); + component.setVersion(metadata.getVersion()); + component.setNamespace(metadata.getNamespace()); + component.setOptionalProperties(metadata.getOptionalProperties()); + component.setType(metadata.getType()); + component.setProcessorType( + Objects.equals(component.getType(), ComponentType.PROCESSOR) ? metadata.getProcessorType() : null); + component.setRequiredProperties(metadata.getRequiredProperties()); + component.setSource(metadata.getSource()); + return component; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ComputationResource.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ComputationResource.java new file mode 100644 index 0000000..3e60e80 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ComputationResource.java @@ -0,0 +1,143 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.resource; + +import com.codahale.metrics.annotation.Timed; +import com.google.common.collect.Sets; +import com.olacabs.fabric.manager.domain.ComputationDomain; +import com.olacabs.fabric.manager.exception.ResourceNotFoundException; +import com.olacabs.fabric.manager.filter.UserRequired; +import com.olacabs.fabric.manager.service.IComputationService; +import com.wordnik.swagger.annotations.Api; +import com.wordnik.swagger.annotations.ApiOperation; +import io.dropwizard.hibernate.UnitOfWork; +import lombok.AllArgsConstructor; + +import javax.validation.Valid; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Computation resource. + */ +@AllArgsConstructor +@Produces(MediaType.APPLICATION_JSON) +@Path("/v1/computations") +@Api("/v1/computations") +public class ComputationResource { + + private final IComputationService service; + + @UserRequired + @POST + @Timed + @Consumes(MediaType.APPLICATION_JSON) + @UnitOfWork + @Path("{tenant}") + @ApiOperation(value = "Save/update computation, basically creates a new version", + response = ComputationDomain.class) + public Response saveOrUpdate(@PathParam("tenant") final String tenant, @Valid final ComputationDomain computation) { + final ComputationDomain result = service.saveOrUpdate(tenant, computation); + return Response.status(Response.Status.CREATED).entity(result).build(); + } + + @GET + @Timed + @UnitOfWork(transactional = false) + @Path("{tenant}/{name}") + @ApiOperation(value = "Get latest computation based on name and version(optional)", + response = ComputationDomain.class) + public Response getLatestByName(@PathParam("tenant") final String tenant, @PathParam("name") final String name, + @QueryParam("version") final Integer version) { + + final Set computations = service.search(tenant, name, version); + if (computations.isEmpty()) { + throw new ResourceNotFoundException("Computation Not found"); + } + return Response + .ok() + .entity(version == null ? fetchLatest(computations) : computations.iterator().next()) + .build(); + } + + @GET + @Timed + @UnitOfWork(transactional = false) + @Path("{tenant}") + @ApiOperation(value = "Search computation based on params", response = List.class) + public Response search(@PathParam("tenant") final String tenant, + @QueryParam("name") final String name, + @QueryParam("version") final Integer version, + @QueryParam("latest") @DefaultValue("true") final Boolean latest) { + + Set computations = service.search(tenant, name, version); + if (computations.isEmpty()) { + throw new ResourceNotFoundException("Computation Not found"); + } + + if (latest) { + final Set latestComputations = Sets.newHashSet(); + computations.stream() + .collect(Collectors.groupingBy(ComputationDomain::getName)) + .entrySet() + .stream() + .forEach(entry -> { + latestComputations.add(fetchLatest(Sets.newHashSet(entry.getValue()))); + }); + computations = latestComputations; + } + + return Response.ok().entity(computations).build(); + } + + @DELETE + @Timed + @Path("{tenant}/{internalId}") + @UnitOfWork + @UserRequired + @ApiOperation(value = "Soft delete computation") + public Response delete(@PathParam("tenant") final String tenant, @PathParam("internalId") final int id) { + service.delete(tenant, id); + return Response.ok().build(); + } + + @GET + @Timed + @Path(("{tenant}/id/{internalId}")) + @UnitOfWork(transactional = false) + public Response get(@PathParam("tenant") final String tenant, @PathParam("internalId") final int id) { + return Response.ok().entity(service.getById(tenant, id)).build(); + } + + /* + * TODO - fix with cleaner solution Fetches the latest + */ + private ComputationDomain fetchLatest(final Set computations) { + ComputationDomain result = new ComputationDomain(); + result.setVersion(0); + for (final ComputationDomain computation : computations) { + if (computation.getVersion() > result.getVersion()) { + result = computation; + } + } + return result; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/GlobalPropertyResource.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/GlobalPropertyResource.java new file mode 100644 index 0000000..53300e8 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/GlobalPropertyResource.java @@ -0,0 +1,81 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.resource; + +import com.codahale.metrics.annotation.Timed; +import com.olacabs.fabric.manager.domain.GlobalPropertyDomain; +import com.olacabs.fabric.manager.service.IGlobalPropertyService; +import com.wordnik.swagger.annotations.Api; +import com.wordnik.swagger.annotations.ApiOperation; +import io.dropwizard.hibernate.UnitOfWork; +import lombok.AllArgsConstructor; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.Set; + +/** + * Todo . + */ +@AllArgsConstructor +@Produces(MediaType.APPLICATION_JSON) +@Path("/v1/global/properties") +@Api("/v1/global/properties") +public class GlobalPropertyResource { + + private IGlobalPropertyService service; + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Timed + @UnitOfWork + @ApiOperation(value = "Save global property", response = GlobalPropertyDomain.class) + public Response save(@NotNull @Valid final GlobalPropertyDomain globalProperty) { + final GlobalPropertyDomain propertyDomain = service.save(globalProperty); + return Response.status(Response.Status.CREATED).entity(propertyDomain).build(); + } + + @GET + @Timed + @UnitOfWork(transactional = false) + @Path("{id}") + @ApiOperation(value = "Get global property by id", response = GlobalPropertyDomain.class) + public Response get(@PathParam("id") final int id) { + return Response.ok().entity(service.get(id)).build(); + } + + @GET + @Timed + @UnitOfWork(transactional = false) + @ApiOperation(value = "Search global property based on name, param", response = Set.class) + public Response search(@QueryParam("name") final String name, @QueryParam("type") final String propertyType) { + return Response.ok().entity(service.search(name, propertyType)).build(); + } + + @DELETE + @Timed + @UnitOfWork + @Path("{id}") + @ApiOperation(value = "Soft delete") + public Response delete(@PathParam("id") final int id) { + service.delete(id); + return Response.ok().build(); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ServiceRegistryResource.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ServiceRegistryResource.java new file mode 100644 index 0000000..a22ed05 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/resource/ServiceRegistryResource.java @@ -0,0 +1,52 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.resource; + +import java.util.List; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import com.codahale.metrics.annotation.Timed; +import com.google.common.collect.ImmutableMap; +import com.olacabs.fabric.manager.managed.ServiceFinder; +import com.wordnik.swagger.annotations.Api; +import com.wordnik.swagger.annotations.ApiOperation; + +import lombok.AllArgsConstructor; + +/** + * Todo . + */ +@AllArgsConstructor +@Produces(MediaType.APPLICATION_JSON) +@Path("/instances") +@Api("/instances") +public class ServiceRegistryResource { + + private ServiceFinder finder; + + @GET + @Timed + @ApiOperation(value = "Returns all service nodes registered for service discovery", response = List.class) + public Response getNodeDetails() { + return Response.ok().entity(ImmutableMap.of("nodes", finder.getAllNodes())).build(); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IApplicationService.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IApplicationService.java new file mode 100644 index 0000000..80af468 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IApplicationService.java @@ -0,0 +1,106 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.service; + +import java.util.Map; + +import com.olacabs.fabric.manager.domain.ApplicationDomain; + +import mesosphere.marathon.client.Marathon; + +/** + * Todo . + */ +public interface IApplicationService { + + /** + * Get the app name. + * + * @param tenant :: + * @param name :: computation name + * @return name + */ + String name(final String tenant, final String name); + + /** + * Persist and deploys the app. + * + * @param application :: + * @param tenant :: + * @param instances :: + */ + ApplicationDomain create(final ApplicationDomain application, final String tenant, final int instances); + + /** + * Soft delete from db and deletes from marathon. + * + * @param appName :: + * @param tenant :: + */ + void delete(final String appName, final String tenant); + + /** + * Get application from db. + * + * @param appName :: + * @param tenant :: + * @return App domain + */ + ApplicationDomain get(final String appName, final String tenant); + + /** + * Get app from deployed env (marathon). + * + * @param appName :: + * @return response + */ + Map getAppFromDeploymentEnv(final String appName); + + /** + * Scale the app. + * + * @param appName :: + * @param tenant :: + * @param scaleTo :: + */ + void scale(final String appName, final String tenant, final int scaleTo); + + /** + * Updates the app. + * + * @param appName :: + * @param tenant :: + * @param updateParam :: + */ + void update(final String appName, final String tenant, final ApplicationDomain updateParam); + + /** + * Restarts the app. + * + * @param appName :: + * @param tenant :: + * @param forcefully :: + */ + void restart(final String appName, final String tenant, final boolean forcefully); + + /** + * Get marathon client. + * + * @return marathon + */ + Marathon getMarathon(); +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IComponentService.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IComponentService.java new file mode 100644 index 0000000..4f742b0 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IComponentService.java @@ -0,0 +1,70 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.service; + +import java.util.Set; + +import com.olacabs.fabric.manager.domain.ComponentDomain; + +/** + * Todo . + */ +public interface IComponentService { + + /** + * Saves Component. + * + * @param component to saveOrUpdate + * @return component + */ + ComponentDomain save(final ComponentDomain component); + + /** + * Search Component. + * + * @param namespace to search + * @param name to search + * @param version to search + * @return set of components + */ + Set search(final String namespace, final String name, final String version); + + /** + * Read by id. + * + * @param id to read + * @return component + */ + ComponentDomain get(final int id); + + /** + * Update component. + * + * @param id to saveOrUpdate + * @param component to saveOrUpdate + */ + void update(final int id, final ComponentDomain component); + + /** + * Delete Component. + * + * @param namespace to deleteApp + * @param name to deleteApp + * @param version to deleteApp + */ + void delete(final String namespace, final String name, final String version); +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IComputationService.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IComputationService.java new file mode 100644 index 0000000..53f87f9 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IComputationService.java @@ -0,0 +1,61 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.service; + +import java.util.Set; +import com.olacabs.fabric.manager.domain.ComputationDomain; + +/** + * Todo . + */ +public interface IComputationService { + + /** + * saveOrUpdate computation. + * + * @param tenant :: + * @param computation :: + * @return created entity + */ + ComputationDomain saveOrUpdate(final String tenant, final ComputationDomain computation); + + /** + * Gets entity by id. + * + * @param tenant :: + * @param id :: + * @return fetched computation + */ + ComputationDomain getById(final String tenant, final int id); + + /** + * Search. + * + * @param tenant :: + * @param name :: + * @return set of entities + */ + Set search(final String tenant, final String name, final Integer version); + + /** + * Soft deletes a computation. + * + * @param tenant :: + * @param id :: + */ + void delete(final String tenant, final int id); +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IGlobalPropertyService.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IGlobalPropertyService.java new file mode 100644 index 0000000..51b5134 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/IGlobalPropertyService.java @@ -0,0 +1,56 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.service; + +import java.util.Set; + +import com.olacabs.fabric.manager.domain.GlobalPropertyDomain; + +/** + * Todo . + */ +public interface IGlobalPropertyService { + + /** + * Saves all properties. + * + * @param property to saveOrUpdate + */ + GlobalPropertyDomain save(final GlobalPropertyDomain property); + + /** + * Gets all properties. + * + * @return list of global properties + */ + Set search(final String name, final String propertyType); + + /** + * Get by id. + * + * @param id of property + * @return property + */ + GlobalPropertyDomain get(final int id); + + /** + * Delete by id. + * + * @param id of property + */ + void delete(final int id); +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/ApplicationService.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/ApplicationService.java new file mode 100644 index 0000000..987f642 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/ApplicationService.java @@ -0,0 +1,312 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.service.impl; + +import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.olacabs.fabric.manager.bean.ExecutorConfig; +import com.olacabs.fabric.manager.bean.RuntimeOptions; +import com.olacabs.fabric.manager.config.ManagerConfig; +import com.olacabs.fabric.manager.dao.IApplicationDAO; +import com.olacabs.fabric.manager.domain.ApplicationDomain; +import com.olacabs.fabric.manager.domain.ComponentInstanceDomain; +import com.olacabs.fabric.manager.domain.ComputationDomain; +import com.olacabs.fabric.manager.exception.FabricManagerException; +import com.olacabs.fabric.manager.service.IApplicationService; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import mesosphere.marathon.client.Marathon; +import mesosphere.marathon.client.model.v2.App; +import mesosphere.marathon.client.model.v2.GetAppResponse; +import mesosphere.marathon.client.model.v2.Parameter; +import mesosphere.marathon.client.model.v2.UpgradeStrategy; +import mesosphere.marathon.client.utils.MarathonException; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Todo . + */ +@Slf4j +@AllArgsConstructor +@Data +public class ApplicationService implements IApplicationService { + + private final IApplicationDAO dao; + private final Marathon marathon; + private final ManagerConfig managerConfig; + + @Override + public String name(final String tenant, final String name) { + return String.format("/fabric/%s/%s", tenant.toLowerCase().replaceAll("_", "-"), name.toLowerCase()); + } + + @Override + public ApplicationDomain create(final ApplicationDomain application, final String tenant, final int instances) { + + final ComputationDomain computation = application.getComputation(); + final ExecutorConfig executorConfig = application.getExecutorConfig(); + final RuntimeOptions runtimeOpts = application.getRuntimeOptions(); + + double cpu = allocateCpu(computation, runtimeOpts); + double mem = allocateMemory(computation, runtimeOpts); + cpu = Math.max(executorConfig.getMinCpu(), cpu); + mem = Math.max(executorConfig.getMinMemory(), mem); + + final App app = App + .dockerAppBuilder(name(tenant, computation.getName()), executorConfig.getExecutorDockerImage(), cpu, + mem, instances) + .forcePullImage(true).network(runtimeOpts.getDockerConfig().getNetworkType().name()).privileged(false) + .build(); + + final List parameters = getParameters(computation, runtimeOpts, app); + final String fabricManagerConnectionString = getFabricConnString(); + final String specUrl = String.format("http://%s/v1/computations/%s/%s?version=%d", + fabricManagerConnectionString, tenant, computation.getName(), computation.getVersion()); + final Map labels = getLabels(computation, executorConfig); + final String openTsdbHost = getOpenTsdb(); + final double heapSize = managerConfig.getExecutor().getAlpha() * mem; + final Map env = setEnvVariables(computation, tenant, computation.getInternalId(), runtimeOpts, + specUrl, openTsdbHost, heapSize); + + app.setEnv(env); + app.setLabels(labels); + app.setUpgradeStrategy(new UpgradeStrategy(1.0, 0.0)); + app.getContainer().setVolumes(runtimeOpts.getDockerConfig().getVolumes()); + app.getContainer().getDocker().setParameters(parameters); + + log.debug("Spawning computation: [{}:{}:{}] with {} instances using URL: {}", tenant, computation.getName(), + Integer.toString(instances), computation.getInternalId(), specUrl); + log.info("Creating app with configuration: {}", app.toString()); + + // deploy and saveOrUpdate + deploy(app); + + return persist(application, tenant); + } + + @Override + public void delete(final String appName, final String tenant) { + final ApplicationDomain application = get(appName, tenant); + dao.delete(application); + try { + marathon.deleteApp(appName); + } catch (final MarathonException e) { + log.error("Failed while deleting app from marathon", e); + dao.revive(application); + throw new FabricManagerException(e); + } + } + + @Override + public ApplicationDomain get(final String appName, final String tenant) { + final Set applications = dao.search(appName, tenant); + if (applications.isEmpty()) { + return null; + } + + return applications.iterator().next(); + } + + @Override + public Map getAppFromDeploymentEnv(final String appName) { + final GetAppResponse response; + try { + response = marathon.getApp(appName); + } catch (final MarathonException e) { + log.error("Failed while getting app from marathon", e); + throw new FabricManagerException(e); + } + return Collections.singletonMap("response", response); + } + + @Override + public void scale(final String appName, final String tenant, final int scaleTo) { + get(appName, tenant); + final GetAppResponse getAppResponse; + try { + getAppResponse = marathon.getApp(appName); + } catch (final MarathonException e) { + log.error("Failed while getting app from marathon", e); + throw new FabricManagerException(e); + } + getAppResponse.getApp().setInstances(scaleTo); + marathon.updateApp(appName, getAppResponse.getApp()); + update(appName, tenant, ApplicationDomain.builder() + .instances(scaleTo) + .build()); + } + + @Override + public void update(final String appName, final String tenant, final ApplicationDomain updateParam) { + final ApplicationDomain fetched = get(appName, tenant); + fetched.update(updateParam); + dao.modify(fetched); + } + + @Override + public void restart(final String appName, final String tenant, final boolean forcefully) { + get(appName, tenant); + marathon.restartApp(appName, forcefully); + update(appName, tenant, ApplicationDomain.builder().build()); + } + + /* + * Get params + */ + private List getParameters(final ComputationDomain computation, final RuntimeOptions runtimeOpts, + final App app) { + final List parameters = Lists.newArrayList(); + parameters.addAll(runtimeOpts.getDockerConfig().getDockerOpts().getParameters()); + parameters.add(new Parameter("label", String.format("id=%s", computation.getName()))); + runtimeOpts.getUris().stream().forEach(app::addUri); + return parameters; + } + + /* + * Get fabric connection string + */ + private String getFabricConnString() { + String fabricServerConnectionString = managerConfig.getFabricManagerConnectionString(); + if (Strings.isNullOrEmpty(fabricServerConnectionString)) { + fabricServerConnectionString = "_" + com.olacabs.fabric.manager.App.APP_NAME + "_tcp.marathon.mesos."; + } + return fabricServerConnectionString; + } + + /* + * Get labels to set + */ + private Map getLabels(final ComputationDomain computation, final ExecutorConfig executorConfig) { + final Map labels = Maps.newHashMap(); + labels.put("computation-id", computation.getName()); + + final String[] tokens = executorConfig.getExecutorDockerImage().split(":"); + labels.put("executor-version", (tokens.length > 2) ? tokens[2] : "latest"); + labels.put("version", "1"); + return labels; + } + + /* + * Get OpenTsdbHost + */ + private String getOpenTsdb() { + return managerConfig.getOpenTsdbConfig().getOpenTsdbUrl().replaceFirst("http://", "").replaceFirst(":[0-9]+$", + ""); + } + + /* + * Get environment variables + */ + private Map setEnvVariables(final ComputationDomain computation, final String tenant, final int id, + final RuntimeOptions runtimeOpts, final String specUrl, + final String openTsdbHost, final double heapSize) { + final Map env = Maps.newHashMap(); + env.put("HEAP_SIZE", String.format("%dm", (int) Math.rint(heapSize))); + env.put("JVM_OPTS", runtimeOpts.getJvmOpts()); + env.put("OPENTSDB_URL", openTsdbHost); + env.put("SPEC_LOCATION", specUrl); + env.put("LOG_PREFIX", String.format("fabric-%s", String.format("%s-%s-%s", tenant, computation.getName(), id))); + env.put("LOG_LEVEL", runtimeOpts.getLogLevel()); + env.put("METRICS_DISABLED", String.valueOf(runtimeOpts.isMetricsDisabled())); + return env; + } + + /* + * create or scale + */ + private void deploy(final App app) { + GetAppResponse getAppResponse = null; + boolean shouldUpdate = true; + try { + getAppResponse = marathon.getApp(app.getId()); + } catch (final MarathonException me) { + log.info("App with id = {} doesn't exist, so doing a POST", app.getId(), me); + try { + marathon.createApp(app); + } catch (final MarathonException e) { + log.error("Creation of marathon app failed - ", e); + throw new FabricManagerException(e); + } + shouldUpdate = false; + } + + if (shouldUpdate) { + log.info("App with id = {} already exists, so doing a PUT", app.getId()); + + final Map oldLabels = getAppResponse.getApp().getLabels(); + if (oldLabels.containsKey("version")) { + int version = Integer.valueOf(oldLabels.get("version")); + version++; + oldLabels.put("version", "" + version); + } else { + oldLabels.put("version", "1"); + } + app.setLabels(oldLabels); + marathon.updateApp(app.getId(), app); + } + } + + private ApplicationDomain persist(final ApplicationDomain application, final String tenant) { + final ApplicationDomain fetchedApp = get(application.getName(), tenant); + if (fetchedApp == null) { + application.setActive(true); + return dao.save(application); + } else { + update(application.getName(), tenant, ApplicationDomain.builder() + .active(true) + .instances(application.getInstances()) + .build()); + } + return get(application.getName(), tenant); + } + + private double allocateMemory(ComputationDomain computation, RuntimeOptions runtimeOpts) { + double mem = 0.0; + if (runtimeOpts.getTopologyMemory() > 0) { + mem = runtimeOpts.getTopologyMemory(); + } else { + for (final ComponentInstanceDomain source : computation.getSources()) { + mem = mem + source.getComponent().getMemory(); + } + for (final ComponentInstanceDomain processor : computation.getProcessors()) { + mem = mem + processor.getComponent().getMemory(); + } + } + return mem; + } + + private double allocateCpu(ComputationDomain computation, RuntimeOptions runtimeOpts) { + double cpu = 0.0; + if (runtimeOpts.getTopologyCpu() > 0) { + cpu = runtimeOpts.getTopologyCpu(); + } else { + for (final ComponentInstanceDomain source : computation.getSources()) { + cpu = cpu + source.getComponent().getCpu(); + } + for (final ComponentInstanceDomain processor : computation.getProcessors()) { + cpu = cpu + processor.getComponent().getCpu(); + } + } + return cpu; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/ComponentService.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/ComponentService.java new file mode 100644 index 0000000..e0611cd --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/ComponentService.java @@ -0,0 +1,76 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.service.impl; + +import java.util.Set; + +import com.olacabs.fabric.manager.dao.IComponentDAO; +import com.olacabs.fabric.manager.domain.ComponentDomain; +import com.olacabs.fabric.manager.exception.ResourceNotFoundException; +import com.olacabs.fabric.manager.exception.UnProcessableException; +import com.olacabs.fabric.manager.service.IComponentService; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * Todo . + */ +@AllArgsConstructor +@Slf4j +public class ComponentService implements IComponentService { + + private final IComponentDAO componentDAO; + + @Override + public ComponentDomain save(final ComponentDomain component) { + final Set components = + componentDAO.search(component.getNamespace(), component.getName(), component.getVersion()); + if (!components.isEmpty()) { + throw new UnProcessableException( + String.format("Component already found with namespace, id, version - [%s,%s,%s]", + component.getNamespace(), component.getName(), component.getVersion())); + } + return componentDAO.save(component); + } + + @Override + public ComponentDomain get(final int id) { + return componentDAO.read(id); + } + + @Override + public Set search(final String namespace, final String name, final String version) { + return componentDAO.search(namespace, name, version); + } + + @Override + public void update(final int id, final ComponentDomain component) { + componentDAO.update(id, component); + } + + @Override + public void delete(final String namespace, final String name, final String version) { + final Set components = search(namespace, name, version); + if (components.isEmpty()) { + throw new ResourceNotFoundException(String + .format("Component not found with namespace, id, version - [%s,%s,%s]", namespace, name, version)); + } + final ComponentDomain component = components.iterator().next(); + componentDAO.delete(component.getInternalId()); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/ComputationService.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/ComputationService.java new file mode 100644 index 0000000..3628ce8 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/ComputationService.java @@ -0,0 +1,90 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.service.impl; + +import java.util.Set; + +import com.olacabs.fabric.manager.dao.IComponentDAO; +import com.olacabs.fabric.manager.dao.IComputationDAO; +import com.olacabs.fabric.manager.domain.ComputationDomain; +import com.olacabs.fabric.manager.exception.ResourceNotFoundException; +import com.olacabs.fabric.manager.service.IComputationService; +import com.olacabs.fabric.manager.utils.ComputationUtil; +import com.olacabs.fabric.model.common.ComponentType; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * Todo . + */ +@AllArgsConstructor +@Slf4j +public class ComputationService implements IComputationService { + + private IComputationDAO computationDAO; + private IComponentDAO componentDAO; + + @Override + public ComputationDomain saveOrUpdate(final String tenant, final ComputationDomain computation) { + final Set computations = computationDAO.search(tenant, computation.getName(), null); + int newVersion = 0; + for (final ComputationDomain c : computations) { + if (c.getVersion() > newVersion) { + newVersion = c.getVersion(); + } + } + if (newVersion > 0) { + computation.setVersion(newVersion + 1); + } + + computation.setTenant(tenant); + ComputationUtil.preWriteComputationCheck(computation); + + computation.getSources().forEach(componentInstance -> { + componentInstance.setComponent(componentDAO.read(componentInstance.getComponentId())); + componentInstance.setType(ComponentType.SOURCE); + }); + computation.getProcessors().forEach(componentInstance -> { + componentInstance.setComponent(componentDAO.read(componentInstance.getComponentId())); + componentInstance.setType(ComponentType.PROCESSOR); + }); + + return computationDAO.save(computation); + } + + @Override + public ComputationDomain getById(final String tenant, final int id) { + final ComputationDomain computation = computationDAO.get(id); + if (null == computation || !computation.getTenant().equalsIgnoreCase(tenant) || computation.isDeleted()) { + throw new ResourceNotFoundException( + String.format("Computation not found with tenant %s and id %d", tenant, id)); + } + return computation; + } + + @Override + public Set search(final String tenant, final String name, final Integer version) { + return computationDAO.search(tenant, name, version); + } + + @Override + public void delete(final String tenant, final int id) { + final ComputationDomain fetchedComputation = getById(tenant, id); + computationDAO.delete(fetchedComputation); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/GlobalPropertyService.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/GlobalPropertyService.java new file mode 100644 index 0000000..da525d7 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/service/impl/GlobalPropertyService.java @@ -0,0 +1,55 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.service.impl; + +import java.util.Set; + +import com.olacabs.fabric.manager.dao.IGlobalPropertyDAO; +import com.olacabs.fabric.manager.domain.GlobalPropertyDomain; +import com.olacabs.fabric.manager.service.IGlobalPropertyService; + +import lombok.AllArgsConstructor; + +/** + * Todo . + */ +@AllArgsConstructor +public class GlobalPropertyService implements IGlobalPropertyService { + + private IGlobalPropertyDAO dao; + + @Override + public GlobalPropertyDomain save(final GlobalPropertyDomain property) { + return dao.save(property); + } + + @Override + public Set search(final String name, final String propertyType) { + return dao.search(name, propertyType); + } + + @Override + public GlobalPropertyDomain get(final int id) { + return dao.get(id); + } + + @Override + public void delete(int id) { + final GlobalPropertyDomain property = get(id); + dao.delete(property); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/ComputationUtil.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/ComputationUtil.java new file mode 100644 index 0000000..20c06ec --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/ComputationUtil.java @@ -0,0 +1,159 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.utils; + +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import com.google.common.base.Strings; +import com.olacabs.fabric.manager.domain.ComponentInstanceDomain; +import com.olacabs.fabric.manager.domain.ComputationDomain; +import com.olacabs.fabric.manager.exception.UnProcessableException; +import com.olacabs.fabric.manager.utils.graph.DirectedGraph; +import com.olacabs.fabric.model.common.ComponentType; + +/** + * Todo . + */ +public final class ComputationUtil { + + private static final Pattern NAME_PATTERN = + Pattern.compile("^(\\/?((\\.{2})|([a-z0-9][a-z0-9\\-.]*[a-z0-9]+)|([a-z0-9]*))($|\\/))+$"); + private static final Pattern EMAIL_PATTERN = Pattern + .compile("^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"); + + private ComputationUtil(){ + } + + private static void validateConnection(final String from, final String to, final String fromType, + final String toType) { + if (Objects.equals(from, to)) { + throw new UnProcessableException( + String.format("Invalid computation spec - component with id=%s connected to itself", from)); + } + if (Strings.isNullOrEmpty(toType) || Strings.isNullOrEmpty(fromType)) { + throw new UnProcessableException( + "Invalid computation spec - connecting two components one of which doesn't exist"); + } + if ("source".equals(fromType) && "source".equals(toType)) { + throw new UnProcessableException("Invalid computation spec - invalid connection source -> source"); + } + if ("processor".equals(fromType) && "source".equals(toType)) { + throw new UnProcessableException("Invalid computation spec - invalid connection processor -> source"); + } + } + + public static void validateConnections(final ComputationDomain computation) { + Map sources = computation.getSources().parallelStream() + .collect(Collectors.toMap(ComponentInstanceDomain::getId, Function.identity())); + Map processors = computation.getProcessors().parallelStream() + .collect(Collectors.toMap(ComponentInstanceDomain::getId, Function.identity())); + + final String sourceType = ComponentType.SOURCE.toString().toLowerCase(); + final String processorType = ComponentType.PROCESSOR.toString().toLowerCase(); + + computation.getConnections().forEach(connection -> { + final String from = connection.getFromLink(); + final String to = connection.getToLink(); + + String fromType = ""; + String toType = ""; + if (sources.containsKey(from)) { + fromType = sourceType; + } + if (processors.containsKey(from)) { + fromType = processorType; + } + if (sources.containsKey(to)) { + toType = ComponentType.SOURCE.toString().toLowerCase(); + } + if (processors.containsKey(to)) { + toType = ComponentType.PROCESSOR.toString().toLowerCase(); + } + + validateConnection(from, to, fromType, toType); + }); + } + + public static void validateGraph(final ComputationDomain computation) { + final DirectedGraph g = GraphUtil.getDirectedGraphFromComputationSpec(computation); + if (g.hasCycle()) { + throw new UnProcessableException("Invalid computation spec - computation contains one or more cycles"); + } + } + + private static void validateEmail(final String email) { + if (!com.google.common.base.Strings.isNullOrEmpty(email)) { + final Matcher matcher = EMAIL_PATTERN.matcher(email); + if (!matcher.matches()){ + throw new UnProcessableException(email + " not a valid ownerEmail"); + } + } else { + throw new UnProcessableException("Email can't be null"); + } + } + + private static void validateComputationName(final String name) { + if (name == null || name.isEmpty()) { + throw new UnProcessableException("Invalid computation spec - computation name must not be empty or null"); + } + if (!NAME_PATTERN.matcher(name).matches()) { + throw new UnProcessableException( + "Invalid computation spec - computation name must only contain lowercase characters," + + " digits, hyphens, ."); + } + } + + private static void validateComputation(final ComputationDomain computation) { + validateEmail(computation.getOwnerEmail()); + validateComputationName(computation.getName()); + validateConnections(computation); + validateGraph(computation); + validateEmail(computation.getOwnerEmail()); + } + + public static void transform(final ComputationDomain computation) { + final Map sources = computation.getSources().parallelStream() + .collect(Collectors.toMap(ComponentInstanceDomain::getId, Function.identity())); + final Map processors = computation.getProcessors().parallelStream() + .collect(Collectors.toMap(ComponentInstanceDomain::getId, Function.identity())); + + computation.getConnections().forEach(connection -> { + final String from = connection.getFromLink(); + if (sources.containsKey(from)) { + connection.setFromType(ComponentType.SOURCE); + } + if (processors.containsKey(from)) { + connection.setFromType(ComponentType.PROCESSOR); + } + }); + } + + public static void preWriteComputationCheck(final ComputationDomain spec) { + ComputationUtil.transform(spec); + ComputationUtil.validateComputation(spec); + } + + public static String id(final String team, final String name) { + return UUID.nameUUIDFromBytes(String.format("%s:%s", team, name).getBytes()).toString(); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/GraphUtil.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/GraphUtil.java new file mode 100644 index 0000000..7ddb891 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/GraphUtil.java @@ -0,0 +1,85 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.utils; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import com.google.common.collect.Lists; +import com.olacabs.fabric.manager.domain.ComponentInstanceDomain; +import com.olacabs.fabric.manager.domain.ComputationDomain; +import com.olacabs.fabric.manager.domain.ConnectionDomain; +import com.olacabs.fabric.manager.utils.graph.DirectedGraph; +import com.olacabs.fabric.manager.utils.graph.UndirectedGraph; + +/** + * Todo . + */ +final class GraphUtil { + + private GraphUtil(){ + } + + /** + * @param spec to get directed graph + * @return directed graph + */ + public static DirectedGraph getDirectedGraphFromComputationSpec(final ComputationDomain spec) { + final Set connections = spec.getConnections(); + final int numberOfNodes = spec.getSources().size() + spec.getProcessors().size(); + final AtomicInteger i = new AtomicInteger(0); + final Map nodes = spec.getSources().stream() + .collect(Collectors.toMap(ComponentInstanceDomain::getId, componentInstance -> i.getAndIncrement())); + nodes.putAll(spec.getProcessors().stream() + .collect(Collectors.toMap(ComponentInstanceDomain::getId, componentInstance -> i.getAndIncrement()))); + final List> adjacencyList = Lists.newArrayList(); + for (int j = 0; j < numberOfNodes; j++) { + adjacencyList.add(Lists.newLinkedList()); + } + connections.stream().forEach(connection -> adjacencyList.get(nodes.get(connection.getFromLink())) + .add(nodes.get(connection.getToLink()))); + return new DirectedGraph(adjacencyList); + } + + /** + * @param spec to get undirected graph + * @return undirected graph + */ + public static UndirectedGraph getUndirectedGraphFromComputationSpec(final ComputationDomain spec) { + final Set connections = spec.getConnections(); + final int numberOfNodes = spec.getSources().size() + spec.getProcessors().size(); + final AtomicInteger i = new AtomicInteger(0); + final Map nodes = spec.getSources().stream() + .collect(Collectors.toMap(ComponentInstanceDomain::getId, componentInstance -> i.getAndIncrement())); + nodes.putAll(spec.getProcessors().stream() + .collect(Collectors.toMap(ComponentInstanceDomain::getId, componentInstance -> i.getAndIncrement()))); + final List> adjacencyList = Lists.newArrayList(); + for (int j = 0; j < numberOfNodes; j++) { + adjacencyList.add(new LinkedList<>()); + } + connections.stream().forEach(connection -> { + adjacencyList.get(nodes.get(connection.getFromLink())).add(nodes.get(connection.getToLink())); + adjacencyList.get(nodes.get(connection.getToLink())).add(nodes.get(connection.getFromLink())); + }); + + return new UndirectedGraph(adjacencyList); + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/graph/DirectedGraph.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/graph/DirectedGraph.java new file mode 100644 index 0000000..d6b44df --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/graph/DirectedGraph.java @@ -0,0 +1,125 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.utils.graph; + +import java.util.ArrayList; +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +/** + * Todo . + */ +@Getter +@Setter +@Slf4j +public class DirectedGraph extends Graph { + + private int timestamp; + + private List nodeTimestamps; + + public DirectedGraph(final List> adjacencyList) { + super(adjacencyList); + } + + private void incrementTimestamp() { + timestamp++; + } + + private List getNeighbours(final int node) { + return adjacencyList.get(node); + } + + private int getStartTime(final int node) { + return nodeTimestamps.get(node).getStart(); + } + + private int getFinishTime(final int node) { + return nodeTimestamps.get(node).getFinish(); + } + + private void setStartTime(final int node, final int startTime) { + nodeTimestamps.get(node).setStart(startTime); + } + + private void setFinishTime(final int node, final int finishTime) { + nodeTimestamps.get(node).setFinish(finishTime); + } + + private void preDfs() { + this.timestamp = 0; + this.nodeTimestamps = new ArrayList<>(); + for (int i = 0; i < adjacencyList.size(); i++) { + nodeTimestamps.add(new DfsTimestamp(-1, -1)); + } + } + + private void postDfs() { + this.nodeTimestamps.clear(); + } + + public boolean hasCycle() { + boolean result = false; + preDfs(); + for (int j = 0; j < numberOfNodes; j++) { + if (getStartTime(j) < 0) { + if (hasCycle(j)) { + result = true; + break; + } + } + } + postDfs(); + return result; + } + + private boolean hasCycle(int currentNode) { + if (getStartTime(currentNode) < 0) { + setStartTime(currentNode, getTimestamp()); + incrementTimestamp(); + for (int node : getNeighbours(currentNode)) { + if (getFinishTime(node) >= 0) { + log.debug("found a cross edge or forward edge, skip following"); + } else if (getStartTime(node) < 0) { + // found a tree edge, need to follow + boolean hasCycle = hasCycle(node); + if (hasCycle) { + return true; + } + } else if (getStartTime(node) < getStartTime(currentNode)) { + // found a back edge + return true; + } + } + setFinishTime(currentNode, getTimestamp()); + incrementTimestamp(); + } + return false; + } + + @Getter + @Setter + @AllArgsConstructor + static class DfsTimestamp { + private int start; + private int finish; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/graph/Graph.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/graph/Graph.java new file mode 100644 index 0000000..f0a0e06 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/graph/Graph.java @@ -0,0 +1,39 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.utils.graph; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * Todo . + */ +@Getter +@Setter +public class Graph { + + protected final int numberOfNodes; + + protected final List> adjacencyList; + + public Graph(final List> adjacencyList) { + this.numberOfNodes = adjacencyList.size(); + this.adjacencyList = adjacencyList; + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/graph/UndirectedGraph.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/graph/UndirectedGraph.java new file mode 100644 index 0000000..a5c35c2 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/utils/graph/UndirectedGraph.java @@ -0,0 +1,69 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.utils.graph; + +import java.util.BitSet; +import java.util.List; + +/** + * Todo . + */ +public class UndirectedGraph extends Graph { + private BitSet visited; + + public UndirectedGraph(final List> adjacencyList) { + super(adjacencyList); + } + + private void preDfs() { + if (visited == null) { + visited = new BitSet(numberOfNodes); + } + } + + private void postDfs() { + visited.clear(); + } + + public int numberOfComponents() { + int components = 0; + preDfs(); + for (int i = 0; i < numberOfNodes; i++) { + if (!visited.get(i)) { + components++; + dfs(i); + } + } + postDfs(); + return components; + } + + private void dfs(int startNode) { + if (visited.get(startNode)) { + return; + } else { + visited.set(startNode); + List neighbours = adjacencyList.get(startNode); + for (int neighbour : neighbours) { + if (!visited.get(neighbour)) { + dfs(neighbour); + } + } + } + } + +} diff --git a/fabric-manager/src/main/resources/dev-config.yml b/fabric-manager/src/main/resources/dev-config.yml new file mode 100644 index 0000000..bff39d4 --- /dev/null +++ b/fabric-manager/src/main/resources/dev-config.yml @@ -0,0 +1,79 @@ + +#Copyright 2016 ANI Technologies 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. + +server: + type: simple + applicationContextPath: / + adminContextPath: /admin + minThreads: 100 + maxThreads: 100 + connector: + port: 18000 + type: http + +fabricServerConnectionString: localhost:18000 +artifactoryPath: http://localhost:8080/artifactory +marathonEndpoint: http://localhost:8080/ + +executor: + minCpu: 0.5 + minMemory: 1024.0 + alpha: 0.5 + executorDockerImage: localhost:9002/fabric-executor:0.0.1 + +opentsdb: + enabled: false + openTsdbUrl: "localhost:4242" + appName: "fabric-manager" + namespace: "fabric" + platform: "" + periodInSeconds: 30 + +serviceDiscovery: + zkConnectionString: localhost:2181 + serviceName: fabric-manager + namespace: fabric + environment: dev + hostname: localhost + port: 18000 + +logging: + level: INFO + loggers: + org.hibernate: ERROR + appenders: + - type: console + threshold: ALL + timeZone: UTC + logFormat: "fabric-manager %d [%thread] %-5level %c{15} - [%X{X-Transaction-Key} - %X{X-Request-Key}] - %msg%n%rEx" + +database: + driverClass: com.mysql.jdbc.Driver + user: root + password: + url: jdbc:mysql://localhost:3306/fabric_manager_local?autoReconnect=true + maxWaitForConnection: 1s + validationQuery: "SELECT 1" + minSize: 8 + maxSize: 32 + checkConnectionWhileIdle: false + properties: + charSet: UTF-8 + hibernate.dialect: org.hibernate.dialect.MySQLDialect + hibernate.hbm2ddl.auto: update + hibernate.show_sql: false + +swagger: + resourcePackage: com.olacabs.fabric.manager.resource diff --git a/fabric-manager/src/main/resources/docker-compose-config.yml b/fabric-manager/src/main/resources/docker-compose-config.yml new file mode 100644 index 0000000..3887fe3 --- /dev/null +++ b/fabric-manager/src/main/resources/docker-compose-config.yml @@ -0,0 +1,78 @@ +#Copyright 2016 ANI Technologies 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. + +server: + type: simple + applicationContextPath: / + adminContextPath: /admin + minThreads: 100 + maxThreads: 100 + connector: + port: 18000 + type: http + +fabricManagerConnectionString: ${FABRIC_MANAGER_CONNECTION_STRING} +artifactoryPath: ${ARTIFACTORY_URL} +marathonEndpoint: ${MARATHON_ENDPOINT} + +executor: + minCpu: ${MIN_CPU} + minMemory: ${MIN_MEMORY} + alpha: ${ALPHA} + executorDockerImage: ${EXECUTOR_DOCKER_IMAGE} + +opentsdb: + enabled: ${METRICS_ENABLED} + openTsdbUrl: ${OPENTSDB_URL} + appName: ${OPENTSDB_APP_NAME} + namespace: ${OPENTSDB_NAMESPACE} + platform: ${OPENTSDB_PLATFORM} + periodInSeconds: ${OPENTSDB_PERIOD_IN_SEC} + +serviceDiscovery: + zkConnectionString: ${ZK_CONNECTION_STRING} + serviceName: ${SERVICE_NAME} + namespace: ${SERVICE_NAMESPACE} + environment: ${SERVICE_ENV} + hostname: ${HOST} + port: ${PORT_18000} + +logging: + level: ${LOG_LEVEL} + loggers: + org.hibernate: ${HIBERNATE_LOG_LEVEL} + appenders: + - type: console + threshold: ALL + timeZone: UTC + logFormat: "fabric-manager %d [%thread] %-5level %c{15} - [%X{X-Transaction-Key} - %X{X-Request-Key}] - %msg%n%rEx" + +database: + driverClass: com.mysql.jdbc.Driver + user: ${DB_USER} + password: ${DB_PASSWORD} + url: ${DB_URL} + maxWaitForConnection: ${DB_MAX_WAIT_FOR_CONNECTION} + validationQuery: "SELECT 1" + minSize: ${DB_MIN_SIZE} + maxSize: ${DB_MAX_SIZE} + checkConnectionWhileIdle: ${DB_CHECK_CONNECTION_WHILE_IDLE} + properties: + charSet: UTF-8 + hibernate.dialect: org.hibernate.dialect.MySQLDialect + hibernate.hbm2ddl.auto: ${DB_AUTO_EXPORT_DDL_TO_DATABASE} + hibernate.show_sql: ${DB_SHOW_SQL} + +swagger: + resourcePackage: com.olacabs.fabric.manager.resource diff --git a/fabric-manager/src/main/resources/prod-config.yml b/fabric-manager/src/main/resources/prod-config.yml new file mode 100644 index 0000000..ae00bf5 --- /dev/null +++ b/fabric-manager/src/main/resources/prod-config.yml @@ -0,0 +1,77 @@ +#Copyright 2016 ANI Technologies 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. + +server: + type: simple + applicationContextPath: / + adminContextPath: /admin + minThreads: 100 + maxThreads: 100 + connector: + port: 18000 + type: http + +fabricManagerConnectionString: ${FABRIC_MANAGER_CONNECTION_STRING} +artifactoryPath: ${ARTIFACTORY_URL} +marathonEndpoint: ${MARATHON_ENDPOINT} + +executor: + minCpu: ${MIN_CPU} + minMemory: ${MIN_MEMORY} + alpha: ${ALPHA} + executorDockerImage: ${EXECUTOR_DOCKER_IMAGE} + +opentsdb: + enabled: ${METRICS_ENABLED} + openTsdbUrl: ${OPENTSDB_URL} + appName: ${OPENTSDB_APP_NAME} + namespace: ${OPENTSDB_NAMESPACE} + platform: ${OPENTSDB_PLATFORM} + periodInSeconds: ${OPENTSDB_PERIOD_IN_SEC} + +serviceDiscovery: + zkConnectionString: ${ZK_CONNECTION_STRING} + serviceName: ${SERVICE_NAME} + namespace: ${SERVICE_NAMESPACE} + environment: ${SERVICE_ENV} + hostname: ${HOST} + port: ${PORT_18000} + +logging: + level: ${LOG_LEVEL} + loggers: + org.hibernate: ${HIBERNATE_LOG_LEVEL} + appenders: + - type: console + threshold: ALL + timeZone: UTC + logFormat: "fabric-manager %d [%thread] %-5level %c{15} - [%X{X-Transaction-Key} - %X{X-Request-Key}] - %msg%n%rEx" + +database: + driverClass: com.mysql.jdbc.Driver + user: ${DB_USER} + password: ${DB_PASSWORD} + url: ${DB_URL} + maxWaitForConnection: ${DB_MAX_WAIT_FOR_CONNECTION} + validationQuery: "SELECT 1" + minSize: ${DB_MIN_SIZE} + maxSize: ${DB_MAX_SIZE} + checkConnectionWhileIdle: ${DB_CHECK_CONNECTION_WHILE_IDLE} + properties: + charSet: UTF-8 + hibernate.dialect: org.hibernate.dialect.MySQLDialect + hibernate.show_sql: ${DB_SHOW_SQL} + +swagger: + resourcePackage: com.olacabs.fabric.manager.resource diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/converter/ComponentSourceConverterTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/converter/ComponentSourceConverterTest.java new file mode 100644 index 0000000..67ca06a --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/converter/ComponentSourceConverterTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.converter; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.olacabs.fabric.model.common.ComponentSource; +import com.olacabs.fabric.model.common.sources.ArtifactoryComponentSource; + +/** + * Todo . + */ +public class ComponentSourceConverterTest { + + private static ComponentSource source = ArtifactoryComponentSource.builder().artifactId("com.olacabs") + .groupId("test").artifactoryUrl("http://test").version("0.1").build(); + private static String sourceString = + "{\"type\":\"artifactory\",\"artifactoryUrl\":\"http://test\",\"groupId\":" + + "\"test\",\"artifactId\":\"com.olacabs\",\"version\":\"0.1\"}"; + + @Test + public void shouldConvertComponentSourceToDatabaseColumn() { + final ComponentSourceConverter converter = new ComponentSourceConverter(); + final String json = converter.convertToDatabaseColumn(source); + assertEquals(json, sourceString); + } + + @Test + public void shouldConvertStringToEntityAttribute() throws JsonProcessingException { + final ComponentSourceConverter converter = new ComponentSourceConverter(); + final ComponentSource componentSource = converter.convertToEntityAttribute(sourceString); + assertEquals(new ObjectMapper().writeValueAsString(componentSource), sourceString); + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/converter/JsonListConverterTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/converter/JsonListConverterTest.java new file mode 100644 index 0000000..deb1906 --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/converter/JsonListConverterTest.java @@ -0,0 +1,63 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.converter; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Test; + +import com.google.common.collect.Lists; + +/** + * Todo . + */ +public class JsonListConverterTest { + + @Test + public void shouldConvertStringToDatabaseColumn() { + JsonListConverter converter = new JsonListConverter(); + List list = Lists.newArrayList(); + list.add("element_1"); + list.add("element_2"); + assertEquals(converter.convertToDatabaseColumn(list), "[\"element_1\",\"element_2\"]"); + } + + @Test + public void shouldConvertStringToEntityAttribute() { + JsonListConverter converter = new JsonListConverter(); + List list = converter.convertToEntityAttribute("[\"element_1\",\"element_2\"]"); + assertEquals(list.size(), 2); + } + + @Test + public void shouldConvertLongToDatabaseColumn() { + JsonListConverter converter = new JsonListConverter(); + List list = Lists.newArrayList(); + list.add(1L); + list.add(2L); + assertEquals(converter.convertToDatabaseColumn(list), "[1,2]"); + } + + @Test + public void shouldConvertLongToEntityAttribute() { + JsonListConverter converter = new JsonListConverter(); + List list = converter.convertToEntityAttribute("[1,2]"); + assertEquals(list.size(), 2); + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/converter/JsonSetConverterTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/converter/JsonSetConverterTest.java new file mode 100644 index 0000000..84c0023 --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/converter/JsonSetConverterTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.converter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Set; + +import org.junit.Test; + +import com.google.common.collect.Sets; + +/** + * Todo . + */ +public class JsonSetConverterTest { + + @Test + public void shouldConvertStringToDatabaseColumn() { + JsonSetConverter converter = new JsonSetConverter(); + Set set = Sets.newHashSet(); + set.add("element_1"); + set.add("element_2"); + String json = converter.convertToDatabaseColumn(set); + boolean valid = (json.equalsIgnoreCase("[\"element_1\",\"element_2\"]") + || json.equalsIgnoreCase("[\"element_2\",\"element_1\"]")); + assertTrue(valid); + } + + @Test + public void shouldConvertStringToEntityAttribute() { + JsonSetConverter converter = new JsonSetConverter(); + Set set = converter.convertToEntityAttribute("[\"element_1\",\"element_2\"]"); + assertEquals(set.size(), 2); + } + + @Test + public void shouldConvertLongToDatabaseColumn() { + JsonSetConverter converter = new JsonSetConverter(); + Set set = Sets.newHashSet(); + set.add(1L); + set.add(2L); + assertEquals(converter.convertToDatabaseColumn(set), "[1,2]"); + } + + @Test + public void shouldConvertLongToEntityAttribute() { + JsonSetConverter converter = new JsonSetConverter(); + Set set = converter.convertToEntityAttribute("[1,2]"); + assertEquals(set.size(), 2); + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/filter/UserRequiredFilterTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/filter/UserRequiredFilterTest.java new file mode 100644 index 0000000..9cb25b5 --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/filter/UserRequiredFilterTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.filter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.*; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.core.UriInfo; + +import org.junit.Before; +import org.junit.Test; + +/** + * Todo . + */ +public class UserRequiredFilterTest { + + private UserFilter userFilter; + private ContainerRequestContext request; + private ContainerResponseContext response; + + @Before + public void setup() { + userFilter = new UserFilter(); + request = mock(ContainerRequestContext.class); + response = mock(ContainerResponseContext.class); + when(request.getHeaderString(UserFilter.X_USER)).thenReturn("awesome_user@olacabs.com"); + + UriInfo uri = mock(UriInfo.class); + doReturn(uri).when(request).getUriInfo(); + doReturn(null).when(uri).getPath(); + when(request.getUriInfo().getPath()).thenReturn(""); + } + + @Test + public void shouldSetUserContext() throws IOException, ServletException { + userFilter.filter(request); + assertEquals(UserContext.instance().getUser(), "awesome_user@olacabs.com"); + } + + @Test + public void shouldResetUserContext() throws IOException, ServletException { + userFilter.filter(request, response); + assertNull(UserContext.instance().getUser()); + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/util/graph/DirectedGraphTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/util/graph/DirectedGraphTest.java new file mode 100644 index 0000000..4c4fb5f --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/util/graph/DirectedGraphTest.java @@ -0,0 +1,80 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.util.graph; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import com.olacabs.fabric.manager.utils.graph.DirectedGraph; + +/** + * Todo . + */ +public class DirectedGraphTest { + + @Test + public void testIsCyclicGraphHasNoCycles() { + List> adjacencyList = new ArrayList<>(); + for (int i = 0; i < 7; i++) { + adjacencyList.add(new LinkedList<>()); + } + adjacencyList.get(0).addAll(Arrays.asList(1, 2)); + adjacencyList.get(2).add(3); + adjacencyList.get(4).addAll(Arrays.asList(2, 5)); + adjacencyList.get(5).add(6); + adjacencyList.get(6).add(2); + + DirectedGraph graph = new DirectedGraph(adjacencyList); + Assert.assertFalse(graph.hasCycle()); + } + + @Test + public void testIsCyclicGraphHasCycles() { + List> adjacencyList = new ArrayList<>(); + for (int i = 0; i < 7; i++) { + adjacencyList.add(new LinkedList<>()); + } + adjacencyList.get(0).addAll(Arrays.asList(1, 2)); + adjacencyList.get(2).addAll(Arrays.asList(3, 4)); + adjacencyList.get(4).add(5); + adjacencyList.get(5).add(6); + adjacencyList.get(6).add(2); + + DirectedGraph graph = new DirectedGraph(adjacencyList); + Assert.assertTrue(graph.hasCycle()); + } + + @Test + public void testIsCyclicEmptyGraph() { + List> adjacencyList = new ArrayList<>(); + DirectedGraph graph = new DirectedGraph(adjacencyList); + Assert.assertFalse(graph.hasCycle()); + } + + @Test + public void testIsCyclicSingletonGraph() { + List> adjacencyList = new ArrayList<>(); + adjacencyList.add(new LinkedList<>()); + DirectedGraph graph = new DirectedGraph(adjacencyList); + Assert.assertFalse(graph.hasCycle()); + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/util/graph/UndirectedGraphTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/util/graph/UndirectedGraphTest.java new file mode 100644 index 0000000..9a84d40 --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/util/graph/UndirectedGraphTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.util.graph; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import com.olacabs.fabric.manager.utils.graph.UndirectedGraph; + +/** + * Todo . + */ +public class UndirectedGraphTest { + + @Test + public void testNumberOfComponentsMoreThanOne() { + List> adjacencyList = new ArrayList<>(); + for (int i = 0; i < 9; i++) { + adjacencyList.add(new LinkedList<>()); + } + adjacencyList.get(0).addAll(Arrays.asList(1, 2)); + adjacencyList.get(1).add(0); + adjacencyList.get(2).addAll(Arrays.asList(0, 3, 4)); + adjacencyList.get(3).add(2); + adjacencyList.get(4).addAll(Arrays.asList(2, 5)); + adjacencyList.get(5).addAll(Arrays.asList(4, 6)); + adjacencyList.get(6).add(5); + adjacencyList.get(7).add(8); + adjacencyList.get(8).add(7); + UndirectedGraph graph = new UndirectedGraph(adjacencyList); + Assert.assertEquals(2, graph.numberOfComponents()); + } + + @Test + public void testNumberOfComponentsEmptyGraph() { + List> adjacencyList = new ArrayList<>(); + UndirectedGraph graph = new UndirectedGraph(adjacencyList); + Assert.assertEquals(0, graph.numberOfComponents()); + } + + @Test + public void testNumberOfComponentsSingletonGraph() { + List> adjacencyList = new ArrayList<>(); + adjacencyList.add(new LinkedList<>()); + UndirectedGraph graph = new UndirectedGraph(adjacencyList); + Assert.assertEquals(1, graph.numberOfComponents()); + } + + @Test + public void testNumberOfComponentsOne() { + List> adjacencyList = new ArrayList<>(); + for (int i = 0; i < 4; i++) { + adjacencyList.add(new LinkedList<>()); + } + adjacencyList.get(0).add(2); + adjacencyList.get(1).add(3); + adjacencyList.get(2).addAll(Arrays.asList(0, 3)); + adjacencyList.get(3).addAll(Arrays.asList(1, 2)); + UndirectedGraph graph = new UndirectedGraph(adjacencyList); + Assert.assertEquals(1, graph.numberOfComponents()); + } +} diff --git a/pom.xml b/pom.xml index d2e975b..026d709 100644 --- a/pom.xml +++ b/pom.xml @@ -72,6 +72,7 @@ fabric-components fabric-processor-archetype fabric-examples + fabric-manager diff --git a/src/build/checkstyle.xml b/src/build/checkstyle.xml index 913c667..271cfae 100644 --- a/src/build/checkstyle.xml +++ b/src/build/checkstyle.xml @@ -107,10 +107,10 @@ - - - - + + + + From bc0bc9de10ed0c5c27837218d6e0f6c849505f10 Mon Sep 17 00:00:00 2001 From: Suman BN Date: Fri, 4 Nov 2016 12:59:02 +0530 Subject: [PATCH 2/6] converter, exceptionMapper, ut --- fabric-manager/DockerFile | 36 ++++ fabric-manager/docker-compose.yml | 93 +++++++++ .../java/com/olacabs/fabric/manager/App.java | 3 +- .../converter/ExecutorConfigConverter.java | 65 +++++++ .../converter/RuntimeOptionsConverter.java | 65 +++++++ .../manager/domain/ApplicationDomain.java | 6 +- .../exception/mapper/HttpExceptionMapper.java | 48 +++++ .../resource/ApplicationResourceTest.java | 134 +++++++++++++ .../resource/ComponentResourceTest.java | 109 +++++++++++ .../resource/ComputationResourceTest.java | 96 +++++++++ .../resource/GlobalPropertyResourceTest.java | 87 +++++++++ .../service/ApplicationServiceTest.java | 184 ++++++++++++++++++ .../manager/service/ComponentServiceTest.java | 111 +++++++++++ .../service/ComputationServiceTest.java | 114 +++++++++++ .../service/GlobalPropertyServiceTest.java | 82 ++++++++ 15 files changed, 1230 insertions(+), 3 deletions(-) create mode 100644 fabric-manager/DockerFile create mode 100644 fabric-manager/docker-compose.yml create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/ExecutorConfigConverter.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/RuntimeOptionsConverter.java create mode 100644 fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/mapper/HttpExceptionMapper.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/ApplicationResourceTest.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/ComponentResourceTest.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/ComputationResourceTest.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/GlobalPropertyResourceTest.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/service/ApplicationServiceTest.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/service/ComponentServiceTest.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/service/ComputationServiceTest.java create mode 100644 fabric-manager/src/test/java/com/olacabs/fabric/manager/service/GlobalPropertyServiceTest.java diff --git a/fabric-manager/DockerFile b/fabric-manager/DockerFile new file mode 100644 index 0000000..d6ef194 --- /dev/null +++ b/fabric-manager/DockerFile @@ -0,0 +1,36 @@ +#Copyright 2016 ANI Technologies 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. + +FROM ubuntu:14.04 +MAINTAINER shashank.g@olacabs.com + +RUN apt-get update --fix-missing \ + && apt-get install -y --no-install-recommends software-properties-common \ + && add-apt-repository ppa:webupd8team/java \ + && gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 \ + && apt-get update \ + && echo debconf shared/accepted-oracle-license-v1-1 select true | debconf-set-selections \ + && echo debconf shared/accepted-oracle-license-v1-1 seen true | debconf-set-selections \ + && apt-get install -y --no-install-recommends oracle-java8-installer \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + + EXPOSE 17000 + + VOLUME /var/log/fabric-manager + + COPY target/fabric-manager*.jar fabric-manager.jar + COPY target/classes/docker-compose-config.yml docker-compose-config.yml + + CMD sh -c "sleep 20 ; java -jar -Xms${JAVA_PROCESS_MIN_HEAP} -Xmx${JAVA_PROCESS_MAX_HEAP} -XX:+${GC_ALGO} -Dfile.encoding=utf-8 fabric-manager.jar server ${CONFIG_ENV}-config.yml" diff --git a/fabric-manager/docker-compose.yml b/fabric-manager/docker-compose.yml new file mode 100644 index 0000000..76e984a --- /dev/null +++ b/fabric-manager/docker-compose.yml @@ -0,0 +1,93 @@ +#Copyright 2016 ANI Technologies 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. + +# Zookeeper compose +zookeeper: + image: garland/zookeeper + ports: + - "2181:2181" + - "2888:2888" + - "3888:3888" + +# MySQL compose +mysql: + image: mysql/mysql-server:latest + environment: + - MYSQL_ROOT_PASSWORD=password + - MYSQL_DATABASE=fabric_manager + ports: + - "3306:3306" + +# Artifactory compose +artifactory: + image: mattgruter/artifactory + ports: + - "8080:8080" + +# OpenTSDB compose +opentsdb: + image: petergrace/opentsdb-docker:latest + ports: + - "4242:4242" + - "60030:60030" + +# Fabric-Manager compose +fabricmanager: + build: . + ports: + - "18000:18000" + volumes: + - /var/log/fabricmanager + # link to zk, artifact, es + links: + - zookeeper + - mysql + - artifactory + - opentsdb + # enviroment valiables + environment: + - FABRIC_MANAGER_CONNECTION_STRING=_fabric-manager._tcp.marathon.mesos. + - ARTIFACTORY_URL=http://artifactory:8080/artifactory + - MARATHON_ENDPOINT=http://localhost:8080/ + - MIN_CPU=0.5 + - MIN_MEMORY=512 + - ALPHA=0.5 + - EXECUTOR_DOCKER_IMAGE=localhost:9002/fabric-executor:0.0.1 + - METRICS_ENABLED=false + - OPENTSDB_URL=opentsdb:4242 + - OPENTSDB_APP_NAME=fabric-manager + - OPENTSDB_NAMESPACE=fabric + - OPENTSDB_PLATFORM=fabric + - OPENTSDB_PERIOD_IN_SEC=30 + - ZK_CONNECTION_STRING=zookeeper:2181 + - SERVICE_NAME=fabric-manager + - SERVICE_NAMESPACE=fabric + - SERVICE_ENV=dcos + - HOST=192.168.99.100 + - PORT_18000=18000 + - LOG_LEVEL=INFO + - HIBERNATE_LOG_LEVEL=ERROR + - DB_USER=root + - DB_PASSWORD=password + - DB_URL=jdbc:mysql://mysql:3306/fabric_manager?autoReconnect=true + - DB_MAX_WAIT_FOR_CONNECTION=1s + - DB_MIN_SIZE=8 + - DB_MAX_SIZE=32 + - DB_CHECK_CONNECTION_WHILE_IDLE=false + - DB_AUTO_EXPORT_DDL_TO_DATABASE=update + - DB_SHOW_SQL=false + - GC_ALGO=UseG1GC + - JAVA_PROCESS_MIN_HEAP=1g + - JAVA_PROCESS_MAX_HEAP=1g + - CONFIG_ENV=docker-compose diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/App.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/App.java index 76af937..ecc543c 100644 --- a/fabric-manager/src/main/java/com/olacabs/fabric/manager/App.java +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/App.java @@ -28,6 +28,7 @@ import com.olacabs.fabric.manager.dao.impl.ComputationDAO; import com.olacabs.fabric.manager.dao.impl.GlobalPropertyDAO; import com.olacabs.fabric.manager.domain.*; +import com.olacabs.fabric.manager.exception.mapper.HttpExceptionMapper; import com.olacabs.fabric.manager.exception.mapper.RuntimeExceptionMapper; import com.olacabs.fabric.manager.filter.UserFilter; import com.olacabs.fabric.manager.managed.OpenTsdbMetricReporter; @@ -137,7 +138,7 @@ public void run(final ManagerConfig config, final Environment environment) throw environment.jersey().register(globalPropertyResource); environment.jersey().register(RuntimeExceptionMapper.class); -// environment.jersey().register(HttpExceptionMapper.class); + environment.jersey().register(HttpExceptionMapper.class); environment.jersey().register(UserFilter.class); } diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/ExecutorConfigConverter.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/ExecutorConfigConverter.java new file mode 100644 index 0000000..de5737e --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/ExecutorConfigConverter.java @@ -0,0 +1,65 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.converter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.olacabs.fabric.manager.bean.ExecutorConfig; +import com.olacabs.fabric.manager.exception.FabricManagerException; +import lombok.extern.slf4j.Slf4j; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; +import java.io.IOException; + +/** + * Executor config converter . + */ +@Converter +@Slf4j +public class ExecutorConfigConverter implements AttributeConverter { + + private final ObjectMapper mapper; + + public ExecutorConfigConverter() { + this(new ObjectMapper()); + } + + public ExecutorConfigConverter(final ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public String convertToDatabaseColumn(final ExecutorConfig object) { + try { + return mapper.writeValueAsString(object); + } catch (final JsonProcessingException e) { + log.error("Unable to parse component source - {}", e.getMessage(), e); + throw new FabricManagerException(e); + } + } + + @Override + public ExecutorConfig convertToEntityAttribute(final String source) { + try { + return mapper.readValue(source, ExecutorConfig.class); + } catch (final IOException e) { + log.error("Unable to parse ExecutorConfig source - {}", e.getMessage(), e); + throw new FabricManagerException(e); + } + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/RuntimeOptionsConverter.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/RuntimeOptionsConverter.java new file mode 100644 index 0000000..34f05dc --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/converter/RuntimeOptionsConverter.java @@ -0,0 +1,65 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.converter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.olacabs.fabric.manager.bean.RuntimeOptions; +import com.olacabs.fabric.manager.exception.FabricManagerException; +import lombok.extern.slf4j.Slf4j; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; +import java.io.IOException; + +/** + * Todo . + */ +@Converter +@Slf4j +public class RuntimeOptionsConverter implements AttributeConverter { + + private final ObjectMapper mapper; + + public RuntimeOptionsConverter() { + this(new ObjectMapper()); + } + + public RuntimeOptionsConverter(final ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public String convertToDatabaseColumn(final RuntimeOptions object) { + try { + return mapper.writeValueAsString(object); + } catch (final JsonProcessingException e) { + log.error("Unable to parse component source - {}", e.getMessage(), e); + throw new FabricManagerException(e); + } + } + + @Override + public RuntimeOptions convertToEntityAttribute(final String runtimeOptions) { + try { + return mapper.readValue(runtimeOptions, RuntimeOptions.class); + } catch (final IOException e) { + log.error("Unable to parse RuntimeOptions source - {}", e.getMessage(), e); + throw new FabricManagerException(e); + } + } +} diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ApplicationDomain.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ApplicationDomain.java index 96e9e1a..da69054 100644 --- a/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ApplicationDomain.java +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ApplicationDomain.java @@ -23,6 +23,8 @@ import com.olacabs.fabric.manager.bean.ExecutorConfig; import com.olacabs.fabric.manager.bean.RuntimeOptions; +import com.olacabs.fabric.manager.converter.ExecutorConfigConverter; +import com.olacabs.fabric.manager.converter.RuntimeOptionsConverter; import lombok.*; /** @@ -45,10 +47,10 @@ public class ApplicationDomain extends TenantBaseDomain { @JoinColumn(name = "computationId") private ComputationDomain computation; -// @Convert(converter = ExecutorConfigConverter.class) + @Convert(converter = ExecutorConfigConverter.class) private ExecutorConfig executorConfig; -// @Convert(converter = RuntimeOptionsConverter.class) + @Convert(converter = RuntimeOptionsConverter.class) private RuntimeOptions runtimeOptions; private Boolean active = true; diff --git a/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/mapper/HttpExceptionMapper.java b/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/mapper/HttpExceptionMapper.java new file mode 100644 index 0000000..e4a1ad9 --- /dev/null +++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/exception/mapper/HttpExceptionMapper.java @@ -0,0 +1,48 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.exception.mapper; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.client.HttpResponseException; + +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; + +/** + * Todo . + */ +@Slf4j +public class HttpExceptionMapper implements ExceptionMapper { + + @Override + public Response toResponse(final HttpResponseException e) { + + final Response defaultResponse = + Response.serverError().entity(ImmutableMap.of("errors", ImmutableList.of(e.getMessage()))).build(); + + log.error("Error - {}", e.getMessage()); + + if (e instanceof groovyx.net.http.HttpResponseException) { + return Response.status(e.getStatusCode()) + .entity(ImmutableMap.of("errors", ImmutableList.of(e.getMessage()))).build(); + } + log.error("Stack trace - ", e); + return defaultResponse; + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/ApplicationResourceTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/ApplicationResourceTest.java new file mode 100644 index 0000000..bf0003e --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/ApplicationResourceTest.java @@ -0,0 +1,134 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.resource; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.olacabs.fabric.manager.bean.ExecutorConfig; +import com.olacabs.fabric.manager.bean.RuntimeOptions; +import com.olacabs.fabric.manager.domain.ApplicationDomain; +import com.olacabs.fabric.manager.domain.ComputationDomain; +import com.olacabs.fabric.manager.service.IApplicationService; +import com.olacabs.fabric.manager.service.IComputationService; +import mesosphere.marathon.client.model.v2.GetAppResponse; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.ws.rs.core.Response; +import java.util.Collections; +import java.util.Map; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; + +/** + * Todo . + */ +public class ApplicationResourceTest { + + private static IApplicationService applicationService = mock(IApplicationService.class); + private static IComputationService computationService = mock(IComputationService.class); + private static ExecutorConfig executorConfig = mock(ExecutorConfig.class); + private static String tenant = "tenant"; + private static String computationName = "test-computation"; + private static ApplicationDomain application; + private static ComputationDomain computation; + private static RuntimeOptions runtimeOptions; + private static ApplicationResource resource; + + @BeforeClass + public static void setUp() { + computation = new ComputationDomain(); + runtimeOptions = new RuntimeOptions(); + + application = new ApplicationDomain(); + application.setName("test-application"); + application.setTenant(tenant); + application.setComputation(computation); + application.setExecutorConfig(new ExecutorConfig()); + application.setRuntimeOptions(runtimeOptions); + + resource = new ApplicationResource(applicationService, computationService, executorConfig); + } + + @Test + public void testAppCreate() { + doReturn(ImmutableSet.of(computation)).when(computationService).search(anyString(), anyString(), anyInt()); + doReturn(application).when(applicationService).create(any(ApplicationDomain.class), anyString(), anyInt()); + + final Response response = resource.create(tenant, computationName, 2, runtimeOptions); + + Assert.assertEquals(response.getStatus(), 201); + Assert.assertEquals(response.getEntity(), application); + } + + @Test + public void testGet() { + doReturn(application).when(applicationService).get(anyString(), anyString()); + + final Response response = resource.get(application.getTenant(), application.getName()); + Assert.assertEquals(response.getStatus(), 200); + Assert.assertEquals(response.getEntity(), application); + } + + @Test + public void testGetFromMarathon() { + Map map = Collections.singletonMap("response", new GetAppResponse()); + doReturn(map).when(applicationService).getAppFromDeploymentEnv(anyString()); + + final Response response = resource.getFromMarathon(application.getTenant(), application.getName()); + Assert.assertEquals(response.getStatus(), 200); + Assert.assertEquals(response.getEntity(), map); + } + + @Test + public void testDeleteApp() { + doNothing().when(applicationService).delete(anyString(), anyString()); + + final Response response = resource.delete(application.getTenant(), application.getName()); + Assert.assertEquals(response.getStatus(), 200); + } + + @Test + public void testScaleApp() { + doNothing().when(applicationService).scale(anyString(), anyString(), anyInt()); + + final Response response = resource.scale(application.getTenant(), computationName, + ImmutableMap.of("instances", 10)); + Assert.assertEquals(response.getStatus(), 204); + } + + @Test + public void testSuspendApp() { + doNothing().when(applicationService).scale(anyString(), anyString(), anyInt()); + + final Response response = resource.suspend(application.getTenant(), computationName); + Assert.assertEquals(response.getStatus(), 204); + } + + @Test + public void testRestartApp() { + doNothing().when(applicationService).restart(anyString(), anyString(), anyBoolean()); + + final Response response = resource.restart(application.getTenant(), computationName, true); + Assert.assertEquals(response.getStatus(), 204); + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/ComponentResourceTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/ComponentResourceTest.java new file mode 100644 index 0000000..51b9c9a --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/ComponentResourceTest.java @@ -0,0 +1,109 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.resource; + +import com.google.common.collect.ImmutableSet; +import com.olacabs.fabric.compute.builder.impl.JarScanner; +import com.olacabs.fabric.manager.domain.ComponentDomain; +import com.olacabs.fabric.manager.service.IComponentService; +import com.olacabs.fabric.manager.service.impl.ComponentService; +import com.olacabs.fabric.model.common.ComponentType; +import com.olacabs.fabric.model.processor.ProcessorType; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.ws.rs.core.Response; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +/** + * Todo . + */ +public class ComponentResourceTest { + + private static IComponentService service = mock(ComponentService.class); + private static JarScanner scanner = mock(JarScanner.class); + + private static ComponentDomain component; + private static ComponentResource resource; + + @BeforeClass + public static void setUp() { + final String defaultArtifactoryPath = "temp"; + + component = new ComponentDomain(); + component.setVersion("0.1"); + component.setMemory(1L); + component.setProcessorType(ProcessorType.EVENT_DRIVEN); + component.setType(ComponentType.PROCESSOR); + component.setName("test-component"); + component.setCpu(1L); + component.setNamespace("global"); + component.setDescription("test-description"); + + resource = new ComponentResource(service, defaultArtifactoryPath, scanner); + } + + @Test + public void testValidSave() { + doReturn(component).when(service).save(any(ComponentDomain.class)); + + final Response response = resource.save(component); + Assert.assertEquals(response.getStatus(), 201); + Assert.assertEquals(response.getEntity(), component); + } + + @Test + public void testGetByVersion() { + doReturn(component).when(service).get(2); + + final Response response = resource.get(2); + Assert.assertEquals(response.getStatus(), 200); + Assert.assertEquals(response.getEntity(), component); + } + + @Test + public void testSearch() { + doReturn(ImmutableSet.of(component)).when(service).search(anyString(), anyString(), anyString()); + + final Response response = + resource.search(component.getNamespace(), component.getName(), component.getVersion()); + Assert.assertEquals(response.getStatus(), 200); + Assert.assertEquals(response.getEntity(), ImmutableSet.of(component)); + } + + @Test + public void testGet() { + doReturn(ImmutableSet.of(component)).when(service).search(anyString(), anyString(), anyString()); + + final Response response = resource.get(component.getNamespace(), component.getName(), component.getVersion()); + Assert.assertEquals(response.getStatus(), 200); + Assert.assertEquals(response.getEntity(), component); + } + + @Test + public void testAllGroupedByVersion() { + doReturn(ImmutableSet.of(component)).when(service).search(anyString(), anyString(), anyString()); + + final Response response = resource.getAllGroupedByVersion(component.getNamespace(), component.getName()); + Assert.assertEquals(response.getStatus(), 200); + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/ComputationResourceTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/ComputationResourceTest.java new file mode 100644 index 0000000..c89897b --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/ComputationResourceTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.resource; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.olacabs.fabric.manager.domain.ComputationDomain; +import com.olacabs.fabric.manager.service.IComputationService; +import com.olacabs.fabric.manager.service.impl.ComputationService; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.ws.rs.core.Response; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; + +/** + * Todo . + */ +public class ComputationResourceTest { + + private static IComputationService service = mock(ComputationService.class); + + private static ComputationDomain computation; + private static ComputationDomain updatedComputation; + private static ComputationResource resource; + private static String tenant = "tenant"; + + @BeforeClass + public static void setUp() { + computation = new ComputationDomain(); + computation.setName("test-computation"); + computation.setDescription("test-description"); + computation.setOwnerEmail("testemail@email.com"); + computation.setTenant(tenant); + computation.setAttributes(Maps.newHashMap()); + computation.setSources(Sets.newHashSet()); + computation.setProcessors(Sets.newHashSet()); + computation.setConnections(Sets.newHashSet()); + computation.setProperties(Maps.newHashMap()); + computation.setVersion(1); + + updatedComputation = computation; + updatedComputation.setDescription("test-updated-description"); + updatedComputation.setOwnerEmail("testupdatedemail@email.com"); + updatedComputation.setVersion(2); + + resource = new ComputationResource(service); + } + + @Test + public void testValidSave() { + doReturn(computation).when(service).saveOrUpdate(anyString(), any(ComputationDomain.class)); + + final Response response = resource.saveOrUpdate(tenant, computation); + Assert.assertEquals(response.getStatus(), 201); + Assert.assertEquals(response.getEntity(), computation); + } + + @Test + public void testGetByName() { + doReturn(ImmutableSet.of(computation, updatedComputation)).when(service).search(anyString(), anyString(), + anyInt()); + + final Response response = resource.getLatestByName(tenant, computation.getName(), 2); + Assert.assertEquals(response.getStatus(), 200); + Assert.assertEquals(response.getEntity(), updatedComputation); + } + + @Test + public void testDeleteById() { + doNothing().when(service).delete(anyString(), anyInt()); + + final Response response = resource.delete(tenant, 1); + Assert.assertEquals(response.getStatus(), 200); + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/GlobalPropertyResourceTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/GlobalPropertyResourceTest.java new file mode 100644 index 0000000..37e826f --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/resource/GlobalPropertyResourceTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.resource; + +import com.google.common.collect.ImmutableSet; +import com.olacabs.fabric.manager.domain.GlobalPropertyDomain; +import com.olacabs.fabric.manager.service.IGlobalPropertyService; +import com.olacabs.fabric.manager.service.impl.GlobalPropertyService; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.ws.rs.core.Response; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; + +/** + * Todo . + */ +public class GlobalPropertyResourceTest { + + private static IGlobalPropertyService service = mock(GlobalPropertyService.class); + + private static GlobalPropertyDomain globalProperty; + private static GlobalPropertyResource resource; + + @BeforeClass + public static void setUp() { + globalProperty = new GlobalPropertyDomain(); + globalProperty.setName("test.global-property"); + globalProperty.setDescription("test-description"); + + resource = new GlobalPropertyResource(service); + } + + @Test + public void testValidSave() { + doReturn(globalProperty).when(service).save(any(GlobalPropertyDomain.class)); + + final Response response = resource.save(globalProperty); + Assert.assertEquals(response.getStatus(), 201); + Assert.assertEquals(response.getEntity(), globalProperty); + } + + @Test + public void testGet() { + doReturn(globalProperty).when(service).get(anyInt()); + + final Response response = resource.get(globalProperty.getId()); + Assert.assertEquals(response.getStatus(), 200); + Assert.assertEquals(response.getEntity(), globalProperty); + } + + @Test + public void testSearch() { + doReturn(ImmutableSet.of(globalProperty)).when(service).search(anyString(), anyString()); + + final Response response = resource.search(globalProperty.getName(), globalProperty.getType()); + Assert.assertEquals(response.getStatus(), 200); + Assert.assertEquals(response.getEntity(), ImmutableSet.of(globalProperty)); + } + + @Test + public void testDeleteById() { + doNothing().when(service).delete(anyInt()); + + final Response response = resource.delete(globalProperty.getId()); + Assert.assertEquals(response.getStatus(), 200); + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/service/ApplicationServiceTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/service/ApplicationServiceTest.java new file mode 100644 index 0000000..968f81c --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/service/ApplicationServiceTest.java @@ -0,0 +1,184 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.service; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.olacabs.fabric.manager.bean.ExecutorConfig; +import com.olacabs.fabric.manager.bean.RuntimeOptions; +import com.olacabs.fabric.manager.config.ManagerConfig; +import com.olacabs.fabric.manager.config.OpenTsdbConfig; +import com.olacabs.fabric.manager.dao.IApplicationDAO; +import com.olacabs.fabric.manager.dao.impl.ApplicationDAO; +import com.olacabs.fabric.manager.domain.ApplicationDomain; +import com.olacabs.fabric.manager.domain.ComputationDomain; +import com.olacabs.fabric.manager.service.impl.ApplicationService; +import mesosphere.marathon.client.Marathon; +import mesosphere.marathon.client.model.v2.App; +import mesosphere.marathon.client.model.v2.GetAppResponse; +import mesosphere.marathon.client.model.v2.Result; +import mesosphere.marathon.client.utils.MarathonException; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Map; +import java.util.Set; + +import static org.mockito.Mockito.*; + +/** + * Application service test. + */ +public class ApplicationServiceTest { + private static IApplicationDAO applicationDAO; + private static Marathon marathon; + private static ManagerConfig managerConfig; + private static ApplicationService applicationService; + private static ApplicationDomain application; + private static ApplicationDomain updatedApplication; + private static String tenant = "tenant"; + private static ComputationDomain computation; + private static RuntimeOptions runtimeOptions; + private static OpenTsdbConfig openTsdbConfig; + private static ExecutorConfig executorConfig; + private static ComputationDomain updatedComputation; + private static GetAppResponse getAppResponse; + + @BeforeClass + public static void setUp() throws Exception { + applicationDAO = mock(ApplicationDAO.class); + marathon = mock(Marathon.class); + managerConfig = mock(ManagerConfig.class); + + getOpenTsdbConfig(); + getExecutorConfig(); + getComputation(); + getRunTimeOptions(); + getApplication(); + + applicationService = new ApplicationService(applicationDAO, marathon, managerConfig); + + final Set applicationDomainSet = Sets.newHashSet(); + applicationDomainSet.add(application); + doReturn(applicationDomainSet).when(applicationDAO).search(anyString(), anyString()); + doReturn(application).when(applicationDAO).save(any(ApplicationDomain.class)); + doNothing().when(applicationDAO).modify(any(ApplicationDomain.class)); + doNothing().when(applicationDAO).delete(any(ApplicationDomain.class)); + doNothing().when(marathon).updateApp(anyString(), any(App.class)); + doNothing().when(marathon).restartApp(anyString(), anyBoolean()); + doReturn(new Result()).when(marathon).deleteApp(anyString()); + + final App app = new App(); + app.setInstances(1); + final Map labels = Maps.newHashMap(); labels.put("version", "1"); + app.setLabels(labels); + getAppResponse = new GetAppResponse(); + getAppResponse.setApp(app); + doReturn(getAppResponse).when(marathon).getApp(anyString()); + } + + private static void getExecutorConfig() { + executorConfig = new ExecutorConfig(); + executorConfig.setExecutorDockerImage("localhost/executor:0.0.1"); + } + + private static void getOpenTsdbConfig() { + openTsdbConfig = new OpenTsdbConfig(); + openTsdbConfig.setOpenTsdbUrl("http://localhost:4242"); + } + + private static void getRunTimeOptions() { + runtimeOptions = new RuntimeOptions(); + } + + private static void getComputation() { + computation = new ComputationDomain(); + computation.setName("test-computation"); + computation.setDescription("test-description"); + computation.setOwnerEmail("testemail@email.com"); + computation.setTenant(tenant); + computation.setAttributes(Maps.newHashMap()); + computation.setSources(Sets.newHashSet()); + computation.setProcessors(Sets.newHashSet()); + computation.setConnections(Sets.newHashSet()); + computation.setProperties(Maps.newHashMap()); + + updatedComputation = computation; + updatedComputation.setDescription("test-updated-description"); + updatedComputation.setOwnerEmail("testupdatedemail@email.com"); + } + + private static void getApplication() { + application = new ApplicationDomain(); + application.setName("test-application"); + application.setTenant(tenant); + application.setComputation(computation); + application.setExecutorConfig(executorConfig); + application.setRuntimeOptions(runtimeOptions); + + updatedApplication = application; + updatedApplication.setComputation(updatedComputation); + } + + @Test + public void testAppCreate() throws MarathonException { + doThrow(new MarathonException(404, "Not Found")).doReturn(getAppResponse).when(marathon).getApp(anyString()); + doReturn(new App()).when(marathon).createApp(any(App.class)); + doReturn(openTsdbConfig).when(managerConfig).getOpenTsdbConfig(); + doReturn(executorConfig).when(managerConfig).getExecutor(); + + applicationService.create(application, tenant, 1); + } + + @Test + public void testAppUpdate() throws MarathonException { + doReturn(new App()).when(marathon).createApp(any(App.class)); + doReturn(openTsdbConfig).when(managerConfig).getOpenTsdbConfig(); + doReturn(executorConfig).when(managerConfig).getExecutor(); + + applicationService.create(updatedApplication, tenant, 1); + } + + @Test + public void testAppGet() throws MarathonException { + ApplicationDomain result = applicationService.get(application.getName(), tenant); + Assert.assertEquals(result, application); + } + + @Test + public void testAppGetFromMarathon() throws MarathonException { + Map result = applicationService.getAppFromDeploymentEnv(application.getName()); + Assert.assertTrue(result instanceof Map); + Assert.assertTrue(result.get("response") instanceof GetAppResponse); + } + + @Test + public void testAppScale() throws MarathonException { + applicationService.scale(application.getName(), tenant, 10); + } + + @Test + public void testAppRestart() throws MarathonException { + applicationService.restart(application.getName(), tenant, true); + } + + @Test + public void testAppDelete() throws MarathonException { + applicationService.delete(application.getName(), tenant); + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/service/ComponentServiceTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/service/ComponentServiceTest.java new file mode 100644 index 0000000..295a1a8 --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/service/ComponentServiceTest.java @@ -0,0 +1,111 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.service; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.olacabs.fabric.manager.dao.IComponentDAO; +import com.olacabs.fabric.manager.domain.ComponentDomain; +import com.olacabs.fabric.manager.exception.UnProcessableException; +import com.olacabs.fabric.manager.service.impl.ComponentService; +import com.olacabs.fabric.model.common.ComponentType; +import com.olacabs.fabric.model.common.sources.ArtifactoryComponentSource; +import com.olacabs.fabric.model.processor.ProcessorType; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Set; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; + +/** + * Todo . + */ +public class ComponentServiceTest { + + private static IComponentService componentService; + private static IComponentDAO componentDAO; + private static ComponentDomain component; + + @BeforeClass + public static void setUp() { + componentDAO = mock(IComponentDAO.class); + componentService = new ComponentService(componentDAO); + + component = new ComponentDomain(); + component.setSource(ArtifactoryComponentSource.builder().version("0.1").artifactoryUrl("http://test") + .artifactId("com.test").groupId("test").build()); + component.setType(ComponentType.PROCESSOR); + component.setName("test"); + component.setCpu(0.5); + component.setDescription("test-description"); + component.setNamespace("global"); + component.setMemory(1024); + component.setProcessorType(ProcessorType.EVENT_DRIVEN); + component.setOptionalProperties(ImmutableList.of("op1", "op2")); + component.setRequiredProperties(ImmutableList.of("rp1", "rp2")); + component.setVersion("0.0.1"); + + doReturn(component).when(componentDAO).save(any(ComponentDomain.class)); + doReturn(component).when(componentDAO).read(anyInt()); + } + + @Test + public void testSave() { + ComponentDomain saved = componentService.save(component); + Assert.assertEquals(saved, component); + } + + @Test + public void testGet() { + final ComponentDomain saved = componentService.get(component.getInternalId()); + Assert.assertEquals(saved, component); + } + + @Test + public void testSaveIfComponentAlreadyRegistered() { + doReturn(ImmutableSet.of(component)).when(componentDAO).search(anyString(), anyString(), anyString()); + try { + componentService.save(component); + } catch (final RuntimeException e) { + assertTrue(e instanceof UnProcessableException); + } + + // Cleanup + doReturn(ImmutableSet.of()).when(componentDAO).search(anyString(), anyString(), anyString()); + } + + @Test + public void testSearch() { + doReturn(ImmutableSet.of(component)).when(componentDAO).search(anyString(), anyString(), anyString()); + final Set result = componentService.search("test", "test", "test"); + assertTrue(result.size() == 1); + + // Cleanup + doReturn(ImmutableSet.of()).when(componentDAO).search(anyString(), anyString(), anyString()); + } + + @Test + public void testDelete() { + doReturn(ImmutableSet.of(component)).when(componentDAO).search(anyString(), anyString(), anyString()); + doNothing().when(componentDAO).delete(anyInt()); + componentService.delete("Test", "test", "test"); + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/service/ComputationServiceTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/service/ComputationServiceTest.java new file mode 100644 index 0000000..2933b2d --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/service/ComputationServiceTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.service; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.olacabs.fabric.manager.dao.IComponentDAO; +import com.olacabs.fabric.manager.dao.IComputationDAO; +import com.olacabs.fabric.manager.dao.impl.ComponentDAO; +import com.olacabs.fabric.manager.dao.impl.ComputationDAO; +import com.olacabs.fabric.manager.domain.ComputationDomain; +import com.olacabs.fabric.manager.service.impl.ComputationService; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Set; + +import static org.mockito.Mockito.*; + +/** + * Computation service test. + */ +public class ComputationServiceTest { + + private static IComputationDAO computationDAO; + private static IComponentDAO componentDAO; + private static ComputationDomain computation; + private static ComputationDomain updatedComputation; + private static ComputationService computationService; + private static String tenant = "tenant"; + + @BeforeClass + public static void setUp() { + computationDAO = mock(ComputationDAO.class); + componentDAO= mock(ComponentDAO.class); + + computation = new ComputationDomain(); + computation.setName("test-computation"); + computation.setDescription("test-description"); + computation.setOwnerEmail("testemail@email.com"); + computation.setTenant(tenant); + computation.setAttributes(Maps.newHashMap()); + computation.setSources(Sets.newHashSet()); + computation.setProcessors(Sets.newHashSet()); + computation.setConnections(Sets.newHashSet()); + computation.setProperties(Maps.newHashMap()); + + updatedComputation = computation; + updatedComputation.setDescription("test-updated-description"); + updatedComputation.setOwnerEmail("testupdatedemail@email.com"); + + computationService = new ComputationService(computationDAO, componentDAO); + } + + @Test + public void testValidSave() { + doReturn(Sets.newHashSet()).when(computationDAO).search(anyString(), anyString(), anyInt()); + doReturn(computation).when(computationDAO).save(any(ComputationDomain.class)); + + final ComputationDomain result = computationService.saveOrUpdate(tenant, computation); + Assert.assertEquals(result, computation); + } + + @Test + public void testValidUpdate() { + final Set computationDomainSet = Sets.newHashSet(); + computationDomainSet.add(computation); + doReturn(computationDomainSet).when(computationDAO).search(anyString(), anyString(), anyInt()); + doReturn(updatedComputation).when(computationDAO).save(any(ComputationDomain.class)); + + final ComputationDomain result = computationService.saveOrUpdate(tenant, updatedComputation); + Assert.assertEquals(result, updatedComputation); + } + + @Test + public void testGetById() { + doReturn(computation).when(computationDAO).get(anyInt()); + + final ComputationDomain result = computationService.getById(tenant, computation.getInternalId()); + Assert.assertEquals(result, computation); + } + + @Test + public void testSearch() { + final Set computationDomainSet = Sets.newHashSet(); + computationDomainSet.add(computation); + doReturn(computationDomainSet).when(computationDAO).search(anyString(), anyString(), anyInt()); + + final ComputationDomain result = computationService.getById(tenant, computation.getInternalId()); + Assert.assertEquals(result, computation); + } + + @Test + public void testDelete() { + doReturn(computation).when(computationDAO).get(anyInt()); + doNothing().when(computationDAO).delete(any(ComputationDomain.class)); + computationService.delete(tenant, computation.getInternalId()); + } +} diff --git a/fabric-manager/src/test/java/com/olacabs/fabric/manager/service/GlobalPropertyServiceTest.java b/fabric-manager/src/test/java/com/olacabs/fabric/manager/service/GlobalPropertyServiceTest.java new file mode 100644 index 0000000..9c91d39 --- /dev/null +++ b/fabric-manager/src/test/java/com/olacabs/fabric/manager/service/GlobalPropertyServiceTest.java @@ -0,0 +1,82 @@ +/* + * Copyright 2016 ANI Technologies 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 com.olacabs.fabric.manager.service; + +import com.google.common.collect.ImmutableSet; +import com.olacabs.fabric.manager.dao.IGlobalPropertyDAO; +import com.olacabs.fabric.manager.dao.impl.GlobalPropertyDAO; +import com.olacabs.fabric.manager.domain.GlobalPropertyDomain; +import com.olacabs.fabric.manager.service.impl.GlobalPropertyService; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Set; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; + +/** + * Todo. + */ +public class GlobalPropertyServiceTest { + private static IGlobalPropertyDAO globalPropertyDAO; + private static IGlobalPropertyService globalPropertyService; + private static GlobalPropertyDomain globalProperty; + + @BeforeClass + public static void setUp() throws Exception { + globalPropertyDAO = mock(GlobalPropertyDAO.class); + + globalProperty = new GlobalPropertyDomain(); + globalProperty.setName("test.global-property"); + globalProperty.setDescription("test-description"); + + doReturn(globalProperty).when(globalPropertyDAO).save(any(GlobalPropertyDomain.class)); + doReturn(globalProperty).when(globalPropertyDAO).get(anyInt()); + doReturn(ImmutableSet.of(globalProperty)).when(globalPropertyDAO).search(anyString(), anyString()); + doNothing().when(globalPropertyDAO).delete(any(GlobalPropertyDomain.class)); + + globalPropertyService = new GlobalPropertyService(globalPropertyDAO); + } + + @Test + public void testSave() { + final GlobalPropertyDomain saved = globalPropertyService.save(globalProperty); + Assert.assertEquals(saved, globalProperty); + } + + @Test + public void testGet() { + final GlobalPropertyDomain saved = globalPropertyService.get(globalProperty.getId()); + Assert.assertEquals(saved, globalProperty); + } + + @Test + public void testSearch() { + final Set search = globalPropertyService.search(globalProperty.getName(), + globalProperty.getType()); + Assert.assertEquals(search, ImmutableSet.of(globalProperty)); + } + + @Test + public void testDelete() { + globalPropertyService.delete(globalProperty.getId()); + } +} From 7dcd903e127be58f191d214015957f60af30c2e4 Mon Sep 17 00:00:00 2001 From: "shashank.g" Date: Fri, 4 Nov 2016 13:14:04 +0530 Subject: [PATCH 3/6] cleaning data From c4963e867aa19cba36eb14761842ff501ff73780 Mon Sep 17 00:00:00 2001 From: "shashank.g" Date: Fri, 4 Nov 2016 13:19:40 +0530 Subject: [PATCH 4/6] pom and docker file fix --- fabric-manager/DockerFile | 2 +- fabric-manager/pom.xml | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fabric-manager/DockerFile b/fabric-manager/DockerFile index d6ef194..843ff7d 100644 --- a/fabric-manager/DockerFile +++ b/fabric-manager/DockerFile @@ -13,7 +13,7 @@ #limitations under the License. FROM ubuntu:14.04 -MAINTAINER shashank.g@olacabs.com +MAINTAINER maintainer@fabric.com RUN apt-get update --fix-missing \ && apt-get install -y --no-install-recommends software-properties-common \ diff --git a/fabric-manager/pom.xml b/fabric-manager/pom.xml index f19ed56..f681a33 100644 --- a/fabric-manager/pom.xml +++ b/fabric-manager/pom.xml @@ -48,6 +48,8 @@ 0.9.1.2 1.9.5 2.5.3 + 0.7.0 + 1.1.0.Final @@ -55,14 +57,14 @@ io.federecio dropwizard-swagger - 0.7.0 + ${swagger.version} javax.validation validation-api - 1.1.0.Final + ${java.validation.version} From 1141fa9e14c9591df7bdccc1f839045405d32ea8 Mon Sep 17 00:00:00 2001 From: "shashank.g" Date: Fri, 4 Nov 2016 14:36:30 +0530 Subject: [PATCH 5/6] details of archetype in readme.md --- README.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d53d35..c7bdc72 100644 --- a/README.md +++ b/README.md @@ -343,4 +343,22 @@ End to end latency to process all messages in seconds (ceiling) averaged over mu Throughput with best configuration T ~ 166666 events / second
-NOTE: Using Disruptor with YieldWaitingStategy instead of LBQ for channel communication actually reduced the throughput
+NOTE: Using Disruptor with YieldWaitingStrategy instead of LBQ for channel communication actually reduced the throughput
+ +###Using Processor Maven Archetype + +To create a processor project, please run following command - + +``` +mvn archetype:generate -DarchetypeGroupId=com.olacabs.fabric -DarchetypeArtifactId=fabric-processor-archetype -DarchetypeVersion=0.0.1-SNAPSHOT -DartifactId= -DgroupId= -DinteractiveMode=ture +``` +Example - + +``` +mvn archetype:generate -DarchetypeGroupId=com.olacabs.fabric -DarchetypeArtifactId=fabric-processor-archetype -DarchetypeVersion=0.0.1-SNAPSHOT -DartifactId=fabric-my-processor -DgroupId=com.olacabs.fabric -DinteractiveMode=ture +``` +What it does - + - Creates the pom project for the processor with all the updated version of compute and other related jars. + - Creates boiler plate code, with example, for scheduled and stream processor. You can modify the example java file as per your need. + + From 5f7f5b3fe1b73126366d4c80d3c2ef3332c9350f Mon Sep 17 00:00:00 2001 From: "shashank.g" Date: Fri, 4 Nov 2016 16:44:19 +0530 Subject: [PATCH 6/6] removing duplicates from build section --- .../fabric-manager.postman_collection | 447 ++++++++++++++++++ fabric-manager/pom.xml | 22 - 2 files changed, 447 insertions(+), 22 deletions(-) create mode 100644 fabric-manager/api-samples/fabric-manager.postman_collection diff --git a/fabric-manager/api-samples/fabric-manager.postman_collection b/fabric-manager/api-samples/fabric-manager.postman_collection new file mode 100644 index 0000000..b9c9cdf --- /dev/null +++ b/fabric-manager/api-samples/fabric-manager.postman_collection @@ -0,0 +1,447 @@ +/* + * Copyright 2016 ANI Technologies 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. + */ + +{ + "variables": [], + "info": { + "name": "fabric-manager", + "_postman_id": "61e3ebf1-b163-c77d-1af7-01e8da450b0b", + "description": "", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" + }, + "item": [ + { + "name": "applications", + "description": "", + "item": [ + { + "name": "Deploy saved computation", + "request": { + "url": "http://localhost:18000/v1/applications/{tenant}/{computation-name}", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + }, + { + "key": "X-User", + "value": "sumanbn", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"instances\": 3,\n\t\"topologyCpu\": 0.75,\n\t\"topologyMemory\": 1024\n}" + }, + "description": "deploy a computation" + }, + "response": [] + }, + { + "name": "Get details of deployed/running computation", + "request": { + "url": "http://localhost:18000/v1/applications/{tenant}/{computation-name}", + "method": "GET", + "header": [ + { + "key": "X-Tenant-Key", + "value": "joiner", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "description": "get deployed/running computation details" + }, + "response": [] + }, + { + "name": "Get marathon application details for running computation", + "request": { + "url": "http://localhost:18000/v1/applications/{tenant}/{computation-name}/marathon", + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "description": "Get marathon application details for running computation" + }, + "response": [] + }, + { + "name": "Scale up/down the instances of running computation", + "request": { + "url": "http://localhost:18000/v1/applications/{tenant}/{computation-name}/scale", + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + }, + { + "key": "X-User", + "value": "sumanbn", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"instances\": 1\n}" + }, + "description": "Scale up/down the instances of running computation" + }, + "response": [] + }, + { + "name": "Suspend a deployed/running computation", + "request": { + "url": "http://localhost:18000/v1/applications/{tenant}/{computation-name}/suspend", + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + }, + { + "key": "X-User", + "value": "sumanbn", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "description": "Suspend a deployed/running computation" + }, + "response": [] + }, + { + "name": "Restart a running computation", + "request": { + "url": "http://localhost:18000/v1/applications/{tenant}/{computation-name}/restart", + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + }, + { + "key": "X-User", + "value": "sumanbn", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "description": "Restart a running computation" + }, + "response": [] + }, + { + "name": "Delete a deployed computation", + "request": { + "url": "http://localhost:18000/v1/applications/{tenant}/{computation-name}", + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + }, + { + "key": "X-User", + "value": "sumanbn", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "description": "delete a deployed computation(delete app from marathon)" + }, + "response": [] + } + ] + }, + { + "name": "components", + "description": "", + "item": [ + { + "name": "Save component", + "request": { + "url": "localhost:18000/v1/components", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + }, + { + "key": "X-User", + "value": "sumanbn", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"namespace\": \"global\",\n \"name\": \"sample-component\",\n \"version\": \"0.0.1\",\n \"type\": \"PROCESSOR\",\n \"description\": \"Sample processor\",\n \"processorType\": \"EVENT_DRIVEN\",\n \"requiredProperties\": [\n \"required_property1\"\n ],\n \"optionalProperties\": [\n \"optional_property1\"\n ],\n \"cpu\": 1,\n \"memory\": 512,\n \"source\": {\n \"type\": \"artifactory\",\n \"artifactoryUrl\": \"http://localhost:8080/artifactory\",\n \"groupId\": \"com.olacabs\",\n \"artifactId\": \"sample-processor\",\n \"version\": \"0.0.1-SNAPSHOT\"\n }\n}" + }, + "description": "Save component" + }, + "response": [] + }, + { + "name": "Register component from artifact", + "request": { + "url": "localhost:18000/v1/components/artifact", + "method": "POST", + "header": [ + { + "key": "X-User", + "value": "user", + "description": "" + }, + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"groupId\": \"com.olacabs.fabric\",\n\t\"artifactId\": \"sample-processor\",\n\t\"version\": \"0.0.1\"\n}" + }, + "description": "register component from artifact" + }, + "response": [] + }, + { + "name": "Register component by URL", + "request": { + "url": "localhost:18000/v1/components/register?url=", + "method": "POST", + "header": [ + { + "key": "X-User", + "value": "suman", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "description": "register component" + }, + "response": [] + }, + { + "name": "Get all components", + "request": { + "url": "localhost:18000/v1/components", + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"id\": \"75cc56e6-6b72-44f3-8db5-45f55b5d5dc4\",\n \"metadata\": {\n \"timestamp\": 1477473295342,\n \"schema\": \"book_joiner\",\n \"schemaVersion\": 1,\n \"type\": \"EVENT\",\n \"routingKey\": {\n \"type\": \"simple\",\n \"value\": \"1477473295342\"\n },\n \"lookupKey\": null,\n \"tenant\": \"joiner\",\n \"stream\": \"book_joiner\",\n \"sender\": null\n },\n \"data\": {\n\t\"bookingId\": \"bookingId1\",\n\t\"city\": \"blore\",\n\t\"bookId\": \"book1\"\n }\n}" + }, + "description": "get all components" + }, + "response": [] + }, + { + "name": "Get component by Id", + "request": { + "url": "localhost:18000/v1/components/{id}", + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"id\": \"75cc56e6-6b72-44f3-8db5-45f55b5d5dc4\",\n \"metadata\": {\n \"timestamp\": 1477473295342,\n \"schema\": \"book_joiner\",\n \"schemaVersion\": 1,\n \"type\": \"EVENT\",\n \"routingKey\": {\n \"type\": \"simple\",\n \"value\": \"1477473295342\"\n },\n \"lookupKey\": null,\n \"tenant\": \"joiner\",\n \"stream\": \"book_joiner\",\n \"sender\": null\n },\n \"data\": {\n\t\"bookingId\": \"bookingId1\",\n\t\"city\": \"blore\",\n\t\"bookId\": \"book1\"\n }\n}" + }, + "description": "Get component by Id" + }, + "response": [] + }, + { + "name": "Get all versions of all components", + "request": { + "url": "localhost:18000/v1/components/versions", + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"id\": \"75cc56e6-6b72-44f3-8db5-45f55b5d5dc4\",\n \"metadata\": {\n \"timestamp\": 1477473295342,\n \"schema\": \"book_joiner\",\n \"schemaVersion\": 1,\n \"type\": \"EVENT\",\n \"routingKey\": {\n \"type\": \"simple\",\n \"value\": \"1477473295342\"\n },\n \"lookupKey\": null,\n \"tenant\": \"joiner\",\n \"stream\": \"book_joiner\",\n \"sender\": null\n },\n \"data\": {\n\t\"bookingId\": \"bookingId1\",\n\t\"city\": \"blore\",\n\t\"bookId\": \"book1\"\n }\n}" + }, + "description": "Get all versions of all components" + }, + "response": [] + }, + { + "name": "Get a component by namespace, name and version", + "request": { + "url": "localhost:18000/v1/components/{namespace}/{name}/{version}", + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"id\": \"75cc56e6-6b72-44f3-8db5-45f55b5d5dc4\",\n \"metadata\": {\n \"timestamp\": 1477473295342,\n \"schema\": \"book_joiner\",\n \"schemaVersion\": 1,\n \"type\": \"EVENT\",\n \"routingKey\": {\n \"type\": \"simple\",\n \"value\": \"1477473295342\"\n },\n \"lookupKey\": null,\n \"tenant\": \"joiner\",\n \"stream\": \"book_joiner\",\n \"sender\": null\n },\n \"data\": {\n\t\"bookingId\": \"bookingId1\",\n\t\"city\": \"blore\",\n\t\"bookId\": \"book1\"\n }\n}" + }, + "description": "Get a component by namespace, name and version" + }, + "response": [] + } + ] + }, + { + "name": "computations", + "description": "", + "item": [ + { + "name": "Save computation", + "request": { + "url": "localhost:18000/v1/computations/{tenant}", + "method": "POST", + "header": [ + { + "key": "X-User", + "value": "sumanbn", + "description": "" + }, + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"computation-name\",\n \"ownerEmail\": \"user@email.com\",\n \"description\": \"Sample decriptionn\",\n \"attributes\": {},\n \"sources\": [\n {\n \"componentId\": 5,\n \"id\": \"source\",\n \"properties\": {\n \"source.source.brokers\": \"localhost:9092\",\n \"source.source.zookeeper\": \"localhost:2181\",\n \"source.source.topic-name\": \"sample-topic\"\n }\n }\n ],\n \"processors\": [\n {\n \"componentId\": 6,\n \"id\": \"processor\",\n \"properties\": {\n \"processor.processor.serviceName\": \"sample-service\",\n \"processor.processor.zookeeper\": \"localhost:2181\",\n \"processor.processor.environment\": \"stage\"\n }\n }\n ],\n \"connections\": [\n {\n \"fromType\": \"SOURCE\",\n \"from\": \"source\",\n \"to\": \"processor\"\n }\n ],\n \"properties\": {}\n}" + }, + "description": "Save computation" + }, + "response": [] + }, + { + "name": "Get all computations under a tenant", + "request": { + "url": "localhost:18000/v1/computations/{tenant}", + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"id\": \"75cc56e6-6b72-44f3-8db5-45f55b5d5dc4\",\n \"metadata\": {\n \"timestamp\": 1477473295342,\n \"schema\": \"book_joiner\",\n \"schemaVersion\": 1,\n \"type\": \"EVENT\",\n \"routingKey\": {\n \"type\": \"simple\",\n \"value\": \"1477473295342\"\n },\n \"lookupKey\": null,\n \"tenant\": \"joiner\",\n \"stream\": \"book_joiner\",\n \"sender\": null\n },\n \"data\": {\n\t\"bookingId\": \"bookingId1\",\n\t\"city\": \"blore\",\n\t\"bookId\": \"book1\"\n }\n}" + }, + "description": "Get all computations under a tenant" + }, + "response": [] + }, + { + "name": "Get computation by Id within tenant", + "request": { + "url": "localhost:18000/v1/computations/{tenant}/id/{id}", + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"id\": \"75cc56e6-6b72-44f3-8db5-45f55b5d5dc4\",\n \"metadata\": {\n \"timestamp\": 1477473295342,\n \"schema\": \"book_joiner\",\n \"schemaVersion\": 1,\n \"type\": \"EVENT\",\n \"routingKey\": {\n \"type\": \"simple\",\n \"value\": \"1477473295342\"\n },\n \"lookupKey\": null,\n \"tenant\": \"joiner\",\n \"stream\": \"book_joiner\",\n \"sender\": null\n },\n \"data\": {\n\t\"bookingId\": \"bookingId1\",\n\t\"city\": \"blore\",\n\t\"bookId\": \"book1\"\n }\n}" + }, + "description": "Get computation by Id within tenant" + }, + "response": [] + }, + { + "name": "Delete computation by ID within tenant", + "request": { + "url": "localhost:18000/v1/computations/{tenant}/{id}", + "method": "DELETE", + "header": [ + { + "key": "X-User", + "value": "user", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"id\": \"75cc56e6-6b72-44f3-8db5-45f55b5d5dc4\",\n \"metadata\": {\n \"timestamp\": 1477473295342,\n \"schema\": \"book_joiner\",\n \"schemaVersion\": 1,\n \"type\": \"EVENT\",\n \"routingKey\": {\n \"type\": \"simple\",\n \"value\": \"1477473295342\"\n },\n \"lookupKey\": null,\n \"tenant\": \"joiner\",\n \"stream\": \"book_joiner\",\n \"sender\": null\n },\n \"data\": {\n\t\"bookingId\": \"bookingId1\",\n\t\"city\": \"blore\",\n\t\"bookId\": \"book1\"\n }\n}" + }, + "description": "delete computation by ID within tenant" + }, + "response": [] + }, + { + "name": "Get latest computation by name within tenant", + "request": { + "url": "localhost:18000/v1/computations/{tenant}/{name}", + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"id\": \"75cc56e6-6b72-44f3-8db5-45f55b5d5dc4\",\n \"metadata\": {\n \"timestamp\": 1477473295342,\n \"schema\": \"book_joiner\",\n \"schemaVersion\": 1,\n \"type\": \"EVENT\",\n \"routingKey\": {\n \"type\": \"simple\",\n \"value\": \"1477473295342\"\n },\n \"lookupKey\": null,\n \"tenant\": \"joiner\",\n \"stream\": \"book_joiner\",\n \"sender\": null\n },\n \"data\": {\n\t\"bookingId\": \"bookingId1\",\n\t\"city\": \"blore\",\n\t\"bookId\": \"book1\"\n }\n}" + }, + "description": "Get latest computation by name within tenant" + }, + "response": [] + } + ] + } + ] +} diff --git a/fabric-manager/pom.xml b/fabric-manager/pom.xml index f681a33..d5859b1 100644 --- a/fabric-manager/pom.xml +++ b/fabric-manager/pom.xml @@ -159,28 +159,6 @@ - - org.projectlombok - lombok-maven-plugin - 1.16.4.1 - - - generate-sources - - delombok - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.3 - - 1.8 - 1.8 - - org.apache.maven.plugins maven-shade-plugin