From 121a1193e12151ee05db2ebe994ca04cfdd055ec Mon Sep 17 00:00:00 2001 From: tobilg Date: Mon, 16 Jan 2017 10:34:01 +0100 Subject: [PATCH] Regenerated JS docs --- docs/Executor.html | 4 +- docs/Mesos.html | 4 +- docs/Scheduler.html | 30 ++--- docs/TaskHealthHelper.html | 244 ++++++++++++++++++++++++++++++++++ docs/TaskHelper.html | 8 +- docs/executor.js.html | 4 +- docs/index.html | 12 +- docs/mesos.js.html | 4 +- docs/scheduler.js.html | 58 ++++++-- docs/taskHealthHelper.js.html | 195 +++++++++++++++++++++++++++ docs/taskHelper.js.html | 21 ++- 11 files changed, 527 insertions(+), 57 deletions(-) create mode 100644 docs/TaskHealthHelper.html create mode 100644 docs/taskHealthHelper.js.html diff --git a/docs/Executor.html b/docs/Executor.html index 84a7bab..dcbf7bf 100644 --- a/docs/Executor.html +++ b/docs/Executor.html @@ -23,7 +23,7 @@
@@ -561,7 +561,7 @@
Parameters:

- Documentation generated by JSDoc 3.4.3 on Fri Dec 30 2016 13:57:21 GMT+0100 (CET) using the Minami theme. + Documentation generated by JSDoc 3.4.3 on Mon Jan 16 2017 10:33:15 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/Mesos.html b/docs/Mesos.html index 1404da0..05a3d7b 100644 --- a/docs/Mesos.html +++ b/docs/Mesos.html @@ -23,7 +23,7 @@
@@ -499,7 +499,7 @@
Returns:

- Documentation generated by JSDoc 3.4.3 on Fri Dec 30 2016 13:57:21 GMT+0100 (CET) using the Minami theme. + Documentation generated by JSDoc 3.4.3 on Mon Jan 16 2017 10:33:15 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/Scheduler.html b/docs/Scheduler.html index c0d3891..ec97d8d 100644 --- a/docs/Scheduler.html +++ b/docs/Scheduler.html @@ -23,7 +23,7 @@
@@ -349,7 +349,7 @@
Parameters:
Source:
@@ -480,7 +480,7 @@
Parameters:
Source:
@@ -634,7 +634,7 @@
Parameters:
Source:
@@ -716,7 +716,7 @@

getRun
Source:
@@ -893,7 +893,7 @@

Parameters:
Source:
@@ -1070,7 +1070,7 @@
Parameters:
Source:
@@ -1225,7 +1225,7 @@
Parameters:
Source:
@@ -1356,7 +1356,7 @@
Parameters:
Source:
@@ -1438,7 +1438,7 @@

reviveSource:
@@ -1593,7 +1593,7 @@
Parameters:
Source:
@@ -1675,7 +1675,7 @@

subscribeSource:
@@ -1757,7 +1757,7 @@

syncSource:
@@ -1840,7 +1840,7 @@

teardownSource:
@@ -1884,7 +1884,7 @@

teardown
- Documentation generated by JSDoc 3.4.3 on Fri Dec 30 2016 13:57:21 GMT+0100 (CET) using the Minami theme. + Documentation generated by JSDoc 3.4.3 on Mon Jan 16 2017 10:33:15 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/TaskHealthHelper.html b/docs/TaskHealthHelper.html new file mode 100644 index 0000000..d0abc17 --- /dev/null +++ b/docs/TaskHealthHelper.html @@ -0,0 +1,244 @@ + + + + + TaskHealthHelper - Documentation + + + + + + + + + + + + + + + + + +
+ +

TaskHealthHelper

+ + + + + + + +
+ +
+ +

+ TaskHealthHelper +

+ + +
+ +
+
+ + + + + +

new TaskHealthHelper(scheduler, options)

+ + + + + +
+

