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.
+
+
diff --git a/fabric-manager/DockerFile b/fabric-manager/DockerFile
new file mode 100644
index 0000000..843ff7d
--- /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 maintainer@fabric.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/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/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/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/pom.xml b/fabric-manager/pom.xml
new file mode 100644
index 0000000..d5859b1
--- /dev/null
+++ b/fabric-manager/pom.xml
@@ -0,0 +1,208 @@
+
+
+
+
+
+ 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
+ 0.7.0
+ 1.1.0.Final
+
+
+
+
+
+ io.federecio
+ dropwizard-swagger
+ ${swagger.version}
+
+
+
+
+ javax.validation
+ validation-api
+ ${java.validation.version}
+
+
+
+
+ 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.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..ecc543c
--- /dev/null
+++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/App.java
@@ -0,0 +1,154 @@
+/*
+ * 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.HttpExceptionMapper;
+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/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/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/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/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..da69054
--- /dev/null
+++ b/fabric-manager/src/main/java/com/olacabs/fabric/manager/domain/ApplicationDomain.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.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 com.olacabs.fabric.manager.converter.ExecutorConfigConverter;
+import com.olacabs.fabric.manager.converter.RuntimeOptionsConverter;
+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/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/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/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());
+ }
+}
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 @@
-
-
-
-
+
+
+
+