Represents a TaskHealthHelper object

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
scheduler + + +object + + + +

The scheduler object.

options + + +object + + + +

The option map object.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.4.3 on Mon Jan 16 2017 10:33:16 GMT+0100 (CET) using the Minami theme. +
+ + + + + \ No newline at end of file diff --git a/docs/TaskHelper.html b/docs/TaskHelper.html index 6a48823..4f0bc58 100644 --- a/docs/TaskHelper.html +++ b/docs/TaskHelper.html @@ -23,7 +23,7 @@
@@ -303,7 +303,7 @@
Parameters:
Source:
@@ -516,7 +516,7 @@
Parameters:
Source:
@@ -560,7 +560,7 @@
Parameters:

- Documentation generated by JSDoc 3.4.3 on Fri Dec 30 2016 13:57:21 GMT+0100 (CET) using the Minami theme. + Documentation generated by JSDoc 3.4.3 on Mon Jan 16 2017 10:33:16 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/executor.js.html b/docs/executor.js.html index 162cf08..73c909b 100644 --- a/docs/executor.js.html +++ b/docs/executor.js.html @@ -23,7 +23,7 @@
@@ -333,7 +333,7 @@

executor.js


- Documentation generated by JSDoc 3.4.3 on Fri Dec 30 2016 13:57:21 GMT+0100 (CET) using the Minami theme. + Documentation generated by JSDoc 3.4.3 on Mon Jan 16 2017 10:33:15 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/index.html b/docs/index.html index d494f37..345c726 100644 --- a/docs/index.html +++ b/docs/index.html @@ -23,7 +23,7 @@
@@ -47,7 +47,8 @@

Home

Classes

  • -

    mesos-framework

    This project provides a high-level wrapper around the Mesos HTTP APIs for schedulers and executors. +

    mesos-framework

    Package version Package downloads Package license Build Status

    +

    This project provides a high-level wrapper around the Mesos HTTP APIs for schedulers and executors. It can be used to write Mesos frameworks in pure JavaScript. The currently supported Mesos versions are those >= 0.28.2.

    Installation

    You can use mesos-framework in your own projects by running

    npm i mesos-framework --save

    Documentation

    The mesos-framework project is not a Mesos framework itself, but can be imagined as a "framework-framework" (or meta framework), meaning that it provides a certain abstraction around the HTTP APIs for schedulers and executors, together with some convenience methods.

    @@ -78,6 +79,8 @@

    Scheduler

    The Scheduler is the "heart" of a Me

  • frameworkFailoverTimeout: The number of seconds to wait before a framework is considered as failed by the leading Mesos master, which will then terminate the existing tasks/executors (default: 604800).
  • tasks: An object (map) with the task info (see below). It's possible to create different (prioritized) tasks, e.g. launching different containers with different instance counts. See the Docker Scheduler example.
  • handlers: An object containing custom handler functions for the Scheduler events, where the property name is the uppercase Event name.
  • +
  • staticPorts: A boolean to indicate whether to use fixed ports in the framework or not. Default is false.
  • +
  • serialNumberedTasks: A boolean to indicate whether to add a task serial number to the task name launched in mesos (from the framework's prespective there are always serial numbers in use, they are also part of the task IDs), disabling this is useful for service access with a single mesos DNS name. Defaults to true.

A tasks sub-object can contain objects with task information:

    @@ -87,7 +90,7 @@

    Scheduler

    The Scheduler is the "heart" of a Me

  • commandInfo: A Mesos.CommandInfo definition (mandatory).
  • containerInfo: A Mesos.ContainerInfo definition.
  • executorInfo: A Mesos.ExecutorInfo definition.
  • -
  • resources: The array of Mesos.Resource definitions (mandatory).
  • +
  • resources: The object of Mesos.Resource types, such as cpu, mem, ports and disk (mandatory) with an optional fixedPorts number array (included in the general port count).
  • portMappings: The array of portMapping objects, each containing a numeric port value (for container ports), and a protocol string (either tcp or udp).
  • healthChecks: A Mesos.HealthCheck definition.
  • labels: A Mesos.Labels definition.
  • @@ -123,6 +126,7 @@

    Events

    Events from Master
    The following events fr

  • sent_request: Is emitted when the scheduler has sent a REQUEST request to the Master to request new resources.
  • updated_task: Is emitted when a task was updated. Contains an object with taskId, executorId and state.
  • removed_task: Is emitted when a task was removed. Contains the taskId.
  • +
  • task_launched: Is emitted when a task moves to the running state, to handle initialization. Contains the task structure.

Example

Also, you can have a look at the examples folder to see examples for command-based and Docker-based schedulers.

"use strict";
@@ -257,7 +261,7 @@ 

Mesos

The module also exposes the Mesos protocol buffer object, which

- Documentation generated by JSDoc 3.4.3 on Fri Dec 30 2016 13:57:21 GMT+0100 (CET) using the Minami theme. + Documentation generated by JSDoc 3.4.3 on Mon Jan 16 2017 10:33:15 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/mesos.js.html b/docs/mesos.js.html index f15f5a4..f5f825f 100644 --- a/docs/mesos.js.html +++ b/docs/mesos.js.html @@ -23,7 +23,7 @@
@@ -99,7 +99,7 @@

mesos.js


- Documentation generated by JSDoc 3.4.3 on Fri Dec 30 2016 13:57:21 GMT+0100 (CET) using the Minami theme. + Documentation generated by JSDoc 3.4.3 on Mon Jan 16 2017 10:33:15 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/scheduler.js.html b/docs/scheduler.js.html index 09a3e7e..61649b5 100644 --- a/docs/scheduler.js.html +++ b/docs/scheduler.js.html @@ -23,7 +23,7 @@
@@ -75,12 +75,24 @@

scheduler.js

self.options.frameworkFailoverTimeout = options.frameworkFailoverTimeout || 604800; // One week self.options.masterConnectionTimeout = options.masterConnectionTimeout*1000 || 10000; // Ten seconds self.options.killUnknownTasks = options.killUnknownTasks || false; + self.options.serialNumberedTasks = (options.serialNumberedTasks === false) ? false : true; // ZooKeeper self.options.useZk = options.useZk || false; self.options.zkUrl = options.zkUrl || "master.mesos:2181"; self.options.zkPrefix = options.zkPrefix || "/dcos-service-"; + // Logging + self.logger = helpers.getLogger((options.logging && options.logging.path ? options.logging.path : null), (options.logging && options.logging.fileName ? options.logging.fileName : null), (options.logging && options.logging.level ? options.logging.level : null)); + + + // Port allocation + self.options.staticPorts = options.staticPorts || false; + + if (self.options.staticPorts){ + self.logger.info("Scheduler configured with fixed ports"); + } + // Master discovery self.options.masterUrl = options.masterUrl || "127.0.0.1"; self.options.port = parseInt(options.port) || 5050; @@ -91,9 +103,6 @@

scheduler.js

self.lastHeartbeat = null; self.zkClient = null; - // Logging - self.logger = helpers.getLogger((options.logging && options.logging.path ? options.logging.path : null), (options.logging && options.logging.fileName ? options.logging.fileName : null), (options.logging && options.logging.level ? options.logging.level : null)); - // Tasks self.tasks = []; @@ -340,6 +349,9 @@

scheduler.js

} else if (event.type === "MESSAGE") { // Emit with usable message object (parsed to ascii) self.emit("message", { agentId: event[event.type.toLocaleLowerCase()].agent_id, executorId: event[event.type.toLocaleLowerCase()].executor_id, data: new Buffer(event[event.type.toLocaleLowerCase()].data, "base64").toString("ascii") }); + } else if (event.type === "ERROR") { + // Emit an actual error object to identify errors from mesos master + self.emit("error", new Error("Error received from Mesos master: " + event[event.type.toLocaleLowerCase()].message)); } else { // Emit original objects for all other types self.emit(event.type.toLocaleLowerCase(), event[event.type.toLocaleLowerCase()]); @@ -380,6 +392,8 @@

scheduler.js

} + var handledTimeout = false; + self.httpRequest = http.request(self.requestTemplate, function (res) { self.logger.info("SUBSCRIBE: Response status: " + res.statusCode); @@ -408,11 +422,14 @@

scheduler.js

// Local cache for chunked JSON messages var cache = ""; + var expectedLength = 0; // Watch for data/chunks res.on('data', function (chunk) { - var expectedLength = 0; + if (chunk instanceof Buffer) { + chunk = chunk.toString(); + } if (chunk.indexOf("\n") > -1) { var temp = chunk.split("\n"); @@ -424,6 +441,7 @@

scheduler.js

} else { // Empty cache cache = ""; + expectedLength = 0; // Handle event handleEvent(temp[1]); } @@ -431,13 +449,17 @@

scheduler.js

self.emit("error", { message: "Other linebreak count found than expected! Actual count: " + temp.length }); } } else { - if (cache.length > 0) { - // Concatenate cached partial data with this chunk + if (cache.length > 0 && (cache.length + chunk.length) >= expectedLength) { + // Concatenate cached partial data with this chunk and handle only when done var eventData = cache + chunk; // Handle event handleEvent(eventData); // Empty cache cache = ""; + expectedLength = 0; + } else if (cache.length > 0 && (cache.length + chunk.length) < expectedLength) { + // Concatenate cached data with current chunk, for cases in which the stream buffer is smaller than the data. + cache += chunk; } } }); @@ -445,8 +467,14 @@

scheduler.js

res.on('end', function () { self.emit("error", { message: "Long-running connection was closed!" }); self.logger.info("Long-running connection was closed!"); - // Re-subscribe - self.subscribe(); + if (!handledTimeout) { + // Re-subscribe + // We need to remove the stream id from the headers before re-subscribing! + self.mesosStreamId = undefined; + delete self.requestTemplate.headers["mesos-stream-id"]; + delete self.requestTemplate.headers["Mesos-Stream-Id"]; + self.subscribe(); + } }); res.on('finish', function () { @@ -480,13 +508,15 @@

scheduler.js

socket.setTimeout(self.options.masterConnectionTimeout); socket.on('timeout', function() { self.logger.error("Received a timeout on the long-running Master connection! Will try to re-register the framework scheduler!"); - - // We need to remove the stream id from the headers before re-subscribing! - self.mesosStreamId = undefined; - delete self.requestTemplate.headers["mesos-stream-id"]; + handledTimeout = true; + socket.destroy(); // If we're using Mesos DNS, we can directy re-register, because Mesos DNS will discover the current leader automatically if (self.options.masterUrl === "leader.mesos") { + // We need to remove the stream id from the headers before re-subscribing! + self.mesosStreamId = undefined; + delete self.requestTemplate.headers["mesos-stream-id"]; + delete self.requestTemplate.headers["Mesos-Stream-Id"]; self.logger.info("Using Mesos DNS, will re-register to 'leader.mesos'!"); // Subscribe self.subscribe(); @@ -938,7 +968,7 @@

scheduler.js


- Documentation generated by JSDoc 3.4.3 on Fri Dec 30 2016 13:57:21 GMT+0100 (CET) using the Minami theme. + Documentation generated by JSDoc 3.4.3 on Mon Jan 16 2017 10:33:15 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/taskHealthHelper.js.html b/docs/taskHealthHelper.js.html new file mode 100644 index 0000000..0d2e29d --- /dev/null +++ b/docs/taskHealthHelper.js.html @@ -0,0 +1,195 @@ + + + + + taskHealthHelper.js - Documentation + + + + + + + + + + + + + + + + + +
+ +

taskHealthHelper.js

+ + + + + + + +
+
+
"use strict";
+
+var http = require("http");
+
+/**
+ * Represents a TaskHealthHelper object
+ * @constructor
+ * @param {object} scheduler - The scheduler object.
+ * @param {object} options - The option map object.
+ */
+function TaskHealthHelper(scheduler, options) {
+    if (!(this instanceof TaskHealthHelper)) {
+        return new TaskHealthHelper(scheduler, options);
+    }
+
+    var self = this;
+
+    self.scheduler = scheduler;
+    self.logger = scheduler.logger;
+    self.options = {};
+    self.options.interval = options.interval || 30;
+    self.options.graceCount = options.graceCount || 4;
+    self.options.portIndex = options.portIndex || 0;
+    self.options.errorEvent = options.errorEvent || "task_unhealthy";
+    self.options.additionalProperties = options.additionalProperties || [];
+    self.options.taskNameFilter = options.taskNameFilter || null;
+    self.options.statusCodes = options.statusCodes || [200];
+    self.options.propertyPrefix = options.propertyPrefix || "";
+    if (options.url) {
+        self.options.url = options.url;
+    } else {
+        throw new Error("Must set URL");
+    }
+
+    self.healthRequestCreate = function (host, port) {
+        return {
+            "host": host,
+            "port": port,
+            "path": options.url,
+            "method": "GET",
+            headers: {}
+        };
+    };
+
+    self.checkRunningInstances = function () {
+
+        self.logger.debug("Running periodic healthcheck" + (self.options.propertyPrefix.length ? ", prefix: " + self.options.propertyPrefix : ""));
+
+        self.scheduler.launchedTasks.forEach(function (task) {
+            self.checkInstance.call(self, task);
+        });
+    };
+}
+
+TaskHealthHelper.prototype.taskFilter = function (name) {
+    var self = this;
+    if (self.options.taskNameFilter) {
+        return name.match(self.options.taskNameFilter) !== null;
+    }
+    return true;
+};
+
+TaskHealthHelper.prototype.setCheckFailed = function (task) {
+
+    var self = this;
+
+    if (task.runtimeInfo[self.options.propertyPrefix + "checkFailCount"] === undefined) {
+        task.runtimeInfo[self.options.propertyPrefix + "checkFailCount"] = 0;
+    }
+    task.runtimeInfo[self.options.propertyPrefix + "checkFailCount"] += 1;
+    self.logger.debug("Task found unhealthy" + (self.options.propertyPrefix.length ? ", prefix: " + self.options.propertyPrefix : ""));
+    if (task.runtimeInfo[self.options.propertyPrefix + "checkFailCount"] === self.options.graceCount) {
+        self.logger.debug("Task marked unhealthy" + (self.options.propertyPrefix.length ? ", prefix: " + self.options.propertyPrefix : ""));
+        task.runtimeInfo[self.options.propertyPrefix + "healthy"] = false;
+        self.options.additionalProperties.forEach(function (property) {
+            if (property.setUnhealthy) {
+                var value = false;
+                if (property.inverse) {
+                    value = !value;
+                }
+                task.runtimeInfo[property.name] = value;
+            }
+        });
+        self.scheduler.emit(self.options.errorEvent, task);
+    } else if (task.runtimeInfo[self.options.propertyPrefix + "healthy"] === false) {
+        self.scheduler.emit(self.options.errorEvent, task);
+    }
+};
+
+TaskHealthHelper.prototype.checkInstance = function (task) {
+
+    var self = this;
+
+    if (task.runtimeInfo && task.runtimeInfo.state === "TASK_RUNNING" && self.taskFilter(task.name)) {
+        if (task.runtimeInfo.network && task.runtimeInfo.network.hostname && task.runtimeInfo.network.ports && task.runtimeInfo.network.ports[self.options.portIndex]) {
+            var req = http.request(self.healthRequestCreate(task.runtimeInfo.network.hostname, task.runtimeInfo.network.ports[self.options.portIndex]), function (res) {
+                if (self.options.statusCodes.indexOf(res.statusCode) > -1) {
+                    task.runtimeInfo[self.options.propertyPrefix + "checkFailCount"] = 0;
+                    task.runtimeInfo[self.options.propertyPrefix + "healthy"] = true;
+                    self.options.additionalProperties.forEach(function (property) {
+                        var value = true;
+                        if (property.inverse) {
+                            value = !value;
+                        }
+                        task.runtimeInfo[property.name] = value;
+                    });
+                } else {
+                    self.setCheckFailed.call(self, task);
+                }
+                res.resume();
+            });
+            req.on("error", function (error) {
+                self.logger.error("Error checking task health:" + JSON.stringify(error) + (self.options.propertyPrefix.length ? ", prefix: " + self.options.propertyPrefix : ""));
+                self.setCheckFailed.call(self, task);
+            });
+            req.end();
+        }
+    }
+};
+
+TaskHealthHelper.prototype.stopHealthCheck = function () {
+    var self = this;
+
+    if (self.interval) {
+        clearInterval(self.interval);
+        self.interval = null;
+    }
+}
+
+TaskHealthHelper.prototype.setupHealthCheck = function () {
+    var self = this;
+
+    self.interval = setInterval(self.checkRunningInstances, self.options.interval * 1000);
+};
+
+module.exports = TaskHealthHelper;
+
+
+
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.4.3 on Mon Jan 16 2017 10:33:15 GMT+0100 (CET) using the Minami theme. +
+ + + + + diff --git a/docs/taskHelper.js.html b/docs/taskHelper.js.html index 5983a95..50104d5 100644 --- a/docs/taskHelper.js.html +++ b/docs/taskHelper.js.html @@ -23,7 +23,7 @@
@@ -66,7 +66,7 @@

taskHelper.js

self.logger.error("Could not load task information."); // We're ready to subscribe self.scheduler.emit("ready"); - } else if (children) { + } else if (children && children.length) { var childStates = {}; children.forEach(function (child) { self.zkClient.getData(self.zkServicePath + "/tasks/" + child, function (error, data, stat) { @@ -92,8 +92,8 @@

taskHelper.js

for (i = 0;i < pending.length; i++) { var pendingTask = pending[i]; self.logger.debug("Pending task: \"" + JSON.stringify(pendingTask) + "\""); - if (pendingTask.name == task.name) { - if (task.runtimeInfo && task.runtimeInfo.agentId) { + if (pendingTask.name === task.name) { + if (task.runtimeInfo && task.runtimeInfo.agentId && (task.runtimeInfo.state === "TASK_RUNNING" || task.runtimeInfo.state === "TASK_STAGING")) { self.scheduler.launchedTasks.push(task); pending.splice(i, 1); self.scheduler.reconcileTasks.push(task); @@ -111,19 +111,16 @@

taskHelper.js

self.scheduler.pendingTasks = pending; childStates[child] = {'loaded': true}; self.logger.debug("childStates length " + Object.keys(childStates).length.toString() + " children.length " + children.length.toString()); - if (Object.keys(childStates).length == children.length) { + if (Object.keys(childStates).length === children.length) { // We're ready to subscribe self.scheduler.emit("ready"); } }); }); - if (children.length == 0) { - // We're ready to subscribe - self.scheduler.emit("ready"); - } + } else { + // We're ready to subscribe - no tasks + self.scheduler.emit("ready"); } - - }); }; @@ -178,7 +175,7 @@

taskHelper.js


- Documentation generated by JSDoc 3.4.3 on Fri Dec 30 2016 13:57:21 GMT+0100 (CET) using the Minami theme. + Documentation generated by JSDoc 3.4.3 on Mon Jan 16 2017 10:33:15 GMT+0100 (CET) using the Minami theme.