From cbb45e9467254be65abd7b7a6d33e7c730a1938f Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sat, 3 Mar 2018 14:24:55 +0100 Subject: [PATCH 01/13] Use Mesos 1.5.0 protobufs --- proto/{1.2.0 => 1.5.0}/executor.proto | 6 +- proto/{1.2.0 => 1.5.0}/mesos.proto | 1007 +++++++++++++++++++++--- proto/{1.2.0 => 1.5.0}/scheduler.proto | 126 ++- proto/all.proto | 6 +- 4 files changed, 1034 insertions(+), 111 deletions(-) rename proto/{1.2.0 => 1.5.0}/executor.proto (98%) rename proto/{1.2.0 => 1.5.0}/mesos.proto (69%) rename proto/{1.2.0 => 1.5.0}/scheduler.proto (76%) diff --git a/proto/1.2.0/executor.proto b/proto/1.5.0/executor.proto similarity index 98% rename from proto/1.2.0/executor.proto rename to proto/1.5.0/executor.proto index d95c1bc..7faf7e8 100644 --- a/proto/1.2.0/executor.proto +++ b/proto/1.5.0/executor.proto @@ -14,9 +14,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +syntax = "proto2"; + +//import "mesos/v1/mesos.proto"; + package mesos.executor; -option java_package = "org.apache.mesos.v1.executor"; +option java_package = "org.apache.mesos.executor"; option java_outer_classname = "Protos"; diff --git a/proto/1.2.0/mesos.proto b/proto/1.5.0/mesos.proto similarity index 69% rename from proto/1.2.0/mesos.proto rename to proto/1.5.0/mesos.proto index 7921ce0..80b8a55 100644 --- a/proto/1.2.0/mesos.proto +++ b/proto/1.5.0/mesos.proto @@ -14,9 +14,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +syntax = "proto2"; + package mesos; -option java_package = "org.apache.mesos.v1"; +option java_package = "org.apache.mesos"; option java_outer_classname = "Protos"; @@ -63,8 +65,8 @@ message AgentID { * A framework-generated ID to distinguish a task. The ID must remain * unique while the task is active. A framework can reuse an ID _only_ * if the previous task with the same ID has reached a terminal state - * (e.g., TASK_FINISHED, TASK_LOST, TASK_KILLED, etc.). However, - * reusing task IDs is strongly discouraged (MESOS-2198). + * (e.g., TASK_FINISHED, TASK_KILLED, etc.). However, reusing task IDs + * is strongly discouraged (MESOS-2198). */ message TaskID { required string value = 1; @@ -93,13 +95,29 @@ message ContainerID { } +/** + * A unique ID assigned to a resource provider. Currently, a resource + * provider gets a new ID whenever it (re)registers with Mesos. + */ +message ResourceProviderID { + required string value = 1; +} + + +/** + * A framework-generated ID to distinguish an operation. The ID + * must be unique within the framework. + */ +message OperationID { + required string value = 1; +} + + /** * Represents time since the epoch, in nanoseconds. */ message TimeInfo { required int64 nanoseconds = 1; - - // TODO(josephw): Add time zone information, if necessary. } @@ -253,11 +271,8 @@ message FrameworkInfo { // `roles` and the default unset `role`, we require that // frameworks set the `MULTI_ROLE` capability if // setting the `roles` field. - // - // NOTE: The implmentation for supporting `roles` - // is not complete, DO NOT USE the `roles` field. - optional string role = 6 [default = "*"]; - repeated string roles = 12; // EXPERIMENTAL. + optional string role = 6 [default = "*", deprecated=true]; + repeated string roles = 12; // Used to indicate the current host from which the scheduler is // registered in the Mesos Web UI. If set to an empty string Mesos @@ -319,14 +334,16 @@ message FrameworkInfo { // Frameworks that enable this capability can define how they // would like to handle partitioned tasks. Frameworks will // receive TASK_UNREACHABLE for tasks on agents that are - // partitioned from the master. If/when a partitioned agent - // reregisters, tasks on the agent that were started by - // PARTITION_AWARE frameworks will not killed. + // partitioned from the master. // // Without this capability, frameworks will receive TASK_LOST - // for tasks on partitioned agents; such tasks will be killed by - // Mesos when the agent reregisters (unless the master has - // failed over). + // for tasks on partitioned agents. + // NOTE: Prior to Mesos 1.5, such tasks will be killed by Mesos + // when the agent reregisters (unless the master has failed over). + // However due to the lack of benefit in maintaining different + // behaviors depending on whether the master has failed over + // (see MESOS-7215), as of 1.5, Mesos will not kill these + // tasks in either case. PARTITION_AWARE = 5; // This expresses the ability for the framework to be @@ -336,10 +353,45 @@ message FrameworkInfo { // expect that "single-tenant" schedulers eventually // provide this and move away from the deprecated // `role` field. + MULTI_ROLE = 6; + + // This capability has two effects for a framework. + // + // (1) The framework is offered resources in a new format. // - // NOTE: The implementation for supporting multiple - // roles is not complete, DO NOT USE THIS. - MULTI_ROLE = 6; // EXPERIMENTAL. + // The offered resources have the `Resource.reservations` field set + // rather than `Resource.role` and `Resource.reservation`. In short, + // an empty `reservations` field denotes unreserved resources, and + // each `ReservationInfo` in the `reservations` field denotes a + // reservation that refines the previous one. + // + // See the 'Resource Format' section for more details. + // + // (2) The framework can create refined reservations. + // + // A framework can refine an existing reservation via the + // `Resource.reservations` field. For example, a reservation for role + // `eng` can be refined to `eng/front_end`. + // + // See `ReservationInfo.reservations` for more details. + // + // NOTE: Without this capability, a framework is not offered resources + // that have refined reservations. A resource is said to have refined + // reservations if it uses the `Resource.reservations` field, and + // `Resource.reservations_size() > 1`. + RESERVATION_REFINEMENT = 7; // EXPERIMENTAL. + + // Indicates that the framework is prepared to receive offers + // for agents whose region is different from the master's + // region. Network links between hosts in different regions + // typically have higher latency and lower bandwidth than + // network links within a region, so frameworks should be + // careful to only place suitable workloads in remote regions. + // Frameworks that are not region-aware will never receive + // offers for remote agents; region-aware frameworks are assumed + // to implement their own logic to decide which workloads (if + // any) are suitable for placement on remote agents. + REGION_AWARE = 8; } // Enum fields should be optional, see: MESOS-4997. @@ -372,10 +424,11 @@ message CheckInfo { UNKNOWN = 0; COMMAND = 1; HTTP = 2; + TCP = 3; - // TODO(alexr): Consider supporting TCP checks and custom user checks. - // The latter should probably be paired with a `data` field and - // complemented by a `data` response in `CheckStatusInfo`. + // TODO(alexr): Consider supporting custom user checks. They should + // probably be paired with a `data` field and complemented by a + // `data` response in `CheckStatusInfo`. } // Describes a command check. If applicable, enters mount and/or network @@ -404,6 +457,13 @@ message CheckInfo { // validation, TLS version. } + // Describes a TCP check, i.e. based on establishing a TCP connection to + // the specified port. Note that is not configurable and is resolved + // automatically to 127.0.0.1. + message Tcp { + required uint32 port = 1; + } + // The type of the check. optional Type type = 1; @@ -413,6 +473,9 @@ message CheckInfo { // HTTP check. optional Http http = 3; + // TCP check. + optional Tcp tcp = 7; + // Amount of time to wait to start checking the task after it // transitions to `TASK_RUNNING` or `TASK_STARTING` if the latter // is used by the executor. @@ -452,6 +515,8 @@ message HealthCheck { // treat return codes between 200 and 399 as success; custom executors // may employ a different strategy, e.g. leveraging the `statuses` field. message HTTPCheckInfo { + optional NetworkInfo.Protocol protocol = 5 [default = IPv4]; + // Currently "http" and "https" are supported. optional string scheme = 3; @@ -487,6 +552,8 @@ message HealthCheck { // Describes a TCP health check, i.e. based on establishing // a TCP connection to the specified port. message TCPCheckInfo { + optional NetworkInfo.Protocol protocol = 2 [default = IPv4]; + // Port expected to be open. required uint32 port = 1; } @@ -514,7 +581,7 @@ message HealthCheck { optional uint32 consecutive_failures = 5 [default = 3]; // Amount of time after the task is launched during which health check - // failures are ignored. Once the a check succeeds for the first time, + // failures are ignored. Once a check succeeds for the first time, // the grace period does not apply anymore. Note that it includes // `delay_seconds`, i.e., setting `grace_period_seconds` < `delay_seconds` // has no effect. @@ -651,7 +718,7 @@ message ExecutorInfo { // 1) `command` must not be set when using a default executor. // // 2) Default executor only accepts a *single* `LAUNCH` or `LAUNCH_GROUP` - // offer operation. + // operation. // // 3) If `container` is set, `container.type` must be `MESOS` // and `container.mesos.image` must not be set. @@ -664,12 +731,12 @@ message ExecutorInfo { } // For backwards compatibility, if this field is not set when using `LAUNCH` - // offer operation, Mesos will infer the type by checking if `command` is - // set (`CUSTOM`) or unset (`DEFAULT`). `type` must be set when using - // `LAUNCH_GROUP` offer operation. + // operation, Mesos will infer the type by checking if `command` is set + // (`CUSTOM`) or unset (`DEFAULT`). `type` must be set when using + // `LAUNCH_GROUP` operation. // - // TODO(vinod): Add support for explicitly setting `type` to `DEFAULT ` - // in `LAUNCH` offer operation. + // TODO(vinod): Add support for explicitly setting `type` to `DEFAULT` in + // `LAUNCH` operation. optional Type type = 15; required ExecutorID executor_id = 1; @@ -723,6 +790,60 @@ message ExecutorInfo { } +/** + * Describes a domain. A domain is a collection of hosts that have + * similar characteristics. Mesos currently only supports "fault + * domains", which identify groups of hosts with similar failure + * characteristics. + * + * Frameworks can generally assume that network links between hosts in + * the same fault domain have lower latency, higher bandwidth, and better + * availability than network links between hosts in different domains. + * Schedulers may prefer to place network-intensive workloads in the + * same domain, as this may improve performance. Conversely, a single + * failure that affects a host in a domain may be more likely to + * affect other hosts in the same domain; hence, schedulers may prefer + * to place workloads that require high availability in multiple + * domains. (For example, all the hosts in a single rack might lose + * power or network connectivity simultaneously.) + * + * There are two kinds of fault domains: regions and zones. Regions + * offer the highest degree of fault isolation, but network latency + * between regions is typically high (typically >50 ms). Zones offer a + * modest degree of fault isolation along with reasonably low network + * latency (typically <10 ms). + * + * The mapping from fault domains to physical infrastructure is up to + * the operator to configure. In cloud environments, regions and zones + * can be mapped to the "region" and "availability zone" concepts + * exposed by most cloud providers, respectively. In on-premise + * deployments, regions and zones can be mapped to data centers and + * racks, respectively. + * + * Both masters and agents can be configured with domains. Frameworks + * can compare the domains of two hosts to determine if the hosts are + * in the same zone, in different zones in the same region, or in + * different regions. Note that all masters in a given Mesos cluster + * must be in the same region. + */ +message DomainInfo { + message FaultDomain { + message RegionInfo { + required string name = 1; + } + + message ZoneInfo { + required string name = 1; + } + + required RegionInfo region = 1; + required ZoneInfo zone = 2; + } + + optional FaultDomain fault_domain = 1; +} + + /** * Describes a master. This will probably have more fields in the * future which might be used, for example, to link a framework webui @@ -759,6 +880,23 @@ message MasterInfo { // and supersedes the use of `ip`, `port` and `hostname`. // Since Mesos 0.24. optional Address address = 7; + + // The domain that this master belongs to. All masters in a Mesos + // cluster should belong to the same region. + optional DomainInfo domain = 8; + + message Capability { + enum Type { + UNKNOWN = 0; + + // The master can handle slaves whose state + // changes after re-registering. + AGENT_UPDATE = 1; + } + optional Type type = 1; + } + + repeated Capability capabilities = 9; } @@ -770,10 +908,21 @@ message MasterInfo { message AgentInfo { required string hostname = 1; optional int32 port = 8 [default = 5051]; + + // The configured resources at the agent. This does not include any + // dynamic reservations or persistent volumes that may currently + // exist at the agent. repeated Resource resources = 3; + repeated Attribute attributes = 5; optional AgentID id = 6; + // The domain that this agent belongs to. If the agent's region + // differs from the master's region, it will not appear in resource + // offers to frameworks that have not enabled the REGION_AWARE + // capability. + optional DomainInfo domain = 10; + message Capability { enum Type { // This must be the first enum value in this list, to @@ -784,10 +933,58 @@ message AgentInfo { // This expresses the ability for the agent to be able // to launch tasks of a 'multi-role' framework. + MULTI_ROLE = 1; + + // This expresses the ability for the agent to be able to launch + // tasks, reserve resources, and create volumes using resources + // allocated to a 'hierarchical-role'. + // NOTE: This capability is required specifically for creating + // volumes because a hierchical role includes '/' (slashes) in them. + // Agents with this capability know to transform the '/' (slashes) + // into ' ' (spaces). + HIERARCHICAL_ROLE = 2; + + // This capability has three effects for an agent. + // + // (1) The format of the checkpointed resources, and + // the resources reported to master. // - // NOTE: The implementation for supporting multiple - // roles is not complete, DO NOT USE THIS. - MULTI_ROLE = 1; // EXPERIMENTAL. + // These resources are reported in the "pre-reservation-refinement" + // format if none of the resources have refined reservations. If any + // of the resources have refined reservations, they are reported in + // the "post-reservation-refinement" format. The purpose is to allow + // downgrading of an agent as well as communication with a pre-1.4.0 + // master until the reservation refinement feature is actually used. + // + // See the 'Resource Format' section for more details. + // + // (2) The format of the resources reported by the HTTP endpoints. + // + // For resources reported by agent endpoints, the + // "pre-reservation-refinement" format is "injected" if possible. + // That is, resources without refined reservations will have the + // `Resource.role` and `Resource.reservation` set, whereas + // resources with refined reservations will not. + // + // See the 'Resource Format' section for more details. + // + // (3) The ability for the agent to launch tasks, reserve resources, and + // create volumes using resources that have refined reservations. + // + // See `ReservationInfo.reservations` section for more details. + // + // NOTE: Resources are said to have refined reservations if it uses the + // `Resource.reservations` field, and `Resource.reservations_size() > 1`. + RESERVATION_REFINEMENT = 3; + + // This expresses the ability for the agent to handle resource + // provider related operations. This includes the following: + // + // (1) The ability to report resources that are provided by some + // local resource providers through the resource provider API. + // + // (2) The ability to provide operation feedback. + RESOURCE_PROVIDER = 4; } // Enum fields should be optional, see: MESOS-4997. @@ -796,6 +993,96 @@ message AgentInfo { } +/** + * Describes the container configuration to run a CSI plugin component. + */ +message CSIPluginContainerInfo { + enum Service { + UNKNOWN = 0; + CONTROLLER_SERVICE = 1; + NODE_SERVICE = 2; + } + + repeated Service services = 1; + optional CommandInfo command = 2; + repeated Resource resources = 3; + optional ContainerInfo container = 4; +} + + +/** + * Describes a CSI plugin. + */ +message CSIPluginInfo { + // The type of the CSI service. This uniquely identifies a CSI + // implementation. For instance: + // org.apache.mesos.csi.test + // + // Please follow to Java package naming convention + // (https://en.wikipedia.org/wiki/Java_package#Package_naming_conventions) + // to avoid conflicts on type names. + required string type = 1; + + // The name of the CSI service. There could be mutliple instances of a + // type of CSI service. The name field is used to distinguish these + // instances. It should be a legal Java identifier + // (https://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html) + // to avoid conflicts on concatenation of type and name. + required string name = 2; + + // A list of container configurations to run CSI plugin components. + // The controller service will be served by the first configuration + // that contains `CONTROLLER_SERVICE`, and the node service will be + // served by the first configuration that contains `NODE_SERVICE`. + repeated CSIPluginContainerInfo containers = 3; +} + + +/** + * Describes a resource provider. Note that the 'id' field is only available + * after a resource provider is registered with the master, and is made + * available here to facilitate re-registration. + */ +message ResourceProviderInfo { + optional ResourceProviderID id = 1; + repeated Attribute attributes = 2; + + // The type of the resource provider. This uniquely identifies a + // resource provider implementation. For instance: + // org.apache.mesos.rp.local.storage + // + // Please follow to Java package naming convention + // (https://en.wikipedia.org/wiki/Java_package#Package_naming_conventions) + // to avoid conflicts on type names. + required string type = 3; + + // The name of the resource provider. There could be multiple + // instances of a type of resource provider. The name field is used + // to distinguish these instances. It should be a legal Java identifier + // (https://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html) + // to avoid conflicts on concatenation of type and name. + required string name = 4; + + // The stack of default reservations. If this field is not empty, it + // indicates that resources from this resource provider are reserved + // by default, except for the resources that have been reserved or + // unreserved through operations. The first `ReservationInfo` + // may have type `STATIC` or `DYNAMIC`, but the rest must have + // `DYNAMIC`. One can create a new reservation on top of an existing + // one by pushing a new `ReservationInfo` to the back. The last + // `ReservationInfo` in this stack is the "current" reservation. The + // new reservation's role must be a child of the current one. + repeated Resource.ReservationInfo default_reservations = 5; // EXPERIMENTAL. + + // Storage resource provider related information. + message Storage { + required CSIPluginInfo plugin = 1; + } + + optional Storage storage = 6; // EXPERIMENTAL. +} + + /** * Describes an Attribute or Resource "value". A value is described * using the standard protocol buffer "union" trick. @@ -861,19 +1148,21 @@ message Attribute { /** - * Describes a resource on a machine. The `name` field is a string - * like "cpus" or "mem" that indicates which kind of resource this is; - * the rest of the fields describe the properties of the resource. A - * resource can take on one of three types: scalar (double), a list of - * finite and discrete ranges (e.g., [1-10, 20-30]), or a set of - * items. A resource is described using the standard protocol buffer - * "union" trick. + * Describes a resource from a resource provider. The `name` field is + * a string like "cpus" or "mem" that indicates which kind of resource + * this is; the rest of the fields describe the properties of the + * resource. A resource can take on one of three types: scalar + * (double), a list of finite and discrete ranges (e.g., [1-10, + * 20-30]), or a set of items. A resource is described using the + * standard protocol buffer "union" trick. * * Note that "disk" and "mem" resources are scalar values expressed in * megabytes. Fractional "cpus" values are allowed (e.g., "0.5"), * which correspond to partial shares of a CPU. */ message Resource { + optional ResourceProviderID provider_id = 12; + required string name = 1; required Value.Type type = 2; optional Value.Scalar scalar = 3; @@ -883,14 +1172,17 @@ message Resource { // The role that this resource is reserved for. If "*", this indicates // that the resource is unreserved. Otherwise, the resource will only // be offered to frameworks that belong to this role. - optional string role = 6 [default = "*"]; + // + // NOTE: Frameworks must not set this field if `reservations` is set. + // See the 'Resource Format' section for more details. + // + // TODO(mpark): Deprecate once `reservations` is no longer experimental. + optional string role = 6 [default = "*", deprecated=true]; // This was initially introduced to support MULTI_ROLE capable // frameworks. Frameworks that are not MULTI_ROLE capable can // continue to assume that the offered resources are allocated // to their role. - // - // NOTE: Implementation of this is in-progress, DO NOT USE! message AllocationInfo { // If set, this resource is allocated to a role. Note that in the // future, this may be unset and the scheduler may be responsible @@ -903,13 +1195,137 @@ message Resource { optional AllocationInfo allocation_info = 11; + // Resource Format: + // + // Frameworks receive resource offers in one of two formats, depending on + // whether the RESERVATION_REFINEMENT capability is enabled. + // + // __WITHOUT__ the RESERVATION_REFINEMENT capability, the framework is offered + // resources in the "pre-reservation-refinement" format. In this format, the + // `Resource.role` and `Resource.reservation` fields are used in conjunction + // to describe the reservation state of a `Resource` message. + // + // The following is an overview of the possible reservation states: + // + // +------------+------------------------------------------------------------+ + // | unreserved | { | + // | | role: "*", | + // | | reservation: , | + // | | reservations: | + // | | } | + // +------------+------------------------------------------------------------+ + // | static | { | + // | | role: "eng", | + // | | reservation: , | + // | | reservations: | + // | | } | + // +------------+------------------------------------------------------------+ + // | dynamic | { | + // | | role: "eng", | + // | | reservation: { | + // | | type: , | + // | | role: , | + // | | principal: , | + // | | labels: | + // | | }, | + // | | reservations: | + // | | } | + // +------------+------------------------------------------------------------+ + // + // __WITH__ the RESERVATION_REFINEMENT capability, the framework is offered + // resources in the "post-reservation-refinement" format. In this format, the + // reservation state of a `Resource` message is expressed solely in + // `Resource.reservations` field. + // + // The following is an overview of the possible reservation states: + // + // +------------+------------------------------------------------------------+ + // | unreserved | { | + // | | role: , | + // | | reservation: , | + // | | reservations: [] | + // | | } | + // +------------+------------------------------------------------------------+ + // | static | { | + // | | role: , | + // | | reservation: , | + // | | reservations: [ | + // | | { | + // | | type: STATIC, | + // | | role: "eng", | + // | | principal: , | + // | | labels: | + // | | } | + // | | ] | + // | | } | + // +------------+------------------------------------------------------------+ + // | dynamic | { | + // | | role: , | + // | | reservation: , | + // | | reservations: [ | + // | | { | + // | | type: DYNAMIC, | + // | | role: "eng", | + // | | principal: , | + // | | labels: | + // | | } | + // | | ] | + // | | } | + // +------------+------------------------------------------------------------+ + // + // We can also __refine__ reservations with this capability like so: + // + // +------------+------------------------------------------------------------+ + // | refined | { | + // | | role: , | + // | | reservation: , | + // | | reservations: [ | + // | | { | + // | | type: STATIC or DYNAMIC, | + // | | role: "eng", | + // | | principal: , | + // | | labels: | + // | | }, | + // | | { | + // | | type: DYNAMIC, | + // | | role: "eng/front_end", | + // | | principal: , | + // | | labels: | + // | | } | + // | | ] | + // | | } | + // +------------+------------------------------------------------------------+ + // + // NOTE: Each `ReservationInfo` in the `reservations` field denotes + // a reservation that refines the previous `ReservationInfo`. + message ReservationInfo { - // Describes a dynamic reservation. A dynamic reservation is - // acquired by an operator via the '/reserve' HTTP endpoint or by - // a framework via the offer cycle by sending back an + // Describes a reservation. A static reservation is set by the operator on + // the command-line and they are immutable without agent restart. A dynamic + // reservation is made by an operator via the '/reserve' HTTP endpoint + // or by a framework via the offer cycle by sending back an // 'Offer::Operation::Reserve' message. - // NOTE: We currently do not allow frameworks with role "*" to - // make dynamic reservations. + // + // NOTE: We currently do not allow frameworks with role "*" to make dynamic + // reservations. + + enum Type { + UNKNOWN = 0; + STATIC = 1; + DYNAMIC = 2; + } + + // The type of this reservation. + // + // NOTE: This field must not be set for `Resource.reservation`. + // See the 'Resource Format' section for more details. + optional Type type = 4; + + // The role to which this reservation is made for. + // + // NOTE: This field must not be set for `Resource.reservation`. + // See the 'Resource Format' section for more details. + optional string role = 3; // Indicates the principal, if any, of the framework or operator // that reserved this resource. If reserved by a framework, the @@ -931,8 +1347,27 @@ message Resource { // If this is set, this resource was dynamically reserved by an // operator or a framework. Otherwise, this resource is either unreserved // or statically reserved by an operator via the --resources flag. + // + // NOTE: Frameworks must not set this field if `reservations` is set. + // See the 'Resource Format' section for more details. + // + // TODO(mpark): Deprecate once `reservations` is no longer experimental. optional ReservationInfo reservation = 8; + // The stack of reservations. If this field is empty, it indicates that this + // resource is unreserved. Otherwise, the resource is reserved. The first + // `ReservationInfo` may have type `STATIC` or `DYNAMIC`, but the rest must + // have `DYNAMIC`. One can create a new reservation on top of an existing + // one by pushing a new `ReservationInfo` to the back. The last + // `ReservationInfo` in this stack is the "current" reservation. The new + // reservation's role must be a child of the current reservation's role. + // + // NOTE: Frameworks must not set this field if `reservation` is set. + // See the 'Resource Format' section for more details. + // + // TODO(mpark): Deprecate `role` and `reservation` once this is stable. + repeated ReservationInfo reservations = 13; // EXPERIMENTAL. + message DiskInfo { // Describes a persistent disk volume. // @@ -955,11 +1390,6 @@ message Resource { // with the "destroy" ACL to determine whether an entity // attempting to destroy the volume is permitted to do so. // - // NOTE: This field is optional, while the `principal` found in - // `ReservationInfo` is required. This field is optional to - // allow for the possibility of volume creation without a - // principal, though currently it must be provided. - // // NOTE: This field should match the FrameworkInfo.principal of // the framework that created the volume. optional string principal = 2; @@ -979,31 +1409,53 @@ message Resource { optional Volume volume = 2; // Describes where a disk originates from. - // TODO(jmlvanre): Add support for BLOCK devices. message Source { enum Type { + UNKNOWN = 0; PATH = 1; MOUNT = 2; + BLOCK = 3; + RAW = 4; } // A folder that can be located on a separate disk device. This // can be shared and carved up as necessary between frameworks. message Path { - // Path to the folder (e.g., /mnt/raid/disk0). - required string root = 1; + // Path to the folder (e.g., /mnt/raid/disk0). If the path is a + // relative path, it is relative to the agent work directory. + optional string root = 1; } // A mounted file-system set up by the Agent administrator. This // can only be used exclusively: a framework cannot accept a // partial amount of this disk. message Mount { - // Path to mount point (e.g., /mnt/raid/disk0). - required string root = 1; + // Path to mount point (e.g., /mnt/raid/disk0). If the path is a + // relative path, it is relative to the agent work directory. + optional string root = 1; } required Type type = 1; optional Path path = 2; optional Mount mount = 3; + + // An identifier for this source. This field maps onto CSI + // volume IDs and is not expected to be set by frameworks. + optional string id = 4; // EXPERIMENTAL. + + // Additional metadata for this source. This field maps onto CSI + // volume metadata and is not expected to be set by frameworks. + optional Labels metadata = 5; // EXPERIMENTAL. + + // This field serves as an indirection to a set of storage + // vendor specific disk parameters which describe the properties + // of the disk. The operator will setup mappings between a + // profile name to a set of vendor specific disk parameters. And + // the framework will do disk selection based on profile names, + // instead of vendor specific disk parameters. + // + // Also see the DiskProfile module. + optional string profile = 6; // EXPERIMENTAL. } optional Source source = 3; @@ -1031,6 +1483,7 @@ message Resource { optional SharedInfo shared = 10; } + /** * When the network bandwidth caps are enabled and the container * is over its limit, outbound packets may be either delayed or @@ -1071,15 +1524,15 @@ message TrafficControlStatistics { message IpStatistics { - optional int64 Forwarding = 1; - optional int64 DefaultTTL = 2; - optional int64 InReceives = 3; - optional int64 InHdrErrors = 4; - optional int64 InAddrErrors = 5; - optional int64 ForwDatagrams = 6; + optional int64 Forwarding = 1; + optional int64 DefaultTTL = 2; + optional int64 InReceives = 3; + optional int64 InHdrErrors = 4; + optional int64 InAddrErrors = 5; + optional int64 ForwDatagrams = 6; optional int64 InUnknownProtos = 7; - optional int64 InDiscards = 8; - optional int64 InDelivers = 9; + optional int64 InDiscards = 8; + optional int64 InDelivers = 9; optional int64 OutRequests = 10; optional int64 OutDiscards = 11; optional int64 OutNoRoutes = 12; @@ -1095,11 +1548,11 @@ message IpStatistics { message IcmpStatistics { optional int64 InMsgs = 1; - optional int64 InErrors = 2; + optional int64 InErrors = 2; optional int64 InCsumErrors = 3; - optional int64 InDestUnreachs = 4; + optional int64 InDestUnreachs = 4; optional int64 InTimeExcds = 5; - optional int64 InParmProbs = 6; + optional int64 InParmProbs = 6; optional int64 InSrcQuenchs = 7; optional int64 InRedirects = 8; optional int64 InEchos = 9; @@ -1163,6 +1616,14 @@ message SNMPStatistics { } +message DiskStatistics { + optional Resource.DiskInfo.Source source = 1; + optional Resource.DiskInfo.Persistence persistence = 2; + optional uint32 limit_bytes = 3; + optional uint32 used_bytes = 4; +} + + /** * A snapshot of resource usage statistics. */ @@ -1237,6 +1698,12 @@ message ResourceStatistics { optional uint32 disk_limit_bytes = 26; optional uint32 disk_used_bytes = 27; + // Per disk (resource) statistics. + repeated DiskStatistics disk_statistics = 43; + + // Cgroups blkio statistics. + optional CgroupInfo.Blkio.Statistics blkio_statistics = 44; + // Perf statistics. optional PerfStatistics perf = 13; @@ -1407,6 +1874,9 @@ message Offer { // URL for reaching the agent running on the host. optional URL url = 8; + // The domain of the agent. + optional DomainInfo domain = 11; + repeated Resource resources = 5; repeated Attribute attributes = 7; repeated ExecutorID executor_ids = 6; @@ -1427,8 +1897,6 @@ message Offer { // roles managed by the scheduler. (Therefore, each // `Offer.resources[i].allocation_info` will match the // top level `Offer.allocation_info`). - // - // NOTE: Implementation of this is in-progress, DO NOT USE! optional Resource.AllocationInfo allocation_info = 10; // Defines an operation that can be performed against offers. @@ -1441,6 +1909,10 @@ message Offer { UNRESERVE = 3; CREATE = 4; DESTROY = 5; + CREATE_VOLUME = 7; + DESTROY_VOLUME = 8; + CREATE_BLOCK = 9; + DESTROY_BLOCK = 10; } // TODO(vinod): Deprecate this in favor of `LaunchGroup` below. @@ -1477,13 +1949,40 @@ message Offer { repeated Resource volumes = 1; } + message CreateVolume { + required Resource source = 1; + required Resource.DiskInfo.Source.Type target_type = 2; + } + + message DestroyVolume { + required Resource volume = 1; + } + + message CreateBlock { + required Resource source = 1; + } + + message DestroyBlock { + required Resource block = 1; + } + optional Type type = 1; + + // NOTE: The `id` field will allow frameworks to indicate that they wish to + // receive feedback about an operation. Since this feature is not yet + // implemented, the `id` field should NOT be set at present. See MESOS-8054. + optional OperationID id = 12; // Experimental. + optional Launch launch = 2; optional LaunchGroup launch_group = 7; optional Reserve reserve = 3; optional Unreserve unreserve = 4; optional Create create = 5; optional Destroy destroy = 6; + optional CreateVolume create_volume = 8; + optional DestroyVolume destroy_volume = 9; + optional CreateBlock create_block = 10; + optional DestroyBlock destroy_block = 11; } } @@ -1677,16 +2176,22 @@ enum TaskState { // the TASK_KILLING_STATE capability. TASK_KILLING = 8; // The task is being killed by the executor. - TASK_FINISHED = 2; // TERMINAL: The task finished successfully. + // The task finished successfully on its own without external interference. + TASK_FINISHED = 2; // TERMINAL. + TASK_FAILED = 3; // TERMINAL: The task failed to finish successfully. TASK_KILLED = 4; // TERMINAL: The task was killed by the executor. TASK_ERROR = 7; // TERMINAL: The task description contains an error. // In Mesos 1.3, this will only be sent when the framework does NOT // opt-in to the PARTITION_AWARE capability. - TASK_LOST = 5; // TERMINAL: The task failed but can be rescheduled. + // + // NOTE: This state is not always terminal. For example, tasks might + // transition from TASK_LOST to TASK_RUNNING or other states when a + // partitioned agent re-registers. + TASK_LOST = 5; // The task failed but can be rescheduled. - // The following task statuses are only sent when the framework + // The following task states are only sent when the framework // opts-in to the PARTITION_AWARE capability. // The task failed to launch because of a transient error. The @@ -1725,6 +2230,89 @@ enum TaskState { } +/** + * Describes a resource limitation that caused a task failure. + */ +message TaskResourceLimitation { + // This field contains the resource whose limits were violated. + // + // NOTE: 'Resources' is used here because the resource may span + // multiple roles (e.g. `"mem(*):1;mem(role):2"`). + repeated Resource resources = 1; +} + + +/** + * Describes a UUID. + */ +message UUID { + required bytes value = 1; +} + + +/** + * Describes an operation, similar to `Offer.Operation`, with + * some additional information. + */ +message Operation { + optional FrameworkID framework_id = 1; + optional AgentID agent_id = 2; + required Offer.Operation info = 3; + required OperationStatus latest_status = 4; + + // All the statuses known to this operation. Some of the statuses in this + // list might not have been acknowledged yet. The statuses are ordered. + repeated OperationStatus statuses = 5; + + // This is the internal UUID for the operation, which is kept independently + // from the framework-specified operation ID, which is optional. + required UUID uuid = 6; +} + + +/** + * Describes possible operation states. + */ +enum OperationState { + // Default value if the enum is not set. See MESOS-4997. + OPERATION_UNSUPPORTED = 0; + + // Initial state. + OPERATION_PENDING = 1; + + // TERMINAL: The operation was successfully applied. + OPERATION_FINISHED = 2; + + // TERMINAL: The operation failed to apply. + OPERATION_FAILED = 3; + + // TERMINAL: The operation description contains an error. + OPERATION_ERROR = 4; + + // TERMINAL: The operation was dropped due to a transient error. + OPERATION_DROPPED = 5; +} + + +/** + * Describes the current status of an operation. + */ +message OperationStatus { + optional OperationID operation_id = 1; + required OperationState state = 2; + optional string message = 3; + + // Converted resources after applying the operation. This only + // applies if the `state` is `OPERATION_FINISHED`. + repeated Resource converted_resources = 4; + + // Statuses that are delivered reliably to the scheduler will + // include a `uuid`. The status is considered delivered once + // it is acknowledged by the scheduler. + optional UUID uuid = 5; +} + + /** * Describes the status of a check. Type and the corresponding field, i.e., * `command` or `http` must be set. If the result of the check is not available @@ -1735,7 +2323,9 @@ enum TaskState { */ message CheckStatusInfo { message Command { - // Exit code of a command check. + // Exit code of a command check. It is the result of calling + // `WEXITSTATUS()` on `waitpid()` termination information on + // Posix and calling `GetExitCodeProcess()` on Windows. optional int32 exit_code = 1; } @@ -1744,6 +2334,11 @@ message CheckStatusInfo { optional uint32 status_code = 1; } + message Tcp { + // Whether a TCP connection succeeded. + optional bool succeeded = 1; + } + // TODO(alexr): Consider adding a `data` field, which can contain, e.g., // truncated stdout/stderr output for command checks or HTTP response body // for HTTP checks. Alternatively, it can be an even shorter `message` field @@ -1759,6 +2354,9 @@ message CheckStatusInfo { // Status of an HTTP check. optional Http http = 3; + // Status of a TCP check. + optional Tcp tcp = 4; + // TODO(alexr): Consider introducing a "last changed at" timestamp, since // task status update's timestamp may not correspond to the last check's // state, e.g., for reconciliation. @@ -1780,9 +2378,7 @@ message TaskStatus { } // Detailed reason for the task status update. - // - // TODO(bmahler): Differentiate between agent removal reasons - // (e.g. unhealthy vs. unregistered for maintenance). + // Refer to docs/task-state-reasons.md for additional explanation. enum Reason { // TODO(jieyu): The default value when a caller doesn't check for // presence is 0 and so ideally the 0 reason is not a valid one. @@ -1798,7 +2394,7 @@ message TaskStatus { REASON_EXECUTOR_REGISTRATION_TIMEOUT = 23; REASON_EXECUTOR_REREGISTRATION_TIMEOUT = 24; REASON_EXECUTOR_TERMINATED = 1; - REASON_EXECUTOR_UNREGISTERED = 2; + REASON_EXECUTOR_UNREGISTERED = 2; // No longer used. REASON_FRAMEWORK_REMOVED = 3; REASON_GC_ERROR = 4; REASON_INVALID_FRAMEWORKID = 5; @@ -1809,9 +2405,13 @@ message TaskStatus { REASON_RESOURCES_UNKNOWN = 18; REASON_AGENT_DISCONNECTED = 10; REASON_AGENT_REMOVED = 11; + REASON_AGENT_REMOVED_BY_OPERATOR = 31; + REASON_AGENT_REREGISTERED = 32; REASON_AGENT_RESTARTED = 12; REASON_AGENT_UNKNOWN = 13; + REASON_TASK_KILLED_DURING_LAUNCH = 30; REASON_TASK_CHECK_STATUS_UPDATED = 28; + REASON_TASK_HEALTH_CHECK_STATUS_UPDATED = 29; REASON_TASK_GROUP_INVALID = 25; REASON_TASK_GROUP_UNAUTHORIZED = 26; REASON_TASK_INVALID = 14; @@ -1862,7 +2462,7 @@ message TaskStatus { // acted upon by Mesos itself. As opposed to the data field, labels // will be kept in memory on master and agent processes. Therefore, // labels should be used to tag TaskStatus message with light-weight - // meta-data. Labels should not contain duplicate key-value pairs. + // meta-data. Labels should not contain duplicate key-value pairs. optional Labels labels = 12; // Container related information that is resolved dynamically such as @@ -1874,6 +2474,10 @@ message TaskStatus { // status updates for tasks running on agents that are unreachable // (e.g., partitioned away from the master). optional TimeInfo unreachable_time = 14; + + // If the reason field indicates a container resource limitation, + // this field optionally contains additional information. + optional TaskResourceLimitation limitation = 16; } @@ -1888,6 +2492,11 @@ message Filters { // SchedulerDriver::launchTasks. You MUST pass Filters with this // field set to change this behavior (i.e., get another offer which // includes unused resources sooner or later than the default). + // + // If this field is set to a number of seconds greater than 31536000 + // (365 days), then the resources will be considered refused for 365 + // days. If it is set to a negative number, then the default value + // will be used. optional double refuse_seconds = 1 [default = 5.0]; } @@ -1895,15 +2504,29 @@ message Filters { /** * Describes a collection of environment variables. This is used with * CommandInfo in order to set environment variables before running a -* command. +* command. The contents of each variable may be specified as a string +* or a Secret; only one of `value` and `secret` must be set. */ message Environment { message Variable { required string name = 1; - // NOTE: The `value` field was made optional in Mesos 1.2 but it - // is currently enforced to be set. This constraint will be - // removed in a future version. + + enum Type { + UNKNOWN = 0; + VALUE = 1; + SECRET = 2; + } + + // In Mesos 1.2, the `Environment.variables.value` message was made + // optional. The default type for `Environment.variables.type` is now VALUE, + // which requires `value` to be set, maintaining backward compatibility. + // + // TODO(greggomann): The default can be removed in Mesos 2.1 (MESOS-7134). + optional Type type = 3 [default = VALUE]; + + // Only one of `value` and `secret` must be set. optional string value = 2; + optional Secret secret = 4; } repeated Variable variables = 1; @@ -1952,6 +2575,53 @@ message Credentials { } +/** + * Secret used to pass privileged information. It is designed to provide + * pass-by-value or pass-by-reference semantics, where the REFERENCE type can be + * used by custom modules which interact with a secure back-end. + */ +message Secret +{ + enum Type { + UNKNOWN = 0; + REFERENCE = 1; + VALUE = 2; + } + + // Can be used by modules to refer to a secret stored in a secure back-end. + // The `key` field is provided to permit reference to a single value within a + // secret containing arbitrary key-value pairs. + // + // For example, given a back-end secret store with a secret named + // "my-secret" containing the following key-value pairs: + // + // { + // "username": "my-user", + // "password": "my-password + // } + // + // the username could be referred to in a `Secret` by specifying + // "my-secret" for the `name` and "username" for the `key`. + message Reference + { + required string name = 1; + optional string key = 2; + } + + // Used to pass the value of a secret. + message Value + { + required bytes data = 1; + } + + optional Type type = 1; + + // Only one of `reference` and `value` must be set. + optional Reference reference = 2; + optional Value value = 3; +} + + /** * Rate (queries per second, QPS) limit for messages from a framework to master. * Strictly speaking they are the combined rate from all frameworks of the same @@ -2032,7 +2702,16 @@ message Image { // Credential to authenticate with docker registry. // NOTE: This is not encrypted, therefore framework and operators // should enable SSL when passing this information. - optional Credential credential = 2; + // + // This field has never been used in Mesos before and is + // deprecated since Mesos 1.3. Please use `config` below + // (see MESOS-7088 for details). + optional Credential credential = 2 [deprecated = true]; // Since 1.3. + + // Docker config containing credentails to authenticate with + // docker registry. The secret is expected to be a docker + // config file in JSON format with UTF-8 character encoding. + optional Secret config = 3; } required Type type = 1; @@ -2049,6 +2728,31 @@ message Image { } +/** + * Describes how the mount will be propagated for a volume. See the + * following doc for more details about mount propagation: + * https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt + */ +message MountPropagation { + enum Mode { + UNKNOWN = 0; + + // The volume in a container will receive new mounts from the host + // or other containers, but filesystems mounted inside the + // container won't be propagated to the host or other containers. + // This is currently the default behavior for all volumes. + HOST_TO_CONTAINER = 1; + + // The volume in a container will receive new mounts from the host + // or other containers, and its own mounts will be propagated from + // the container to the host or other containers. + BIDIRECTIONAL = 2; + } + + optional Mode mode = 1; +} + + /** * Describes a volume mapping either from host to container or vice * versa. Both paths can either refer to a directory or a file. @@ -2088,9 +2792,11 @@ message Volume { // in a backwards-compatible way. See: MESOS-4997. UNKNOWN = 0; - // TODO(gyliu513): Add HOST_PATH and IMAGE as volume source type. + // TODO(gyliu513): Add IMAGE as volume source type. DOCKER_VOLUME = 1; + HOST_PATH = 4; SANDBOX_PATH = 2; + SECRET = 3; } message DockerVolume { @@ -2104,6 +2810,12 @@ message Volume { optional Parameters driver_options = 3; } + // Absolute path pointing to a directory or file on the host. + message HostPath { + required string path = 1; + optional MountPropagation mount_propagation = 2; + } + // Describe a path from a container's sandbox. The container can // be the current container (SELF), or its parent container // (PARENT). PARENT allows all child containers to share a volume @@ -2132,7 +2844,12 @@ message Volume { // The source of the volume created by docker volume driver. optional DockerVolume docker_volume = 2; + optional HostPath host_path = 5; optional SandboxPath sandbox_path = 3; + + // The volume/secret isolator uses the secret-fetcher module (third-party or + // internal) downloads the secret and makes it available at container_path. + optional Secret secret = 4; } optional Source source = 5; @@ -2177,7 +2894,7 @@ message NetworkInfo { // request the network isolator on the Agent to assign an IP address to the // container being launched. If a specific IP address is specified in // ip_address, this field should not be set. - optional Protocol protocol = 1; + optional Protocol protocol = 1 [default = IPv4]; // Statically assigned IP provided by the Framework. This IP will be // assigned to the container by the network isolator module on the Agent. @@ -2286,8 +3003,24 @@ message CapabilityInfo { * E.g, capabilities, limits etc. */ message LinuxInfo { - // Represents the capability whitelist. - optional CapabilityInfo capability_info = 1; + // Since 1.4.0, deprecated in favor of `effective_capabilities`. + optional CapabilityInfo capability_info = 1 [deprecated = true]; + + // The set of capabilities that are allowed but not initially + // granted to tasks. + optional CapabilityInfo bounding_capabilities = 2; + + // Represents the set of capabilities that the task will + // be executed with. + optional CapabilityInfo effective_capabilities = 3; + + // If set as 'true', the container shares the pid namespace with + // its parent. If the container is a top level container, it will + // share the pid namespace with the agent. If the container is a + // nested container, it will share the pid namespace with its + // parent container. This field will be ignored if 'namespaces/pid' + // isolator is not enabled. + optional bool share_pid_namespace = 4; } @@ -2455,6 +3188,71 @@ message ContainerStatus { * Linux control group (cgroup) information. */ message CgroupInfo { + // Configuration of a blkio cgroup subsystem. + message Blkio { + enum Operation { + UNKNOWN = 0; + TOTAL = 1; + READ = 2; + WRITE = 3; + SYNC = 4; + ASYNC = 5; + } + + // Describes a stat value without the device descriptor part. + message Value { + optional Operation op = 1; // Required. + optional uint32 value = 2; // Required. + } + + message CFQ { + message Statistics { + // Stats are grouped by block devices. If `device` is not + // set, it represents `Total`. + optional Device.Number device = 1; + // blkio.sectors + optional uint32 sectors = 2; + // blkio.time + optional uint32 time = 3; + // blkio.io_serviced + repeated Value io_serviced = 4; + // blkio.io_service_bytes + repeated Value io_service_bytes = 5; + // blkio.io_service_time + repeated Value io_service_time = 6; + // blkio.io_wait_time + repeated Value io_wait_time = 7; + // blkio.io_merged + repeated Value io_merged = 8; + // blkio.io_queued + repeated Value io_queued = 9; + } + + // TODO(jasonlai): Add fields for blkio weight and weight + // device. + } + + message Throttling { + message Statistics { + // Stats are grouped by block devices. If `device` is not + // set, it represents `Total`. + optional Device.Number device = 1; + // blkio.throttle.io_serviced + repeated Value io_serviced = 2; + // blkio.throttle.io_service_bytes + repeated Value io_service_bytes = 3; + } + + // TODO(jasonlai): Add fields for blkio.throttle.*_device. + } + + message Statistics { + repeated CFQ.Statistics cfq = 1; + repeated CFQ.Statistics cfq_recursive = 2; + repeated Throttling.Statistics throttling = 3; + } + } + // Configuration of a net_cls cgroup subsystem. message NetCls { // The 32-bit classid consists of two parts, a 16 bit major handle @@ -2631,4 +3429,37 @@ message FileInfo { // Group ID of owner. optional string gid = 7; +} + + +/** + * Describes information abount a device. + */ +message Device { + message Number { + required uint32 major_number = 1; + required uint32 minor_number = 2; + } + + optional string path = 1; + optional Number number = 2; +} + + +/** + * Describes a device whitelist entry that expose from host to container. + */ +message DeviceAccess { + message Access { + optional bool read = 1; + optional bool write = 2; + optional bool mknod = 3; + } + required Device device = 1; + required Access access = 2; +} + + +message DeviceWhitelist { + repeated DeviceAccess allowed_devices = 1; } \ No newline at end of file diff --git a/proto/1.2.0/scheduler.proto b/proto/1.5.0/scheduler.proto similarity index 76% rename from proto/1.2.0/scheduler.proto rename to proto/1.5.0/scheduler.proto index d28ecb1..7c7de46 100644 --- a/proto/1.2.0/scheduler.proto +++ b/proto/1.5.0/scheduler.proto @@ -14,9 +14,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +syntax = "proto2"; + +//import "mesos/v1/mesos.proto"; + package mesos.scheduler; -option java_package = "org.apache.mesos.v1.scheduler"; +option java_package = "org.apache.mesos.scheduler"; option java_outer_classname = "Protos"; @@ -37,15 +41,16 @@ message Event { // in a backwards-compatible way. See: MESOS-4997. UNKNOWN = 0; - SUBSCRIBED = 1; // See 'Subscribed' below. - OFFERS = 2; // See 'Offers' below. - INVERSE_OFFERS = 9; // See 'InverseOffers' below. - RESCIND = 3; // See 'Rescind' below. - RESCIND_INVERSE_OFFER = 10; // See 'RescindInverseOffer' below. - UPDATE = 4; // See 'Update' below. - MESSAGE = 5; // See 'Message' below. - FAILURE = 6; // See 'Failure' below. - ERROR = 7; // See 'Error' below. + SUBSCRIBED = 1; // See 'Subscribed' below. + OFFERS = 2; // See 'Offers' below. + INVERSE_OFFERS = 9; // See 'InverseOffers' below. + RESCIND = 3; // See 'Rescind' below. + RESCIND_INVERSE_OFFER = 10; // See 'RescindInverseOffer' below. + UPDATE = 4; // See 'Update' below. + UPDATE_OPERATION_STATUS = 11; // See 'UpdateOperationStatus' below. + MESSAGE = 5; // See 'Message' below. + FAILURE = 6; // See 'Failure' below. + ERROR = 7; // See 'Error' below. // Periodic message sent by the Mesos master according to // 'Subscribed.heartbeat_interval_seconds'. If the scheduler does @@ -114,10 +119,26 @@ message Event { // to the task. It is also the responsibility of the scheduler to // explicitly acknowledge the receipt of a status update. See // 'Acknowledge' in the 'Call' section below for the semantics. + // + // A task status update may be used for guaranteed delivery of some + // task-related information, e.g., task's health update. Such + // information may be shadowed by subsequent task status updates, that + // do not preserve fields of the previously sent message. message Update { required TaskStatus status = 1; } + // Received when there is an operation status update generated by the + // master, agent, or resource provider. These updates are only sent to + // the framework for operations which had the operation ID set by the + // framework. It is the responsibility of the scheduler to explicitly + // acknowledge the receipt of a status update. + // See 'AcknowledgeOperationStatus' in the 'Call' section below for + // the semantics. + message UpdateOperationStatus { + required OperationStatus status = 1; + } + // Received when a custom message generated by the executor is // forwarded by the master. Note that this message is not // interpreted by Mesos and is only forwarded (without reliability @@ -146,6 +167,16 @@ message Event { // 'executor_id' will be set and possibly 'status' (if we were // able to determine the exit status). optional ExecutorID executor_id = 2; + + // On Posix, `status` corresponds to termination information in the + // `stat_loc` area returned from a `waitpid` call. On Windows, `status` + // is obtained via calling the `GetExitCodeProcess()` function. For + // messages coming from Posix agents, schedulers need to apply + // `WEXITSTATUS` family macros or equivalent transformations to obtain + // exit codes. + // + // TODO(alexr): Consider unifying Windows and Posix behavior by returning + // exit code here, see MESOS-7241. optional int32 status = 3; } @@ -167,12 +198,32 @@ message Event { optional Rescind rescind = 4; optional RescindInverseOffer rescind_inverse_offer = 10; optional Update update = 5; + optional UpdateOperationStatus update_operation_status = 11; optional Message message = 6; optional Failure failure = 7; optional Error error = 8; } +/** + * Synchronous responses for calls made to the scheduler API. + */ +message Response { + // Each of the responses of type `FOO` corresponds to `Foo` message below. + enum Type { + UNKNOWN = 0; + + RECONCILE_OPERATIONS = 1; // See 'ReconcileOperations' below. + } + + message ReconcileOperations { + repeated OperationStatus operation_statuses = 1; + } + + optional ReconcileOperations reconcile_operations = 1; +} + + /** * Scheduler call API. * @@ -196,7 +247,9 @@ message Call { KILL = 6; // See 'Kill' below. SHUTDOWN = 7; // See 'Shutdown' below. ACKNOWLEDGE = 8; // See 'Acknowledge' below. + ACKNOWLEDGE_OPERATION_STATUS = 15; // See message below. RECONCILE = 9; // See 'Reconcile' below. + RECONCILE_OPERATIONS = 16; // See 'ReconcileOperations' below. MESSAGE = 10; // See 'Message' below. REQUEST = 11; // See 'Request' below. SUPPRESS = 12; // Inform master to stop sending offers to the framework. @@ -217,6 +270,11 @@ message Call { // See the comments below on 'framework_id' on the semantics for // 'framework_info.id'. required FrameworkInfo framework_info = 1; + + // List of suppressed roles for which the framework does not wish to be + // offered resources. The framework can decide to suppress all or a subset + // of roles the framework (re)registers as. + repeated string suppressed_roles = 2; } // Accepts an offer, performing the specified operations @@ -271,11 +329,11 @@ message Call { optional Filters filters = 2; } - // Revive offers for a specified role. If role is unset, the - // `REVIVE` call will revive offers for all of the roles the - // framework is subscribed to. + // Revive offers for the specified roles. If `roles` is empty, + // the `REVIVE` call will revive offers for all of the roles + // the framework is currently subscribed to. message Revive { - optional string role = 1; + repeated string roles = 1; } // Kills a specific task. If the scheduler has a custom executor, @@ -325,6 +383,18 @@ message Call { required bytes uuid = 3; } + // Acknowledges the receipt of an operation status update. Schedulers + // are responsible for explicitly acknowledging the receipt of updates + // which have the 'UpdateOperationStatus.status().uuid()' field set. + // Such status updates are retried by the agent or resource provider + // until they are acknowledged by the scheduler. + message AcknowledgeOperationStatus { + optional AgentID agent_id = 1; + optional ResourceProviderID resource_provider_id = 2; + required bytes uuid = 3; + required OperationID operation_id = 4; + } + // Allows the scheduler to query the status for non-terminal tasks. // This causes the master to send back the latest task status for // each task in 'tasks', if possible. Tasks that are no longer known @@ -341,6 +411,21 @@ message Call { repeated Task tasks = 1; } + // Allows the scheduler to query the status of operations. This causes + // the master to send back the latest status for each operation in + // 'operations', if possible. If 'operations' is empty, then the + // master will send the latest status for each operation currently + // known. + message ReconcileOperations { + message Operation { + required OperationID operation_id = 1; + optional AgentID agent_id = 2; + optional ResourceProviderID resource_provider_id = 3; + } + + repeated Operation operations = 1; + } + // Sends arbitrary binary data to the executor. Note that Mesos // neither interprets this data nor makes any guarantees about the // delivery of this message to the executor. @@ -360,11 +445,11 @@ message Call { repeated mesos.Request requests = 1; } - // Suppress offers for a specified role. If role is unset, the - // `SUPPRESS` call will suppress offers for all of the roles the - // framework is subscribed to. + // Suppress offers for the specified roles. If `roles` is empty, + // the `SUPPRESS` call will suppress offers for all of the roles + // the framework is currently subscribed to. message Suppress { - optional string role = 1; + repeated string roles = 1; } // Identifies who generated this call. Master assigns a framework id @@ -377,7 +462,8 @@ message Call { // Type of the call, indicates which optional field below should be // present if that type has a nested message definition. - // See comments on `Event::Type` above on the reasoning behind this field being optional. + // See comments on `Event::Type` above on the reasoning behind this + // field being optional. optional Type type = 2; optional Subscribe subscribe = 3; @@ -389,7 +475,9 @@ message Call { optional Kill kill = 6; optional Shutdown shutdown = 7; optional Acknowledge acknowledge = 8; + optional AcknowledgeOperationStatus acknowledge_operation_status = 17; optional Reconcile reconcile = 9; + optional ReconcileOperations reconcile_operations = 18; optional Message message = 10; optional Request request = 11; optional Suppress suppress = 16; diff --git a/proto/all.proto b/proto/all.proto index 66159b4..e3a3e1b 100644 --- a/proto/all.proto +++ b/proto/all.proto @@ -1,6 +1,6 @@ /* * This is used to import/concatenate all required protobufs */ -import "1.2.0/mesos.proto"; -import "1.2.0/scheduler.proto"; -import "1.2.0/executor.proto"; \ No newline at end of file +import "1.5.0/mesos.proto"; +import "1.5.0/scheduler.proto"; +import "1.5.0/executor.proto"; \ No newline at end of file From 7862a39ab0ead1d78314040deac1cdbe29da9efd Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sat, 3 Mar 2018 14:25:10 +0100 Subject: [PATCH 02/13] Fix examples --- examples/dockerSchedulerApacheFlink.js | 25 +++++++++++---------- examples/dockerSchedulerHostNetworking.js | 3 ++- examples/dockerSchedulerHostNetworkingZk.js | 3 ++- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/examples/dockerSchedulerApacheFlink.js b/examples/dockerSchedulerApacheFlink.js index 5c025e2..0843228 100644 --- a/examples/dockerSchedulerApacheFlink.js +++ b/examples/dockerSchedulerApacheFlink.js @@ -2,6 +2,7 @@ var Scheduler = require("../index").Scheduler; var Mesos = require("../index").Mesos.getMesos(); +var Builder = require("../index").Builder; var ContainerInfo = new Mesos.ContainerInfo( Mesos.ContainerInfo.Type.DOCKER, // Type @@ -33,12 +34,12 @@ var scheduler = new Scheduler({ "instances": 3, "executorInfo": null, // Can take a Mesos.ExecutorInfo object "containerInfo": ContainerInfo, // Mesos.ContainerInfo object - "commandInfo": new Mesos.CommandInfo( // Strangely, this is needed, even when specifying ContainerInfo... + "commandInfo": new Mesos.CommandInfo( null, // URI new Mesos.Environment([ - new Mesos.Environment.Variable("flink_recovery_mode", "zookeeper"), - new Mesos.Environment.Variable("flink_recovery_zookeeper_quorum", "172.17.10.101:2181"), - new Mesos.Environment.Variable("flink_recovery_zookeeper_storageDir", "/data/zk") + new Builder("mesos.Environment.Variable").setName("flink_recovery_mode").setValue("zookeeper"), + new Builder("mesos.Environment.Variable").setName("flink_recovery_zookeeper_quorum").setValue("172.17.10.101:2181"), + new Builder("mesos.Environment.Variable").setName("flink_recovery_zookeeper_storageDir").setValue("/data/zk") ]), // Environment false, // Is shell? null, // Command @@ -63,14 +64,14 @@ var scheduler = new Scheduler({ "commandInfo": new Mesos.CommandInfo( // Strangely, this is needed, even when specifying ContainerInfo... null, // URI new Mesos.Environment([ - new Mesos.Environment.Variable("flink_recovery_mode", "zookeeper"), - new Mesos.Environment.Variable("flink_recovery_zookeeper_quorum", "172.17.10.101:2181"), - new Mesos.Environment.Variable("flink_recovery_zookeeper_storageDir", "/data/zk"), - new Mesos.Environment.Variable("flink_taskmanager_tmp_dirs", "/data/tasks"), - new Mesos.Environment.Variable("flink_blob_storage_directory", "/data/blobs"), - new Mesos.Environment.Variable("flink_state_backend", "filesystem"), - new Mesos.Environment.Variable("flink_taskmanager_numberOfTaskSlots", "1"), - new Mesos.Environment.Variable("flink_taskmanager_heap_mb", "1536") + new Builder("mesos.Environment.Variable").setName("flink_recovery_mode").setValue("zookeeper"), + new Builder("mesos.Environment.Variable").setName("flink_recovery_zookeeper_quorum").setValue("172.17.10.101:2181"), + new Builder("mesos.Environment.Variable").setName("flink_recovery_zookeeper_storageDir").setValue("/data/zk"), + new Builder("mesos.Environment.Variable").setName("flink_taskmanager_tmp_dirs").setValue("/data/tasks"), + new Builder("mesos.Environment.Variable").setName("flink_blob_storage_directory").setValue("/data/blobs"), + new Builder("mesos.Environment.Variable").setName("flink_state_backend").setValue("filesystem"), + new Builder("mesos.Environment.Variable").setName("flink_taskmanager_numberOfTaskSlots").setValue("1"), + new Builder("mesos.Environment.Variable").setName("flink_taskmanager_heap_mb").setValue("1536") ]), // Environment false, // Is shell? null, // Command diff --git a/examples/dockerSchedulerHostNetworking.js b/examples/dockerSchedulerHostNetworking.js index ca1394e..d467762 100644 --- a/examples/dockerSchedulerHostNetworking.js +++ b/examples/dockerSchedulerHostNetworking.js @@ -2,6 +2,7 @@ var Scheduler = require("../index").Scheduler; var Mesos = require("../index").Mesos.getMesos(); +var Builder = require("../index").Builder; var ContainerInfo = new Mesos.ContainerInfo( Mesos.ContainerInfo.Type.DOCKER, // Type @@ -36,7 +37,7 @@ var scheduler = new Scheduler({ "commandInfo": new Mesos.CommandInfo( // Strangely, this is needed, even when specifying ContainerInfo... null, // URI new Mesos.Environment([ - new Mesos.Environment.Variable("FOO", "BAR") + new Builder("mesos.Environment.Variable").setName("FOO").setValue("BAR") ]), // Environment false, // Is shell? null, // Command diff --git a/examples/dockerSchedulerHostNetworkingZk.js b/examples/dockerSchedulerHostNetworkingZk.js index c4b4113..9d893c1 100644 --- a/examples/dockerSchedulerHostNetworkingZk.js +++ b/examples/dockerSchedulerHostNetworkingZk.js @@ -2,6 +2,7 @@ var Scheduler = require("../index").Scheduler; var Mesos = require("../index").Mesos.getMesos(); +var Builder = require("../index").Builder; var ContainerInfo = new Mesos.ContainerInfo( Mesos.ContainerInfo.Type.DOCKER, // Type @@ -38,7 +39,7 @@ var scheduler = new Scheduler({ "commandInfo": new Mesos.CommandInfo( // Strangely, this is needed, even when specifying ContainerInfo... null, // URI new Mesos.Environment([ - new Mesos.Environment.Variable("FOO", "BAR") + new Builder("mesos.Environment.Variable").setName("FOO").setValue("BAR") ]), // Environment false, // Is shell? null, // Command From bd6c3b809d51313d4988e2dd972d12b721e501ba Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sat, 3 Mar 2018 14:25:31 +0100 Subject: [PATCH 03/13] Update dependencies --- package-lock.json | 5524 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 12 +- 2 files changed, 5530 insertions(+), 6 deletions(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c8921df --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5524 @@ +{ + "name": "mesos-framework", + "version": "0.7.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "always-error": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/always-error/-/always-error-1.0.0.tgz", + "integrity": "sha1-lchAQs+obzjIbKbCzELAoBA0QbI=", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "requires": { + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true + }, + "ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "0.7.1", + "optjs": "3.2.2" + } + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + }, + "atob": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", + "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "dev": true + }, + "babylon": { + "version": "7.0.0-beta.19", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", + "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "ban-sensitive-files": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/ban-sensitive-files/-/ban-sensitive-files-1.9.2.tgz", + "integrity": "sha512-8dlYLybLhAKvd2fGoDd2zskdbO8pm/FKxTwy+iA5mqq4bKovZNM4xNAzYWbttW9yjbxTz1O3SN+cyUx3LEG5CQ==", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "check-more-types": "2.24.0", + "debug": "3.1.0", + "ggit": "2.4.2", + "lazy-ass": "1.6.0", + "pluralize": "7.0.0", + "ramda": "0.25.0", + "update-notifier": "2.3.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + } + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "requires": { + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "2.3.1", + "cli-boxes": "1.0.0", + "string-width": "2.1.1", + "term-size": "1.2.0", + "widest-line": "2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "5.2.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", + "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "kind-of": "6.0.2", + "repeat-element": "1.1.2", + "snapdragon": "0.8.1", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "requires": { + "long": "3.2.0" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + } + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", + "dev": true + }, + "catharsis": { + "version": "0.8.9", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz", + "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=", + "dev": true, + "requires": { + "underscore-contrib": "0.3.0" + } + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + }, + "dependencies": { + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true, + "optional": true + } + } + }, + "chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "dev": true, + "requires": { + "assertion-error": "1.1.0", + "deep-eql": "0.1.3", + "type-detect": "1.0.0" + } + }, + "chai-as-promised": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-6.0.0.tgz", + "integrity": "sha1-GgKkM6byTa+sY7nJb6FoTbGqjaY=", + "dev": true, + "requires": { + "check-error": "1.0.2" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "chdir-promise": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/chdir-promise/-/chdir-promise-0.6.2.tgz", + "integrity": "sha512-EG5MutQt4qTxoQPfBtPCfU1A/MqborgaO66xrPSD/dRTB40OLN0wy+YAo5ZAw7DawhtCPdZHAdQ206fyWkhoiw==", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "check-more-types": "2.24.0", + "debug": "3.1.0", + "lazy-ass": "1.6.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "dev": true, + "requires": { + "colors": "1.0.3" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "clone": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + }, + "colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "configstore": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz", + "integrity": "sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw==", + "dev": true, + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.2.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cp-sugar": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cp-sugar/-/cp-sugar-1.0.0.tgz", + "integrity": "sha1-HCb5vcocA89q90SmVSOf+THMq28=", + "dev": true, + "requires": { + "cross-spawn-async": "2.2.5", + "pinkie-promise": "2.0.1", + "promisify-event": "1.0.0", + "shell-quote": "1.6.1" + } + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + } + } + }, + "cross-spawn-async": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", + "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "which": "1.3.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + } + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" + }, + "d3-helpers": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/d3-helpers/-/d3-helpers-0.3.0.tgz", + "integrity": "sha1-SzHc5KISGnczY4RXTYk/vtX7KT0=", + "dev": true + }, + "dargs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", + "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=", + "dev": true + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "requires": { + "type-detect": "0.1.1" + }, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true + } + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "1.0.3" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + } + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "1.0.1" + } + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, + "elegant-status": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/elegant-status/-/elegant-status-1.1.0.tgz", + "integrity": "sha1-Qe9KXy0DZCmDurtPZKS1drEVUhU=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "elegant-spinner": "1.0.1", + "log-update": "1.0.2", + "os-family": "1.0.0" + } + }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "1.3.3" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + }, + "dependencies": { + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "execa": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.6.3.tgz", + "integrity": "sha1-V7aaWU8IF1nGnlNw8NF7nLEWWP4=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.1", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.1", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "1.0.0", + "is-glob": "3.1.0", + "micromatch": "3.1.9", + "resolve-dir": "1.0.1" + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0", + "object.pick": "1.3.0", + "parse-filepath": "1.0.2" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "formatio": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "dev": true, + "requires": { + "samsam": "1.1.2" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "dev": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "fstream-npm": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/fstream-npm/-/fstream-npm-1.2.1.tgz", + "integrity": "sha512-iBHpm/LmD1qw0TlHMAqVd9rwdU6M+EHRUnPkXpRi5G/Hf0FIFH+oZFryodAU2MFNfGRh/CzhUFlMKV3pdeOTDw==", + "dev": true, + "requires": { + "fstream-ignore": "1.0.5", + "inherits": "2.0.3" + } + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "ggit": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/ggit/-/ggit-2.4.2.tgz", + "integrity": "sha512-4pltyhG4cjVT1Nqs9pq8Iykc/lTibc4LKRUAxszA9+OgwpfGhbsFgzhtyXwh5AbiWZrBa87nIHzyVGlJoT4nCw==", + "dev": true, + "requires": { + "always-error": "1.0.0", + "bluebird": "3.5.1", + "chdir-promise": "0.6.2", + "check-more-types": "2.24.0", + "cli-table": "0.3.1", + "colors": "1.1.2", + "commander": "2.12.2", + "d3-helpers": "0.3.0", + "debug": "3.1.0", + "find-up": "2.1.0", + "glob": "7.1.2", + "lazy-ass": "1.6.0", + "lodash": "4.17.4", + "moment": "2.19.3", + "moment-timezone": "0.5.14", + "optimist": "0.6.1", + "pluralize": "7.0.0", + "q": "2.0.3", + "quote": "0.4.0", + "ramda": "0.25.0", + "semver": "5.4.1" + }, + "dependencies": { + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "commander": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + }, + "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" + } + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "0.5.2" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "0.1.1" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "1.3.5" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.0" + } + }, + "globby": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-4.1.0.tgz", + "integrity": "sha1-CA9UVJ7BuCpsYOYx/ILhIR2+lfg=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "6.0.4", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "dev": true, + "requires": { + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.0", + "safe-buffer": "5.1.1", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.1" + } + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.1.0", + "liftoff": "2.5.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "gulp-istanbul": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gulp-istanbul/-/gulp-istanbul-1.1.3.tgz", + "integrity": "sha512-uMLSdqPDnBAV/B9rNyOgVMgrVC1tPbe+5GH6P13UOyxbRDT/w4sKYHWftPMA8j9om+NFvfeRlqpDXL2fixFWNA==", + "dev": true, + "requires": { + "istanbul": "0.4.5", + "istanbul-threshold-checker": "0.2.1", + "lodash": "4.17.5", + "plugin-error": "0.1.2", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" + } + }, + "gulp-mocha": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gulp-mocha/-/gulp-mocha-4.3.1.tgz", + "integrity": "sha1-d5ULQ7z/gWWVdnwHNOD9p9Fz3Nk=", + "dev": true, + "requires": { + "dargs": "5.1.0", + "execa": "0.6.3", + "gulp-util": "3.0.8", + "mocha": "3.5.3", + "npm-run-path": "2.0.2", + "through2": "2.0.3" + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.2", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.1" + } + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "ansi-regex": "2.1.1", + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-width": "2.2.0", + "figures": "1.7.0", + "lodash": "4.17.5", + "readline2": "1.0.1", + "run-async": "0.1.0", + "rx-lite": "3.1.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "through": "2.3.8" + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "1.0.0", + "is-windows": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "0.1.1", + "is-path-inside": "1.0.1" + } + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "dev": true, + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "1.0.0" + } + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.11", + "js-yaml": "3.10.0", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.0", + "wordwrap": "1.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-threshold-checker": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/istanbul-threshold-checker/-/istanbul-threshold-checker-0.2.1.tgz", + "integrity": "sha1-xdyU6PLMXNP/0zVFL4S1U8QkgzE=", + "dev": true, + "requires": { + "istanbul": "0.4.5", + "lodash": "4.17.5" + } + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + } + } + }, + "js2xmlparser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz", + "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=", + "dev": true, + "requires": { + "xmlcreate": "1.0.2" + } + }, + "jsdoc": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz", + "integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==", + "dev": true, + "requires": { + "babylon": "7.0.0-beta.19", + "bluebird": "3.5.1", + "catharsis": "0.8.9", + "escape-string-regexp": "1.0.5", + "js2xmlparser": "3.0.0", + "klaw": "2.0.0", + "marked": "0.3.17", + "mkdirp": "0.5.1", + "requizzle": "0.2.1", + "strip-json-comments": "2.0.1", + "taffydb": "2.6.2", + "underscore": "1.8.3" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", + "dev": true + } + } + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "klaw": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz", + "integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "dev": true, + "requires": { + "package-json": "4.0.1" + } + }, + "lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", + "dev": true + }, + "lazy-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", + "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", + "dev": true, + "requires": { + "set-getter": "0.1.0" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "3.0.1", + "findup-sync": "2.0.0", + "fined": "1.1.0", + "flagged-respawn": "1.0.0", + "is-plain-object": "2.0.4", + "object.map": "1.0.1", + "rechoir": "0.6.2", + "resolve": "1.5.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", + "dev": true + }, + "log-update": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", + "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "cli-cursor": "1.0.2" + } + }, + "lolex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", + "dev": true + }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "make-dir": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", + "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + }, + "make-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz", + "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "marked": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.17.tgz", + "integrity": "sha512-+AKbNsjZl6jFfLPwHhWmGTqE009wTKn3RTmn9K8oUKHrX/abPJjtcRtXpYB/FFrwPJRUA86LX/de3T0knkPCmQ==", + "dev": true + }, + "micromatch": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.9.tgz", + "integrity": "sha512-SlIz6sv5UPaAVVFRKodKjCg48EbNoIhgetzfK/Cy0v5U52Z6zB136M8tp0UC9jM53LYbmIRihJszvvqpKkfm9g==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.1", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.1", + "to-regex": "3.0.2" + } + }, + "minami": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/minami/-/minami-1.2.3.tgz", + "integrity": "sha1-mbbc37LwpU2hycj3qjoyd4eq+fg=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "mock-req": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/mock-req/-/mock-req-0.2.0.tgz", + "integrity": "sha1-dJRGgE0sAGFpNC7nvmu6HP/VNMI=", + "dev": true + }, + "mock-res": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/mock-res/-/mock-res-0.3.3.tgz", + "integrity": "sha1-srN9ylpK1pMLzfl2V3i+mSfUDQU=", + "dev": true + }, + "moment": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.3.tgz", + "integrity": "sha1-vbmdJw1tf9p4zA+6zoVeJ/59pp8=", + "dev": true + }, + "moment-timezone": { + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.14.tgz", + "integrity": "sha1-TrOP+VOLgBCLpGekWPPtQmjM/LE=", + "dev": true, + "requires": { + "moment": "2.19.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.1", + "to-regex": "3.0.2" + } + }, + "natives": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz", + "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==", + "dev": true + }, + "node-emoji": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.8.1.tgz", + "integrity": "sha512-+ktMAh1Jwas+TnGodfCfjUbJKoANqPaJFN0z0iqh41eqD8dvguNzcitVSBSVK1pidz0AqGbLKcoVuVLRVZ/aVg==", + "dev": true, + "requires": { + "lodash.toarray": "4.4.0" + } + }, + "node-zookeeper-client": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/node-zookeeper-client/-/node-zookeeper-client-0.2.2.tgz", + "integrity": "sha1-CXvaAZme749gLOBotjJgAGnb9oU=", + "requires": { + "async": "0.2.10", + "underscore": "1.4.4" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.0.9" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "4.3.6", + "validate-npm-package-license": "3.0.3" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "nsp": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/nsp/-/nsp-2.8.1.tgz", + "integrity": "sha512-jvjDg2Gsw4coD/iZ5eQddsDlkvnwMCNnpG05BproSnuG+Gr1bSQMwWMcQeYje+qdDl3XznmhblMPLpZLecTORQ==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cli-table": "0.3.1", + "cvss": "1.0.2", + "https-proxy-agent": "1.0.0", + "joi": "6.10.1", + "nodesecurity-npm-utils": "5.0.0", + "path-is-absolute": "1.0.1", + "rc": "1.2.1", + "semver": "5.4.1", + "subcommand": "2.1.0", + "wreck": "6.3.0" + }, + "dependencies": { + "agent-base": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true, + "requires": { + "extend": "3.0.1", + "semver": "5.0.3" + }, + "dependencies": { + "semver": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + } + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "dev": true, + "requires": { + "colors": "1.0.3" + } + }, + "cliclopts": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cliclopts/-/cliclopts-1.1.1.tgz", + "integrity": "sha1-aUMcfLWvcjd0sNORG0w3USQxkQ8=", + "dev": true + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + }, + "cvss": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cvss/-/cvss-1.0.2.tgz", + "integrity": "sha1-32fpK/EqeW9J6Sh5nI2zunS5/NY=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "isemail": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", + "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=", + "dev": true + }, + "joi": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", + "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", + "dev": true, + "requires": { + "hoek": "2.16.3", + "isemail": "1.2.0", + "moment": "2.18.1", + "topo": "1.1.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "moment": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", + "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nodesecurity-npm-utils": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nodesecurity-npm-utils/-/nodesecurity-npm-utils-5.0.0.tgz", + "integrity": "sha1-Baow3jDKjIRcQEjpT9eOXgi1Xtk=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "dev": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + } + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "subcommand": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/subcommand/-/subcommand-2.1.0.tgz", + "integrity": "sha1-XkzspaN3njNlsVEeBfhmh3MC92A=", + "dev": true, + "requires": { + "cliclopts": "1.1.1", + "debug": "2.6.9", + "minimist": "1.2.0", + "xtend": "4.0.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "topo": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", + "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "wreck": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/wreck/-/wreck-6.3.0.tgz", + "integrity": "sha1-oTaXafB7u2LWo3gzanhx/Hc8dAs=", + "dev": true, + "requires": { + "boom": "2.10.1", + "hoek": "2.16.3" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.1.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "1.0.0", + "make-iterator": "1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.1" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-family": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/os-family/-/os-family-1.0.0.tgz", + "integrity": "sha1-0SMIxCSjYwKhwQapUoe73VyiR38=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.2.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "requires": { + "got": "6.7.1", + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0", + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "1.0.0", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pkgd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pkgd/-/pkgd-1.1.2.tgz", + "integrity": "sha1-aaumxykr0s8Dun8+LqqBydOj5Gk=", + "dev": true, + "requires": { + "fstream-npm": "1.2.1", + "normalize-path": "2.1.1", + "pinkie-promise": "2.0.1" + } + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + } + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "pop-iterate": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pop-iterate/-/pop-iterate-1.0.1.tgz", + "integrity": "sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M=", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "promisify-event": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/promisify-event/-/promisify-event-1.0.0.tgz", + "integrity": "sha1-vXUj6ga3AWLzcJeQFrU6aGxg6Q8=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "protobufjs": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.2.tgz", + "integrity": "sha1-WXSNfc8D0tsiwT2p/rAk4Wq4DJE=", + "requires": { + "ascli": "1.0.1", + "bytebuffer": "5.0.1", + "glob": "7.1.2", + "yargs": "3.32.0" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "publish-please": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/publish-please/-/publish-please-2.3.1.tgz", + "integrity": "sha1-KQbBKP4f1rjG7LXxK7kNDkJlqWU=", + "dev": true, + "requires": { + "ban-sensitive-files": "1.9.2", + "chalk": "1.1.3", + "cp-sugar": "1.0.0", + "elegant-status": "1.1.0", + "globby": "4.1.0", + "inquirer": "0.12.0", + "lodash": "4.17.5", + "node-emoji": "1.8.1", + "nsp": "2.8.1", + "pinkie-promise": "2.0.1", + "pkgd": "1.1.2", + "promisify-event": "1.0.0", + "read-pkg": "1.1.0", + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } + } + }, + "q": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/q/-/q-2.0.3.tgz", + "integrity": "sha1-dbjbAlWhpa+C9Yw/Oqoe/sfQ0TQ=", + "dev": true, + "requires": { + "asap": "2.0.6", + "pop-iterate": "1.0.1", + "weak-map": "1.0.5" + } + }, + "quote": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/quote/-/quote-0.4.0.tgz", + "integrity": "sha1-EIOSF/bBNiuJGUBE0psjP9fzLwE=", + "dev": true + }, + "ramda": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz", + "integrity": "sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ==", + "dev": true + }, + "rc": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.5.tgz", + "integrity": "sha1-J1zWh/bjs2zHVrqibf7oCnkDAf0=", + "dev": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "mute-stream": "0.0.5" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.5.0" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "requires": { + "rc": "1.2.5", + "safe-buffer": "5.1.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "1.2.5" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "requirefrom": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/requirefrom/-/requirefrom-0.2.1.tgz", + "integrity": "sha1-bw0V8x4ekV3KjE6kO98v9B+6ADg=" + }, + "requizzle": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", + "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=", + "dev": true, + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + } + } + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "run-sequence": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-1.2.2.tgz", + "integrity": "sha1-UJWgvr6YczsBQL0I3YDsAw3azes=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "gulp-util": "3.0.8" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "samsam": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", + "dev": true + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } + } + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "set-getter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", + "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", + "dev": true, + "requires": { + "to-object-path": "0.3.0" + } + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "0.0.1", + "array-map": "0.0.0", + "array-reduce": "0.0.0", + "jsonify": "0.0.0" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sinon": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", + "dev": true, + "requires": { + "formatio": "1.1.1", + "lolex": "1.3.2", + "samsam": "1.1.2", + "util": "0.10.3" + } + }, + "snapdragon": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", + "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "2.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "dev": true, + "requires": { + "atob": "2.0.3", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "stream-consume": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "0.7.0" + }, + "dependencies": { + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.4", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "optional": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "optional": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "underscore": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=" + }, + "underscore-contrib": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz", + "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=", + "dev": true, + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + } + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "1.0.0" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true + }, + "update-notifier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.3.0.tgz", + "integrity": "sha1-TognpruRUUCrCTVZ1wFOPruDdFE=", + "dev": true, + "requires": { + "boxen": "1.3.0", + "chalk": "2.3.1", + "configstore": "3.1.1", + "import-lazy": "2.1.0", + "is-installed-globally": "0.1.0", + "is-npm": "1.0.0", + "latest-version": "3.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "5.2.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "1.0.4" + } + }, + "use": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", + "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "isobject": "3.0.1", + "lazy-cache": "2.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "dev": true, + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "weak-map": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz", + "integrity": "sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes=", + "dev": true + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "widest-line": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.0.tgz", + "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", + "dev": true, + "requires": { + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "winston": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.0.tgz", + "integrity": "sha1-gIBQuT1SZh7Z+2wms/DIJnCLCu4=", + "requires": { + "async": "1.0.0", + "colors": "1.0.3", + "cycle": "1.0.3", + "eyes": "0.1.8", + "isstream": "0.1.2", + "stack-trace": "0.0.10" + }, + "dependencies": { + "async": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" + } + } + }, + "winston-daily-rotate-file": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-1.7.2.tgz", + "integrity": "sha1-ZQK/opeCT9mC2l5WR8dThXjS+aA=", + "requires": { + "mkdirp": "0.5.1" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true + }, + "xmlcreate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz", + "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "2.1.1", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "string-width": "1.0.2", + "window-size": "0.1.4", + "y18n": "3.2.1" + } + } + } +} diff --git a/package.json b/package.json index 4434cc0..4dfb06a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mesos-framework", - "version": "0.6.0", + "version": "0.7.0", "description": "A wrapper around the Mesos HTTP APIs for Schedulers and Executors. Write your Mesos framework in pure JavaScript!", "keywords": [ "mesos", @@ -23,13 +23,13 @@ "author": "TobiLG", "license": "Apache-2.0", "dependencies": { - "lodash": "^4.17.4", + "lodash": "^4.17.5", "node-zookeeper-client": "^0.2.2", "protobufjs": "^5.0.2", "requirefrom": "^0.2.1", - "uuid": "^3.1.0", - "winston": "^2.3.1", - "winston-daily-rotate-file": "^1.4.6" + "uuid": "^3.2.1", + "winston": "^2.4.0", + "winston-daily-rotate-file": "^1.7.2" }, "devDependencies": { "chai": "^3.5.0", @@ -39,7 +39,7 @@ "gulp-istanbul": "~1.1.2", "gulp-mocha": "~4.3.1", "istanbul": "0.4.5", - "jsdoc": "^3.4.3", + "jsdoc": "^3.5.5", "minami": "^1.2.3", "mocha": "^3.4.2", "mock-req": "^0.2.0", From 6a6b757f3e326104d7ad83e26d421e951f2a6590 Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sat, 3 Mar 2018 14:25:49 +0100 Subject: [PATCH 04/13] Use docker-compose for local development --- docker-compose.yml | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9b82787 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,43 @@ +version: "2" + +services: + zk: + image: bobrik/zookeeper + network_mode: host + environment: + ZK_CONFIG: tickTime=2000,initLimit=10,syncLimit=5,maxClientCnxns=128,forceSync=no,clientPort=2181 + ZK_ID: 1 + + master: + image: mesosphere/mesos-master:1.5.0 + network_mode: host + environment: + MESOS_ZK: zk://127.0.0.1:2181/mesos + MESOS_QUORUM: 1 + MESOS_CLUSTER: docker-compose + MESOS_REGISTRY: replicated_log + MESOS_HOSTNAME: ${DOCKER_IP} + LIBPROCESS_IP: ${DOCKER_IP} + depends_on: + - zk + + agent: + image: mesosphere/mesos-slave:1.5.0 + network_mode: host + pid: host + environment: + MESOS_SYSTEMD_ENABLE_SUPPORT: "false" + MESOS_MASTER: zk://127.0.0.1:2181/mesos + MESOS_CONTAINERIZERS: docker,mesos + MESOS_PORT: 5051 + MESOS_RESOURCES: ports(*):[11000-11999] + MESOS_HOSTNAME: ${DOCKER_IP} + LIBPROCESS_IP: ${DOCKER_IP} + MESOS_WORK_DIR: /tmp/mesos + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup + - /usr/local/bin/docker:/usr/bin/docker + - /var/run/docker.sock:/var/run/docker.sock + depends_on: + - zk + - master \ No newline at end of file From 9e9415fa806d8adb646a1063d07d17e64a16ea54 Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sat, 3 Mar 2018 14:26:27 +0100 Subject: [PATCH 05/13] Update readme --- README.md | 61 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 7648ac7..7f96aba 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Package version](https://img.shields.io/npm/v/mesos-framework.svg)](https://www.npmjs.com/package/mesos-framework) [![Package downloads](https://img.shields.io/npm/dt/mesos-framework.svg)](https://www.npmjs.com/package/mesos-framework) [![Package license](https://img.shields.io/npm/l/mesos-framework.svg)](https://www.npmjs.com/package/mesos-framework) [![Build Status](https://travis-ci.org/tobilg/mesos-framework.svg?branch=master)](https://travis-ci.org/tobilg/mesos-framework) This project provides a high-level wrapper around the Mesos HTTP APIs for [schedulers](http://mesos.apache.org/documentation/latest/scheduler-http-api/) and [executors](http://mesos.apache.org/documentation/latest/executor-http-api/). -It can be used to write Mesos frameworks in pure JavaScript. The currently supported Mesos version is `1.2.0`. +It can be used to write Mesos frameworks in pure JavaScript. The currently supported Mesos version is `1.5.0`. ## Installation @@ -131,30 +131,23 @@ Also, you can have a look at the `examples` folder to see examples for command-b ```javascript "use strict"; - + var Scheduler = require("mesos-framework").Scheduler; var Mesos = require("mesos-framework").Mesos.getMesos(); - + var scheduler = new Scheduler({ - "masterUrl": "172.17.10.101", // If Mesos DNS is used this would be "leader.mesos", otherwise use the actual IP address of the leading master + "masterUrl": "172.17.11.102", // If Mesos DNS is used this would be "leader.mesos", otherwise use the actual IP address of the leading master "port": 5050, "frameworkName": "My first Command framework", "logging": { - "level": "debug" // Set log Level to debug (default is info) + "level": "debug" }, - "restartStates": ["TASK_FAILED", "TASK_KILLED", "TASK_LOST", "TASK_ERROR", "TASK_FINISHED"], // Overwrite the restartStates (by default, TASK_FINISHED tasks are NOT restarted!) + "restartStates": ["TASK_FAILED", "TASK_KILLED", "TASK_LOST", "TASK_ERROR", "TASK_FINISHED"], "tasks": { "sleepProcesses": { "priority": 1, "instances": 3, - "commandInfo": new Mesos.CommandInfo( - null, // URI - null, // Environment - true, // Is shell? - "sleep 10;", // Command - null, // Arguments - null // User - ), + "commandInfo": new Builder("mesos.CommandInfo").setValue("env && sleep 100").setShell(true), "resources": { "cpus": 0.2, "mem": 128, @@ -170,16 +163,16 @@ var scheduler = new Scheduler({ } } }); - + // Start the main logic once the framework scheduler has received the "SUBSCRIBED" event from the leading Mesos master scheduler.on("subscribed", function (obj) { - + // Display the Mesos-Stream-Id scheduler.logger.info("Mesos Stream Id is " + obj.mesosStreamId); - + // Display the framework id scheduler.logger.info("Framework Id is " + obj.frameworkId); - + // Trigger shutdown after one minute setTimeout(function() { // Send "TEARDOWN" request @@ -187,25 +180,25 @@ scheduler.on("subscribed", function (obj) { // Shutdown process process.exit(0); }, 60000); - + }); - + // Capture "offers" events scheduler.on("offers", function (offers) { scheduler.logger.info("Got offers: " + JSON.stringify(offers)); }); - + // Capture "heartbeat" events scheduler.on("heartbeat", function (heartbeatTimestamp) { scheduler.logger.info("Heartbeat on " + heartbeatTimestamp); }); - + // Capture "error" events scheduler.on("error", function (error) { scheduler.logger.info("ERROR: " + JSON.stringify(error)); scheduler.logger.info(error.stack); }); - + scheduler.on("ready", function () { // Start framework scheduler scheduler.subscribe(); @@ -250,12 +243,14 @@ The following events from the Executor calls are exposed: ### Mesos +#### Creating objects ("natively" via protobufjs) + The module also exposes the Mesos protocol buffer object, which is loaded via [protobuf.js](https://github.com/dcodeIO/ProtoBuf.js/). It can be used to create the objects which can be then passed to the scheduler/executor methods. **Example:** ```javascript var Mesos = require("mesos-framework").Mesos.getMesos(); - + var TaskID = new Mesos.TaskID("my-task-id"); ``` @@ -264,13 +259,27 @@ You can also instantiate Mesos protocol buffer objects from plain JSON. Be sure **Example:** ```javascript var Builder = require("mesos-framework").Mesos.getBuilder(); - + var taskId = { "value": "my-task-id" }; var TaskID = new (Builder.build("mesos.TaskID"))(taskId); ``` + +#### Creating objects (via builder pattern) + +You can also create Mesos objects via the builder pattern like this: + +**Example:** +```javascript +var Builder = require("mesos-framework").Builder; + +var commandInfo = new Builder("mesos.CommandInfo") + .setValue("env && sleep 100") + .setShell(true); +``` + ### taskHealthHelper This module allows for testing of task health (or any metric available via HTTP, for example cluster state, leader, etc...) and emit a scheduler event so the issue will be handled in code. @@ -291,4 +300,4 @@ The additional properties array is an array of objects with the following member * `name`: The name of the property to set, for example: "leader" (mandatory). * `setUnhealthy`: Should the property be set when the check fails (optional, when unset it only sets the property when healthy). -* `inverse`: Whether the health status and the property are inversed or not (optional). \ No newline at end of file +* `inverse`: Whether the health status and the property are inversed or not (optional). From d38dc3c3c56918f502866277ab9572ec882d0745 Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sat, 3 Mar 2018 14:26:41 +0100 Subject: [PATCH 06/13] Expose builder --- index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/index.js b/index.js index 14e1702..f81f9d5 100644 --- a/index.js +++ b/index.js @@ -5,3 +5,4 @@ module.exports.Executor = require("./lib/executor"); module.exports.Mesos = require("./lib/mesos")(); module.exports.TaskHealthHelper = require("./lib/taskHealthHelper"); module.exports.helpers = require("./lib/helpers"); +module.exports.Builder = require("./lib/builder"); From d72c1cbc2050487a4e16fd061334f808a0946aa7 Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sat, 3 Mar 2018 14:27:23 +0100 Subject: [PATCH 07/13] Enable Mesos 1.5.0 support --- docs/scheduler.js.html | 6 +- lib/helpers.js | 6 +- lib/scheduler.js | 8 +- lib/schedulerHandlers.js | 48 +++---- tests/helpers.test.js | 24 ++-- tests/scheduler.test.js | 112 ++++++++-------- tests/schedulerHandlers.test.js | 225 ++++++++++++++++---------------- tests/taskHealthHelper.test.js | 2 +- tests/taskHelper.test.js | 42 +++--- 9 files changed, 242 insertions(+), 231 deletions(-) diff --git a/docs/scheduler.js.html b/docs/scheduler.js.html index b55fb73..847bacd 100644 --- a/docs/scheduler.js.html +++ b/docs/scheduler.js.html @@ -590,7 +590,7 @@

scheduler.js

self.logger.info("SUBSCRIBE: " + JSON.stringify(Subscribe)); // Set the Call object - var Call = helpers.stringifyEnumsRecursive( + var Call = helpers.fixEnums( new mesos.scheduler.Call( self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null, "SUBSCRIBE", @@ -624,7 +624,7 @@

scheduler.js

self.logger.info("ACCEPT: " + JSON.stringify(Accept)); // Set the Call object - var Call = helpers.stringifyEnumsRecursive(new mesos.scheduler.Call(new mesos.FrameworkID(self.frameworkId), "ACCEPT", null, Accept)); + var Call = helpers.fixEnums(new mesos.scheduler.Call(new mesos.FrameworkID(self.frameworkId), "ACCEPT", null, Accept)); helpers.doRequest.call(self, Call, function (error, response) { if (error) { @@ -649,7 +649,7 @@

scheduler.js

var Decline = new mesos.scheduler.Call.Decline(offers, filters); // Set the Call object - var Call = helpers.stringifyEnumsRecursive(new mesos.scheduler.Call(new mesos.FrameworkID(self.frameworkId), "DECLINE", null, null, Decline)); + var Call = helpers.fixEnums(new mesos.scheduler.Call(new mesos.FrameworkID(self.frameworkId), "DECLINE", null, null, Decline)); helpers.doRequest.call(self, Call, function (error, response) { if (error) { diff --git a/lib/helpers.js b/lib/helpers.js index 20af5df..438bc0e 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -141,18 +141,18 @@ module.exports = { return message; }, - stringifyEnumsRecursive: function (message) { + fixEnums: function (message) { var self = this; var newMessage = self.stringifyEnums(message); _.forEach(message, function(subMessage, key) { if (_.isObject(subMessage) && subMessage.$type) { - newMessage[key] = self.stringifyEnumsRecursive(message[key]); + newMessage[key] = self.fixEnums(message[key]); } else if (_.isArray(subMessage) && subMessage.length > 0) { var arrayItems = []; var index; for (index = 0; index < subMessage.length; index += 1) { if (_.isObject(subMessage[index]) && subMessage[index].$type) { - arrayItems.push(self.stringifyEnumsRecursive(subMessage[index])); + arrayItems.push(self.fixEnums(subMessage[index])); } else { arrayItems.push(subMessage[index]); } diff --git a/lib/scheduler.js b/lib/scheduler.js index 1fe8c2a..33a17e7 100644 --- a/lib/scheduler.js +++ b/lib/scheduler.js @@ -200,7 +200,7 @@ function Scheduler (options) { self.logger.debug("error:" + JSON.stringify(error)); // Check if node doesn't exist yet - if (error.getCode() == zookeeper.Exception.NO_NODE) { + if (error.getCode() === zookeeper.Exception.NO_NODE) { self.logger.debug("Node " + zkPath + " doesn't exist yet. Will be created on framework launch"); @@ -549,7 +549,7 @@ Scheduler.prototype.subscribe = function () { self.logger.info("SUBSCRIBE: " + JSON.stringify(Subscribe)); // Set the Call object - var Call = helpers.stringifyEnumsRecursive( + var Call = helpers.fixEnums( new mesos.scheduler.Call( self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null, "SUBSCRIBE", @@ -583,7 +583,7 @@ Scheduler.prototype.accept = function (offers, operations, filters) { self.logger.info("ACCEPT: " + JSON.stringify(Accept)); // Set the Call object - var Call = helpers.stringifyEnumsRecursive(new mesos.scheduler.Call(new mesos.FrameworkID(self.frameworkId), "ACCEPT", null, Accept)); + var Call = helpers.fixEnums(new mesos.scheduler.Call(new mesos.FrameworkID(self.frameworkId), "ACCEPT", null, Accept)); helpers.doRequest.call(self, Call, function (error, response) { if (error) { @@ -608,7 +608,7 @@ Scheduler.prototype.decline = function (offers, filters) { var Decline = new mesos.scheduler.Call.Decline(offers, filters); // Set the Call object - var Call = helpers.stringifyEnumsRecursive(new mesos.scheduler.Call(new mesos.FrameworkID(self.frameworkId), "DECLINE", null, null, Decline)); + var Call = helpers.fixEnums(new mesos.scheduler.Call(new mesos.FrameworkID(self.frameworkId), "DECLINE", null, null, Decline)); helpers.doRequest.call(self, Call, function (error, response) { if (error) { diff --git a/lib/schedulerHandlers.js b/lib/schedulerHandlers.js index cf0149a..a733acf 100644 --- a/lib/schedulerHandlers.js +++ b/lib/schedulerHandlers.js @@ -5,7 +5,6 @@ var lib = require("requirefrom")("lib"); var Mesos = lib("mesos"); var Builder = lib("builder"); var helpers = lib("helpers"); - var mesos = new Mesos().getMesos(); function searchPortsInRanges(task, offerResources, usableRanges, neededStaticPorts, neededPorts) { @@ -159,8 +158,8 @@ module.exports = { var envVars = []; var demandedResources = [ - helpers.stringifyEnumsRecursive(new mesos.Resource("cpus", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(task.resources.cpus))), - helpers.stringifyEnumsRecursive(new mesos.Resource("mem", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(task.resources.mem))) + helpers.fixEnums(new Builder("mesos.Resource").setName("cpus").setType(mesos.Value.Type.SCALAR).setScalar(new mesos.Value.Scalar(task.resources.cpus))), + helpers.fixEnums(new Builder("mesos.Resource").setName("mem").setType(mesos.Value.Type.SCALAR).setScalar(new mesos.Value.Scalar(task.resources.mem))) ]; // Reduce available offer cpu and mem resources by requested task resources @@ -168,7 +167,7 @@ module.exports = { offerResources.mem -= task.resources.mem; if (task.resources.disk > 0) { - demandedResources.push(helpers.stringifyEnumsRecursive(new mesos.Resource("disk", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(task.resources.disk)))); + demandedResources.push(helpers.fixEnums(new Builder("mesos.Resource").setName("disk").setType(mesos.Value.Type.SCALAR).setScalar(new mesos.Value.Scalar(task.resources.disk)))); // Reduce disk resources by requested task resources offerResources.disk -= task.resources.disk; } @@ -221,7 +220,15 @@ module.exports = { } // Add to demanded resources - demandedResources.push(helpers.stringifyEnumsRecursive(new mesos.Resource("ports", mesos.Value.Type.RANGES, null, new mesos.Value.Ranges(usedPortRanges)))); + demandedResources.push( + helpers.fixEnums( + new Builder("mesos.Resource").setName("ports").setType(mesos.Value.Type.RANGES).setRanges( + new Builder("mesos.Value.Ranges") + .setRange(usedPortRanges) + ) + ) + ); + // Check if task is a container task, and if so, it the networking mode is BRIDGE and there are port mappings defined if (task.containerInfo) { @@ -249,7 +256,7 @@ module.exports = { var portIndex = 0; // Create environment variables for the used ports (schema is "PORT" appended by port index) usedPorts.forEach(function (port) { - envVars.push(new mesos.Environment.Variable("PORT" + portIndex, port.toString())); + envVars.push(new Builder("mesos.Environment.Variable").setName("PORT" + portIndex).setValue(port.toString())); portIndex++; }); @@ -260,12 +267,12 @@ module.exports = { // Add HOST - envVars.push(new mesos.Environment.Variable("HOST", offer.url.address.ip)); + envVars.push(new Builder("mesos.Environment.Variable").setName("HOST").setValue(offer.url.address.ip)); // Add env var for serial task number if (self.options.serialNumberedTasks) { var taskNameArray = task.name.split("-"); - envVars.push(new mesos.Environment.Variable("TASK_" + taskNameArray[0].toUpperCase() + "_SERIAL_NUMBER", taskNameArray[1])); + envVars.push(new Builder("mesos.Environment.Variable").setName("TASK_" + taskNameArray[0].toUpperCase() + "_SERIAL_NUMBER").setValue(taskNameArray[1])); } if (neededPorts > 0 || neededStaticPorts > 0) { @@ -316,10 +323,10 @@ module.exports = { .setTaskId(new mesos.TaskID(taskId)) .setAgentId(offer.agent_id) .setResources(demandedResources) - .setExecutor((task.executorInfo ? helpers.stringifyEnumsRecursive(task.executorInfo) : null)) - .setCommand((task.commandInfo ? helpers.stringifyEnumsRecursive(task.commandInfo) : null)) - .setContainer((task.containerInfo ? helpers.stringifyEnumsRecursive(task.containerInfo) : null)) - .setHealthCheck((task.mesosHealthCheck ? helpers.stringifyEnumsRecursive(task.mesosHealthCheck) : null)) + .setExecutor((task.executorInfo ? helpers.fixEnums(task.executorInfo) : null)) + .setCommand((task.commandInfo ? helpers.fixEnums(task.commandInfo) : null)) + .setContainer((task.containerInfo ? helpers.fixEnums(task.containerInfo) : null)) + .setHealthCheck((task.mesosHealthCheck ? helpers.fixEnums(task.mesosHealthCheck) : null)) .setLabels((task.labels ? task.labels : null)) ); @@ -378,14 +385,11 @@ module.exports = { process.nextTick(function () { // Set the Operations object - var Operations = helpers.stringifyEnumsRecursive( - new mesos.Offer.Operation( - mesos.Offer.Operation.Type.LAUNCH, - new mesos.Offer.Operation.Launch(toLaunch) - ) - ); + var Operations = new Builder("mesos.Offer.Operation") + .setType(mesos.Offer.Operation.Type.LAUNCH) + .setLaunch(new mesos.Offer.Operation.Launch(toLaunch)); - self.logger.debug("Operation before accept: " + JSON.stringify(helpers.stringifyEnumsRecursive(Operations))); + self.logger.debug("Operation before accept: " + JSON.stringify(helpers.fixEnums(Operations))); // Trigger acceptance self.accept([offer.id], Operations, null); @@ -540,13 +544,13 @@ module.exports = { } } // TODO: Check! - if (!match && index >= self.launchedTasks.length && status.reason == "REASON_RECONCILIATION") { + if (!match && index >= self.launchedTasks.length && status.reason === "REASON_RECONCILIATION") { // Cleaning up unknown tasks - if (self.options.killUnknownTasks && status.state == "TASK_RUNNING") { + if (self.options.killUnknownTasks && status.state === "TASK_RUNNING") { self.logger.info("Killing unknown task ID: " + status.task_id.value + " on agent: " + status.agent_id.value); self.kill(status.task_id.value, status.agent_id.value); // Cleaning up stale tasks from ZK. - } else if (status.state != "TASK_RUNNING" && self.options.useZk) { + } else if (status.state !== "TASK_RUNNING" && self.options.useZk) { self.logger.info("Cleaning up an unknown task from ZK: " + status.task_id.value); self.taskHelper.deleteTask(status.task_id.value); } diff --git a/tests/helpers.test.js b/tests/helpers.test.js index 45a8e8d..64e9979 100644 --- a/tests/helpers.test.js +++ b/tests/helpers.test.js @@ -1,5 +1,9 @@ -var helpers = require("../lib/helpers"); -var mesos = require("../lib/mesos")().getMesos(); +"use strict"; + +var lib = require("requirefrom")("lib"); +var helpers = lib("helpers"); +var mesos = lib("mesos")().getMesos(); +var Builder = lib("builder"); var winston = require("winston"); var http = require("http"); @@ -121,7 +125,7 @@ describe("helpers", function() { null // Volume Driver ) ); - var enumerated = helpers.stringifyEnumsRecursive(ContainerInfo); + var enumerated = helpers.fixEnums(ContainerInfo); expect(enumerated.type).to.equal("DOCKER"); expect(enumerated.docker.network).to.equal("HOST"); }); @@ -146,7 +150,7 @@ describe("helpers", function() { console.log(JSON.stringify(ContainerInfo)); var ContainerInfoClone = helpers.cloneDeep(ContainerInfo); console.log(JSON.stringify(ContainerInfoClone)); - var enumerated = helpers.stringifyEnumsRecursive(ContainerInfoClone); + var enumerated = helpers.fixEnums(ContainerInfoClone); console.log(JSON.stringify(enumerated)); console.log(JSON.stringify(ContainerInfoClone)); expect(enumerated.type).to.equal("DOCKER"); @@ -180,19 +184,19 @@ describe("helpers", function() { null, // ExecutorInfo null, // CommandInfo ContainerInfo, // ContainerInfo - new mesos.HealthCheck(null, null, null, null, null, mesos.HealthCheck.Type.HTTP, null, new mesos.HealthCheck.HTTPCheckInfo("http", 80, "/health", [200])), // HealthCheck + new mesos.HealthCheck(null, null, null, null, null, mesos.HealthCheck.Type.HTTP, null, new mesos.HealthCheck.HTTPCheckInfo(mesos.NetworkInfo.Protocol.IPv4, "http", 80, "/health", [200])), // HealthCheck null, // KillPolicy null, // Data null, // Labels null // DiscoveryInfo )]; - var launchMessage = new mesos.Offer.Operation( - mesos.Offer.Operation.Type.LAUNCH, - new mesos.Offer.Operation.Launch(taskInfos) - ); + var launchMessage = new Builder("mesos.Offer.Operation") + .setType(mesos.Offer.Operation.Type.LAUNCH) + .setLaunch(new mesos.Offer.Operation.Launch(taskInfos)); + console.log(JSON.stringify(launchMessage)); - var enumerated = helpers.stringifyEnumsRecursive(launchMessage); + var enumerated = helpers.fixEnums(launchMessage); console.log(JSON.stringify(enumerated)); console.log(JSON.stringify(launchMessage)); expect(enumerated.launch.task_infos[0].container.type).to.equal("DOCKER"); diff --git a/tests/scheduler.test.js b/tests/scheduler.test.js index 59812aa..b006316 100644 --- a/tests/scheduler.test.js +++ b/tests/scheduler.test.js @@ -1,13 +1,17 @@ -// Project require -var Scheduler = require("../").Scheduler; -var helpers = require("../lib/helpers"); -var TaskHelper = require("../lib/taskHelper"); +"use strict"; + +// Global var http = require("http"); var util = require("util"); var EventEmitter = require("events").EventEmitter; -var winston = require("winston"); -var mesos = (require("../lib/mesos"))().getMesos(); -var schedulerHandlers = require("../lib/schedulerHandlers"); + +// Project require +var lib = require("requirefrom")("lib"); +var Scheduler = require("../index").Scheduler; +var helpers = lib("helpers"); +var TaskHelper = lib("taskHelper"); +var mesos = lib("mesos")().getMesos(); +var Builder = lib("builder"); // Lib require for stubs var zookeeper = require("node-zookeeper-client"); @@ -687,32 +691,31 @@ describe("Scheduler constructor", function() { var sent = false; var toLaunch = []; var demandedResources = [ - helpers.stringifyEnumsRecursive(new mesos.Resource("cpus", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(1))), - helpers.stringifyEnumsRecursive(new mesos.Resource("mem", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(128))) - ]; + helpers.fixEnums(new mesos.Resource(null, "cpus", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(1))), + helpers.fixEnums(new mesos.Resource(null, "mem", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(128))) + ]; scheduler.frameworkId = "123445547452563"; toLaunch.push( - new mesos.TaskInfo( - "312312", // Task name - new mesos.TaskID("23242"), // TaskID - {value:"321312"}, // AgentID - demandedResources, // Resources - null, // ExecutorInfo - null, // CommandInfo - null, // ContainerInfo - null, // HealthCheck - null, // KillPolicy - null, // Data - null, // Labels - null // DiscoveryInfo - ) - ); - var Operations = helpers.stringifyEnumsRecursive( - new mesos.Offer.Operation( - mesos.Offer.Operation.Type.LAUNCH, - new mesos.Offer.Operation.Launch(toLaunch) - ) - ); + new mesos.TaskInfo( + "312312", // Task name + new mesos.TaskID("23242"), // TaskID + {value:"321312"}, // AgentID + demandedResources, // Resources + null, // ExecutorInfo + null, // CommandInfo + null, // ContainerInfo + null, // HealthCheck + null, // KillPolicy + null, // Data + null, // Labels + null // DiscoveryInfo + ) + ); + + var Operations = new Builder("mesos.Offer.Operation") + .setType(mesos.Offer.Operation.Type.LAUNCH) + .setLaunch(new mesos.Offer.Operation.Launch(toLaunch)); + scheduler.on("ready", function() { scheduler.accept([{value:"12312312"}], Operations, null); }); @@ -738,32 +741,31 @@ describe("Scheduler constructor", function() { var sent = false; var toLaunch = []; var demandedResources = [ - helpers.stringifyEnumsRecursive(new mesos.Resource("cpus", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(1))), - helpers.stringifyEnumsRecursive(new mesos.Resource("mem", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(128))) - ]; + helpers.fixEnums(new mesos.Resource(null, "cpus", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(1))), + helpers.fixEnums(new mesos.Resource(null, "mem", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(128))) + ]; scheduler.frameworkId = "123445547452563"; toLaunch.push( - new mesos.TaskInfo( - "312312", // Task name - new mesos.TaskID("23242"), // TaskID - {value:"321312"}, // AgentID - demandedResources, // Resources - null, // ExecutorInfo - null, // CommandInfo - null, // ContainerInfo - null, // HealthCheck - null, // KillPolicy - null, // Data - null, // Labels - null // DiscoveryInfo - ) - ); - var Operations = helpers.stringifyEnumsRecursive( - new mesos.Offer.Operation( - mesos.Offer.Operation.Type.LAUNCH, - new mesos.Offer.Operation.Launch(toLaunch) - ) - ); + new mesos.TaskInfo( + "312312", // Task name + new mesos.TaskID("23242"), // TaskID + {value:"321312"}, // AgentID + demandedResources, // Resources + null, // ExecutorInfo + null, // CommandInfo + null, // ContainerInfo + null, // HealthCheck + null, // KillPolicy + null, // Data + null, // Labels + null // DiscoveryInfo + ) + ); + + var Operations = new Builder("mesos.Offer.Operation") + .setType(mesos.Offer.Operation.Type.LAUNCH) + .setLaunch(new mesos.Offer.Operation.Launch(toLaunch)); + scheduler.on("ready", function() { scheduler.accept([{value:"12312312"}], Operations, null); }); diff --git a/tests/schedulerHandlers.test.js b/tests/schedulerHandlers.test.js index e19b463..2dee997 100644 --- a/tests/schedulerHandlers.test.js +++ b/tests/schedulerHandlers.test.js @@ -1,17 +1,16 @@ "use strict"; +// Global +var util = require("util"); +var EventEmitter = require("events").EventEmitter; + // Project require var lib = require("requirefrom")("lib"); var handlers = lib("schedulerHandlers"); var helpers = lib("helpers"); var Builder = lib("builder"); var TaskHelper = lib("taskHelper"); -var winston = require("winston"); -var util = require("util"); -var EventEmitter = require("events").EventEmitter; -var path = require("path"); -var MesosLib = lib("mesos"); -var Mesos = new MesosLib().getMesos(); +var Mesos = lib("mesos")().getMesos(); // Testing require var expect = require("chai").expect; @@ -29,17 +28,6 @@ describe("Offers handlers tests", function () { var scheduler = new SchedulerStub(); - var Url = { - "scheme": "http", - "address": { - "hostname": "bla.mesos", - "ip": "127.0.0.1", - "port": "2121" - }, - "path": "/bla", - "fragment": "" - }; - var offers; var ContainerInfo = new Mesos.ContainerInfo( @@ -65,15 +53,14 @@ describe("Offers handlers tests", function () { var task1; beforeEach(function () { + task1 = { "name": "My Task-121", "task_id": {"value": "12220-3440-12532-my-task"}, "containerInfo": ContainerInfo, "commandInfo": new Mesos.CommandInfo( null, // URI - new Mesos.Environment([ - new Mesos.Environment.Variable("FOO", "BAR") - ]), // Environment + new Mesos.Environment([new Builder("mesos.Environment.Variable").setName("FOO").setValue("BAR")]), // Environment false, // Is shell? null, // Command null, // Arguments @@ -89,60 +76,36 @@ describe("Offers handlers tests", function () { "disk": 10 } }; - offers = { - "type": "OFFERS", - "offers": [ - { - "id": {"value": "12214-23523-O235235"}, - "framework_id": {"value": "12124-235325-32425"}, - "agent_id": {"value": "12325-23523-S23523"}, - "hostname": "agent.host", - "url": Url, - "resources": [ - { - "name": "cpus", - "type": "SCALAR", - "scalar": {"value": 1.1}, - "role": "*" - }, - { - "name": "mem", - "role": "*", - "type": "SCALAR", - "scalar": {"value": 256} - }, - { - "name": "disk", - "type": "SCALAR", - "scalar": { - "value": 10000 - } - }, - { - "name": "ports", - "role": "*", - "type": "RANGES", - "ranges": { - "range": [ - { - "begin": 7000, - "end": 7009 - }, - { - "begin": 8080, - "end": 8090 - }, - { - "begin": 9000, - "end": 9019 - } - ] - } - } - ] - } - ] - }; + offers = helpers.fixEnums(new Builder("mesos.scheduler.Event.Offers") + .setOffers(new Builder("mesos.Offer") + .setId(new Mesos.OfferID("12214-23523-O235235")) + .setFrameworkId(new Mesos.FrameworkID("12124-235325-32425")) + .setAgentId(new Mesos.AgentID("12325-23523-S23523")) + .setHostname("agent.host") + .setUrl(new Builder("mesos.URL") + .setScheme("http") + .setAddress(new Builder("mesos.Address") + .setHostname("bla.mesos") + .setIp("127.0.0.1") + .setPort(2121) + ).setPath("/bla") + ) + .setResources([ + new Builder("mesos.Resource").setName("cpus").setType(Mesos.Value.Type.SCALAR).setScalar(new Mesos.Value.Scalar(1.1)), + new Builder("mesos.Resource").setName("mem").setType(Mesos.Value.Type.SCALAR).setScalar(new Mesos.Value.Scalar(256)), + new Builder("mesos.Resource").setName("disk").setType(Mesos.Value.Type.SCALAR).setScalar(new Mesos.Value.Scalar(10000)), + new Builder("mesos.Resource").setName("ports").setType(Mesos.Value.Type.RANGES).setRanges( + new Builder("mesos.Value.Ranges") + .setRange([ + new Mesos.Value.Range(7000, 7009), + new Mesos.Value.Range(8080, 8090), + new Mesos.Value.Range(9000, 9019) + ]) + ) + ]) + ) + ); + }); util.inherits(SchedulerStub, EventEmitter); @@ -199,12 +162,7 @@ describe("Offers handlers tests", function () { var logger = helpers.getLogger(null, null, "debug"); - var httpHealthCheck = new Builder("mesos.HealthCheck.HTTPCheckInfo").setScheme("http").setPort(80).setPath("/health").setStatuses([200]); - var healthCheck = new Builder("mesos.HealthCheck") - .setHttp(httpHealthCheck); - // .setType(Mesos.HealthCheck.Type.HTTP) - task1.healthCheck = healthCheck; - //task1.healthCheck = helpers.stringifyEnumsRecursive(new Mesos.HealthCheck(null, null, null, null, null, Mesos.HealthCheck.Type.HTTP, null, new Mesos.HealthCheck.HTTPCheckInfo("http", 80, "/health", [200]))); + task1.healthCheck = new Builder("mesos.HealthCheck").setHttp(new Builder("mesos.HealthCheck.HTTPCheckInfo").setScheme("http").setPort(80).setPath("/health").setStatuses([200])); scheduler.logger.info(JSON.stringify(task1)); scheduler.pendingTasks = [task1]; scheduler.launchedTasks = []; @@ -233,7 +191,9 @@ describe("Offers handlers tests", function () { scheduler.logger = logger; scheduler.frameworkId = "12124-235325-32425"; scheduler.options = {"frameworkName": "myfmw", "serialNumberedTasks": true}; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(false); expect(scheduler.launchedTasks.length).to.equal(0); @@ -262,7 +222,9 @@ describe("Offers handlers tests", function () { saved = true; }; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(true); expect(saved).to.be.true; @@ -278,7 +240,7 @@ describe("Offers handlers tests", function () { var logger = helpers.getLogger(null, null, "debug"); scheduler.pendingTasks = [task1]; - task1.healthCheck = new Mesos.HealthCheck(null, null, null, null, null, Mesos.HealthCheck.Type.HTTP, null, new Mesos.HealthCheck.HTTPCheckInfo("http", 80, "/health", [200])); + task1.healthCheck = new Builder("mesos.HealthCheck").setHttp(new Builder("mesos.HealthCheck.HTTPCheckInfo").setScheme("http").setPort(80).setPath("/health").setStatuses([200])); scheduler.launchedTasks = []; scheduler.logger = logger; scheduler.frameworkId = "12124-235325-32425"; @@ -290,7 +252,9 @@ describe("Offers handlers tests", function () { saved = true; }; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(true); expect(saved).to.be.true; @@ -314,7 +278,9 @@ describe("Offers handlers tests", function () { scheduler.frameworkId = "12124-235325-32425"; scheduler.options = {"frameworkName": "myfmw", "serialNumberedTasks": true}; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(true); expect(scheduler.launchedTasks.length).to.equal(1); @@ -337,7 +303,9 @@ describe("Offers handlers tests", function () { scheduler.frameworkId = "12124-235325-32425"; scheduler.options = {"frameworkName": "myfmw", "serialNumberedTasks": true}; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(true); expect(scheduler.launchedTasks.length).to.equal(1); @@ -359,7 +327,9 @@ describe("Offers handlers tests", function () { scheduler.frameworkId = "12124-235325-32425"; scheduler.options = {"frameworkName": "myfmw", "serialNumberedTasks": true}; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(true); expect(scheduler.launchedTasks.length).to.equal(1); @@ -383,7 +353,9 @@ describe("Offers handlers tests", function () { scheduler.frameworkId = "12124-235325-32425"; scheduler.options = {"frameworkName": "myfmw", "serialNumberedTasks": true}; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(false); expect(scheduler.launchedTasks.length).to.equal(0); @@ -402,7 +374,9 @@ describe("Offers handlers tests", function () { scheduler.frameworkId = "12124-235325-32425"; scheduler.options = {"frameworkName": "myfmw", "serialNumberedTasks": true}; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(true); expect(scheduler.launchedTasks.length).to.equal(1); @@ -426,7 +400,9 @@ describe("Offers handlers tests", function () { scheduler.frameworkId = "12124-235325-32425"; scheduler.options = {"frameworkName": "myfmw", "serialNumberedTasks": true}; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(true); expect(scheduler.launchedTasks.length).to.equal(1); @@ -444,22 +420,23 @@ describe("Offers handlers tests", function () { task1.resources.staticPorts = [8080,9001]; task1.commandInfo.environment = []; offers.offers[0].resources[4] = { - "name": "portsa", - "role": "*", - "type": "RANGES", - "ranges": { - "range": [ - { - "begin": 8080, - "end": 8090 - }, - { - "begin": 9000, - "end": 9019 - } - ] - } - }; + "provider_id": { value: null }, + "name": "portsa", + "role": "*", + "type": "RANGES", + "ranges": { + "range": [ + { + "begin": 8080, + "end": 8090 + }, + { + "begin": 9000, + "end": 9019 + } + ] + } + }; var logger = helpers.getLogger(null, null, "debug"); scheduler.pendingTasks = [task1]; @@ -468,7 +445,9 @@ describe("Offers handlers tests", function () { scheduler.frameworkId = "12124-235325-32425"; scheduler.options = {"frameworkName": "myfmw", "serialNumberedTasks": true}; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(true); expect(scheduler.launchedTasks.length).to.equal(1); @@ -494,7 +473,9 @@ describe("Offers handlers tests", function () { scheduler.frameworkId = "12124-235325-32425"; scheduler.options = {"frameworkName": "myfmw", "serialNumberedTasks": true}; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(true); expect(scheduler.launchedTasks.length).to.equal(1); @@ -522,7 +503,9 @@ describe("Offers handlers tests", function () { scheduler.frameworkId = "12124-235325-32425"; scheduler.options = {"frameworkName": "myfmw", "serialNumberedTasks": true}; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(true); expect(scheduler.launchedTasks.length).to.equal(1); @@ -542,7 +525,9 @@ describe("Offers handlers tests", function () { scheduler.frameworkId = "12124-235325-32425"; scheduler.options = {"frameworkName": "myfmw", "serialNumberedTasks": false}; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(false); expect(scheduler.launchedTasks.length).to.equal(0); @@ -563,7 +548,9 @@ describe("Offers handlers tests", function () { scheduler.frameworkId = "12124-235325-32425"; scheduler.options = {"frameworkName": "myfmw", "serialNumberedTasks": false}; scheduler.options.staticPorts = true; + handlers["OFFERS"].call(scheduler, offers); + setTimeout(function () { expect(accept).to.equal(false); expect(scheduler.launchedTasks.length).to.equal(0); @@ -574,8 +561,7 @@ describe("Offers handlers tests", function () { it("Receive an offer while suitable task with runtimeInfo is pending", function (done) { - var runtimeInfo = {agentId: "12345"}; - task1.runtimeInfo = runtimeInfo; + task1.runtimeInfo = {agentId: "12345"}; var logger = helpers.getLogger(null, null, "debug"); @@ -638,7 +624,7 @@ describe("Update handlers tests", function () { beforeEach(function () { acknowleged = false; killed = false; - runtimeInfo = {agentId: "12345", executorId: "5457"} + runtimeInfo = {agentId: "12345", executorId: "5457"}; task1 = { "name": "my-task", "taskId": "12344-my-task", @@ -646,14 +632,14 @@ describe("Update handlers tests", function () { "commandInfo": new Mesos.CommandInfo( null, // URI new Mesos.Environment([ - new Mesos.Environment.Variable("FOO", "BAR"), - new Mesos.Environment.Variable("PORT5053252", "BAR"), - new Mesos.Environment.Variable("PORT5", "BAR"), - new Mesos.Environment.Variable("PORT5HAFDSA", "BAR"), - new Mesos.Environment.Variable("1PORT3", "BAR"), - new Mesos.Environment.Variable("0HOST", "BAR"), - new Mesos.Environment.Variable("HOST1", "BAR"), - new Mesos.Environment.Variable("HOST", "BAR") // 3 Variables need to be removed when restarting a task, 5 should be left + new Builder("mesos.Environment.Variable").setName("FOO1").setValue("BAR"), + new Builder("mesos.Environment.Variable").setName("FOO2").setValue("BAR"), + new Builder("mesos.Environment.Variable").setName("FOO3").setValue("BAR"), + new Builder("mesos.Environment.Variable").setName("FOO4").setValue("BAR"), + new Builder("mesos.Environment.Variable").setName("FOO5").setValue("BAR"), + new Builder("mesos.Environment.Variable").setName("FOO6").setValue("BAR"), + new Builder("mesos.Environment.Variable").setName("FOO7").setValue("BAR"), + new Builder("mesos.Environment.Variable").setName("FOO8").setValue("BAR") // 3 Variables need to be removed when restarting a task, 5 should be left ]), // Environment false, // Is shell? null, // Command @@ -713,6 +699,7 @@ describe("Update handlers tests", function () { }; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(acknowleged).to.equal(false); done(); @@ -745,6 +732,7 @@ describe("Update handlers tests", function () { }; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(acknowleged).to.equal(true); done(); @@ -768,8 +756,7 @@ describe("Update handlers tests", function () { } }; - var taskHelper = sinon.createStubInstance(TaskHelper); - scheduler.taskHelper = taskHelper; + scheduler.taskHelper = sinon.createStubInstance(TaskHelper); scheduler.pendingTasks = []; scheduler.launchedTasks = [task1]; scheduler.logger = logger; @@ -782,6 +769,7 @@ describe("Update handlers tests", function () { scheduler.options.useZk = false; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(scheduler.launchedTasks.length).to.equal(0); done(); @@ -805,8 +793,7 @@ describe("Update handlers tests", function () { } }; - var taskHelper = sinon.createStubInstance(TaskHelper); - scheduler.taskHelper = taskHelper; + scheduler.taskHelper = sinon.createStubInstance(TaskHelper); scheduler.pendingTasks = []; scheduler.launchedTasks = [task1]; scheduler.logger = logger; @@ -819,6 +806,7 @@ describe("Update handlers tests", function () { scheduler.options.useZk = true; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(scheduler.launchedTasks.length).to.equal(0); done(); @@ -850,9 +838,10 @@ describe("Update handlers tests", function () { }; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(scheduler.pendingTasks.length).to.equal(1); - expect(scheduler.pendingTasks[0].commandInfo.environment.variables).to.have.lengthOf(5); + expect(scheduler.pendingTasks[0].commandInfo.environment.variables).to.have.lengthOf(8); done(); }, 100); //timeout with an error in one second @@ -891,6 +880,7 @@ describe("Update handlers tests", function () { }; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(scheduler.pendingTasks.length).to.equal(1); expect(deleted).to.be.true; @@ -934,6 +924,7 @@ describe("Update handlers tests", function () { task1.runtimeInfo.restarting = true; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(scheduler.pendingTasks.length).to.equal(0); expect(deleted).to.be.true; @@ -971,6 +962,7 @@ describe("Update handlers tests", function () { task1.runtimeInfo.restarting = true; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(scheduler.pendingTasks.length).to.equal(0); expect(deleted).to.be.false; @@ -1005,6 +997,7 @@ describe("Update handlers tests", function () { }; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(scheduler.launchedTasks[0].runtimeInfo.state).to.equal("TASK_FAILED"); done(); @@ -1047,6 +1040,7 @@ describe("Update handlers tests", function () { }; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(saved).to.be.true; expect(scheduler.launchedTasks[0].runtimeInfo.state).to.equal("TASK_RUNNING"); @@ -1092,6 +1086,7 @@ describe("Update handlers tests", function () { }; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(saved).to.be.true; expect(scheduler.launchedTasks[0].runtimeInfo.state).to.equal("TASK_RUNNING"); @@ -1136,6 +1131,7 @@ describe("Update handlers tests", function () { }; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(saved).to.be.true; expect(scheduler.launchedTasks[0].runtimeInfo.state).to.equal("TASK_RUNNING"); @@ -1174,6 +1170,7 @@ describe("Update handlers tests", function () { scheduler.options.killUnknownTasks = false; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(killed).to.equal(false); done(); @@ -1218,6 +1215,7 @@ describe("Update handlers tests", function () { scheduler.options.killUnknownTasks = false; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(killed).to.equal(false); expect(deleted).to.be.true; @@ -1255,6 +1253,7 @@ describe("Update handlers tests", function () { scheduler.options.killUnknownTasks = true; handlers["UPDATE"].call(scheduler, update); + setTimeout(function () { expect(killed).to.equal(true); done(); diff --git a/tests/taskHealthHelper.test.js b/tests/taskHealthHelper.test.js index 5e3e3ed..35e6886 100644 --- a/tests/taskHealthHelper.test.js +++ b/tests/taskHealthHelper.test.js @@ -9,7 +9,7 @@ node: true "use strict"; const fs = require("fs"); -var Scheduler = require("../").Scheduler; +var Scheduler = require("../index").Scheduler; var http = require("http"); var TaskHealthHelper = require("../lib/taskHealthHelper"); diff --git a/tests/taskHelper.test.js b/tests/taskHelper.test.js index bc995ca..72f7be1 100644 --- a/tests/taskHelper.test.js +++ b/tests/taskHelper.test.js @@ -1,14 +1,16 @@ "use strict"; -// Project require -var Scheduler = require("../").Scheduler; -var helpers = require("../lib/helpers"); -var TaskHelper = require("../lib/taskHelper"); -var winston = require("winston"); +// Global var util = require("util"); var EventEmitter = require("events").EventEmitter; -var path = require("path"); -var Mesos = require("../lib/mesos")().getMesos(); + +// Project require +var lib = require("requirefrom")("lib"); +var Scheduler = require("../index").Scheduler; +var helpers = lib("helpers"); +var TaskHelper = lib("taskHelper"); +var Builder = lib("builder"); +var Mesos = lib("mesos")().getMesos(); // Lib require for stubs var zookeeper = require("node-zookeeper-client"); @@ -37,7 +39,7 @@ describe("Load tasks from Zk:", function () { // Inherit from EventEmitter EventEmitter.call(this); return this; - }; + } util.inherits(SchedulerStub, EventEmitter); @@ -250,9 +252,9 @@ describe("Load tasks from Zk:", function () { "commandInfo": new Mesos.CommandInfo( null, // URI new Mesos.Environment([ - new Mesos.Environment.Variable("FOO", "BAR"), - new Mesos.Environment.Variable("HOST", "214214.1244.412421"), - new Mesos.Environment.Variable("PORT0", "3232") + new Builder("mesos.Environment.Variable").setName("FOO").setValue("BAR"), + new Builder("mesos.Environment.Variable").setName("HOST").setValue("214214.1244.412421"), + new Builder("mesos.Environment.Variable").setName("PORT0").setValue("3232") ]), // Environment false, // Is shell? null, // Command @@ -264,9 +266,9 @@ describe("Load tasks from Zk:", function () { "commandInfo": new Mesos.CommandInfo( null, // URI new Mesos.Environment([ - new Mesos.Environment.Variable("FOO", "BAR"), - new Mesos.Environment.Variable("HOST", "214214.1244.412421"), - new Mesos.Environment.Variable("PORT0", "3232") + new Builder("mesos.Environment.Variable").setName("FOO").setValue("BAR"), + new Builder("mesos.Environment.Variable").setName("HOST").setValue("214214.1244.412421"), + new Builder("mesos.Environment.Variable").setName("PORT0").setValue("3232") ]), // Environment false, // Is shell? null, // Command @@ -350,9 +352,9 @@ describe("Load tasks from Zk:", function () { "commandInfo": new Mesos.CommandInfo( null, // URI new Mesos.Environment([ - new Mesos.Environment.Variable("FOO", "BAR"), - new Mesos.Environment.Variable("HOST", "214214.1244.412421"), - new Mesos.Environment.Variable("PORT0", "3232") + new Builder("mesos.Environment.Variable").setName("FOO").setValue("BAR"), + new Builder("mesos.Environment.Variable").setName("HOST").setValue("214214.1244.412421"), + new Builder("mesos.Environment.Variable").setName("PORT0").setValue("3232") ]), // Environment false, // Is shell? null, // Command @@ -364,9 +366,9 @@ describe("Load tasks from Zk:", function () { "commandInfo": new Mesos.CommandInfo( null, // URI new Mesos.Environment([ - new Mesos.Environment.Variable("FOO", "BAR"), - new Mesos.Environment.Variable("HOST", "214214.1244.412421"), - new Mesos.Environment.Variable("PORT0", "3232") + new Builder("mesos.Environment.Variable").setName("FOO").setValue("BAR"), + new Builder("mesos.Environment.Variable").setName("HOST").setValue("214214.1244.412421"), + new Builder("mesos.Environment.Variable").setName("PORT0").setValue("3232") ]), // Environment false, // Is shell? null, // Command From b533a0a20d1ddef335ed8c6c341e7108e8c9edad Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sun, 4 Mar 2018 17:20:33 +0100 Subject: [PATCH 08/13] Update docs & coverage reports --- docs/Builder.html | 4 +- docs/Executor.html | 4 +- docs/Mesos.html | 4 +- docs/Scheduler.html | 434 ++- docs/TaskHealthHelper.html | 4 +- docs/TaskHelper.html | 12 +- docs/builder.js.html | 4 +- docs/coverage/base.css | 212 ++ docs/coverage/index.html | 106 + docs/coverage/mesos-framework/index.html | 93 + docs/coverage/mesos-framework/index.js.html | 89 + .../mesos-framework/lib/builder.js.html | 137 + .../mesos-framework/lib/executor.js.html | 914 +++++ .../lib/executorHandlers.js.html | 140 + .../mesos-framework/lib/helpers.js.html | 572 +++ docs/coverage/mesos-framework/lib/index.html | 197 + .../mesos-framework/lib/mesos.js.html | 239 ++ .../mesos-framework/lib/scheduler.js.html | 3386 +++++++++++++++++ .../lib/schedulerHandlers.js.html | 1823 +++++++++ .../lib/taskHealthHelper.js.html | 560 +++ .../mesos-framework/lib/taskHelper.js.html | 518 +++ docs/coverage/prettify.css | 1 + docs/coverage/prettify.js | 1 + docs/coverage/sort-arrow-sprite.png | Bin 0 -> 209 bytes docs/coverage/sorter.js | 158 + docs/executor.js.html | 4 +- docs/index.html | 66 +- docs/mesos.js.html | 4 +- docs/scheduler.js.html | 438 ++- docs/taskHealthHelper.js.html | 11 +- docs/taskHelper.js.html | 19 +- 31 files changed, 9859 insertions(+), 295 deletions(-) create mode 100644 docs/coverage/base.css create mode 100644 docs/coverage/index.html create mode 100644 docs/coverage/mesos-framework/index.html create mode 100644 docs/coverage/mesos-framework/index.js.html create mode 100644 docs/coverage/mesos-framework/lib/builder.js.html create mode 100644 docs/coverage/mesos-framework/lib/executor.js.html create mode 100644 docs/coverage/mesos-framework/lib/executorHandlers.js.html create mode 100644 docs/coverage/mesos-framework/lib/helpers.js.html create mode 100644 docs/coverage/mesos-framework/lib/index.html create mode 100644 docs/coverage/mesos-framework/lib/mesos.js.html create mode 100644 docs/coverage/mesos-framework/lib/scheduler.js.html create mode 100644 docs/coverage/mesos-framework/lib/schedulerHandlers.js.html create mode 100644 docs/coverage/mesos-framework/lib/taskHealthHelper.js.html create mode 100644 docs/coverage/mesos-framework/lib/taskHelper.js.html create mode 100644 docs/coverage/prettify.css create mode 100644 docs/coverage/prettify.js create mode 100644 docs/coverage/sort-arrow-sprite.png create mode 100644 docs/coverage/sorter.js diff --git a/docs/Builder.html b/docs/Builder.html index da857f4..8577eeb 100644 --- a/docs/Builder.html +++ b/docs/Builder.html @@ -24,7 +24,7 @@
@@ -217,7 +217,7 @@
Parameters:

- Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/Executor.html b/docs/Executor.html index 91b2e28..593c523 100644 --- a/docs/Executor.html +++ b/docs/Executor.html @@ -24,7 +24,7 @@
@@ -575,7 +575,7 @@
Parameters:

- Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/Mesos.html b/docs/Mesos.html index 0732128..bbaacdc 100644 --- a/docs/Mesos.html +++ b/docs/Mesos.html @@ -24,7 +24,7 @@
@@ -682,7 +682,7 @@
Returns:

- Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/Scheduler.html b/docs/Scheduler.html index e11c000..dbad84e 100644 --- a/docs/Scheduler.html +++ b/docs/Scheduler.html @@ -24,7 +24,7 @@
@@ -99,7 +99,7 @@

new Schedule
Source:
@@ -209,7 +209,7 @@

Methods

-

accept(offers, taskInfos, filters)

+

accept(offersIds, operations, filters)

@@ -252,7 +252,7 @@

acceptSource:
@@ -296,7 +296,7 @@
Parameters:
- offers + offersIds @@ -313,7 +313,7 @@
Parameters:
-

The array of OfferIDs which should be accepted.

+

The array of OfferIDs which should be accepted.

@@ -322,7 +322,7 @@
Parameters:
- taskInfos + operations @@ -339,7 +339,7 @@
Parameters:
-

The array of Operation objects.

+

The array of Operation objects.

@@ -365,7 +365,7 @@
Parameters:
-

The Filters object.

+

The Filters object.

@@ -439,7 +439,7 @@

ac
Source:
@@ -500,7 +500,7 @@

Parameters:
-

The OfferID array which should be sent to the server.

+

The OfferID array which should be sent to the server.

@@ -526,7 +526,7 @@
Parameters:
-

The Filters object which should be sent to the server.

+

The Filters object which should be sent to the server.

@@ -600,7 +600,7 @@

acknowledg
Source:
@@ -685,6 +685,219 @@

Parameters:
+

+ + +
+ + + +

acknowledgeOperationStatus(agentId, resourceProviderId, operationId, uuid)

+ + + + + +
+

Acknowledges the receipt of an operation status update. Schedulers are responsible for explicitly acknowledging the receipt of updates which have the 'UpdateOperationStatus.status().uuid()' field set. Such status updates are retried by the agent or resource provider until they are acknowledged by the scheduler.

+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
agentId + + +string + + + + +

The AgentID the task is running on.

+ +
resourceProviderId + + +string + + + + +

The ResourceProviderId

+ +
operationId + + +string + + + + +

The OperationID

+ +
uuid + + +string + + + + +

The uuid of the Operation

+ +
+ + + + + + + + + + + + + + + +
@@ -735,7 +948,7 @@

backOffSource:
@@ -775,7 +988,7 @@

backOffdecline(offers, filters)

+

decline(offersIds, filters)

@@ -818,7 +1031,7 @@

declineSource:
@@ -862,7 +1075,7 @@
Parameters:
- offers + offersIds @@ -879,7 +1092,7 @@
Parameters:
-

The array of OfferIDs which should be declined.

+

The array of OfferIDs which should be declined.

@@ -905,7 +1118,7 @@
Parameters:
-

The Filters object.

+

The Filters object.

@@ -979,7 +1192,7 @@

d
Source:
@@ -1040,7 +1253,7 @@

Parameters:
-

The OfferID array which should be sent to the server.

+

The OfferID array which should be sent to the server.

@@ -1066,7 +1279,7 @@
Parameters:
-

The Filters object which should be sent to the server.

+

The Filters object which should be sent to the server.

@@ -1140,7 +1353,7 @@

getRun
Source:
@@ -1249,7 +1462,7 @@

killSource:
@@ -1310,7 +1523,7 @@
Parameters:
-

The TaskID to kill.

+

The TaskID to kill.

@@ -1336,7 +1549,7 @@
Parameters:
-

The AgentID the task is running on.

+

The AgentID the task is running on.

@@ -1410,7 +1623,7 @@

messageSource:
@@ -1471,7 +1684,7 @@
Parameters:
-

The AgentID the task is running on.

+

The AgentID the task is running on.

@@ -1497,7 +1710,7 @@
Parameters:
-

The ExecutorID which runs the task.

+

The ExecutorID which runs the task.

@@ -1598,7 +1811,7 @@

reconcileSource:
@@ -1659,7 +1872,7 @@
Parameters:
-

The TaskID to kill.

+

The TaskID to kill.

@@ -1685,7 +1898,142 @@
Parameters:
-

The AgentID the task is running on.

+

The AgentID the task is running on.

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

+ + +
+ + + +

reconcileOperations(operations)

+ + + + + +
+

Allows the scheduler to query the status of operations. This causes the master to send back the latest status for each operation in 'operations', if possible. If 'operations' is empty, then the master will send the latest status for each operation currently known.

+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1759,7 +2107,7 @@

requestSource:
@@ -1820,7 +2168,7 @@
Parameters:

@@ -1894,7 +2242,7 @@

reviveSource:
@@ -1978,7 +2326,7 @@

shutdownSource:
@@ -2039,7 +2387,7 @@
Parameters:

@@ -2065,7 +2413,7 @@
Parameters:
@@ -2139,7 +2487,7 @@

subscribeSource:
@@ -2283,7 +2631,7 @@
Parameters:

@@ -2357,7 +2705,7 @@

syncSource:
@@ -2441,7 +2789,7 @@

teardownSource:
@@ -2493,7 +2841,7 @@

teardown
- Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/TaskHealthHelper.html b/docs/TaskHealthHelper.html index 0d5201e..0ccdb7d 100644 --- a/docs/TaskHealthHelper.html +++ b/docs/TaskHealthHelper.html @@ -24,7 +24,7 @@
@@ -243,7 +243,7 @@
Parameters:

- Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/TaskHelper.html b/docs/TaskHelper.html index f749923..a82c4c3 100644 --- a/docs/TaskHelper.html +++ b/docs/TaskHelper.html @@ -24,7 +24,7 @@
@@ -99,7 +99,7 @@

new TaskHel
Source:
@@ -252,7 +252,7 @@

deleteTask<
Source:
@@ -387,7 +387,7 @@

loadTasksSource:
@@ -470,7 +470,7 @@

saveTaskSource:
@@ -574,7 +574,7 @@
Parameters:

- Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/builder.js.html b/docs/builder.js.html index bbed259..f9ea4c9 100644 --- a/docs/builder.js.html +++ b/docs/builder.js.html @@ -24,7 +24,7 @@
@@ -75,7 +75,7 @@

builder.js


- Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/coverage/base.css b/docs/coverage/base.css new file mode 100644 index 0000000..417c7ad --- /dev/null +++ b/docs/coverage/base.css @@ -0,0 +1,212 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } + + +.medium .chart { border:1px solid #666; } +.medium .cover-fill { background: #666; } + +.cbranch-no { background: yellow !important; color: #111; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } +.medium { background: #eaeaea; } + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/docs/coverage/index.html b/docs/coverage/index.html new file mode 100644 index 0000000..244b778 --- /dev/null +++ b/docs/coverage/index.html @@ -0,0 +1,106 @@ + + + + Code coverage report for All files + + + + + + + +
+
+

+ All files +

+
+
+ 87.67% + Statements + 903/1030 +
+
+ 85.26% + Branches + 538/631 +
+
+ 78.06% + Functions + 121/155 +
+
+ 87.67% + Lines + 903/1030 +
+
+
+
+
+

NameTypeDescription
operations + + +array + + + + +

An array of Operation objects to query.

-

The Request objects which should be sent to the server.

+

The Request objects which should be sent to the server.

-

The AgentID the task is running on.

+

The AgentID the task is running on.

-

The ExecutorID whcih runs the task.

+

The ExecutorID whcih runs the task.

-

The Role objects which should be sent to the server.

+

The Role objects which should be sent to the server.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
mesos-framework
100%6/6100%0/0100%0/0100%6/6
mesos-framework/lib
87.6%897/102485.26%538/63178.06%121/15587.6%897/1024
+
+
+ +
+ + + + + diff --git a/docs/coverage/mesos-framework/index.html b/docs/coverage/mesos-framework/index.html new file mode 100644 index 0000000..0fa20d7 --- /dev/null +++ b/docs/coverage/mesos-framework/index.html @@ -0,0 +1,93 @@ + + + + Code coverage report for mesos-framework + + + + + + + +
+
+

+ All files mesos-framework +

+
+
+ 100% + Statements + 6/6 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 0/0 +
+
+ 100% + Lines + 6/6 +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.js
100%6/6100%0/0100%0/0100%6/6
+
+
+ + + + + + + diff --git a/docs/coverage/mesos-framework/index.js.html b/docs/coverage/mesos-framework/index.js.html new file mode 100644 index 0000000..9a7ad2d --- /dev/null +++ b/docs/coverage/mesos-framework/index.js.html @@ -0,0 +1,89 @@ + + + + Code coverage report for mesos-framework/index.js + + + + + + + +
+
+

+ All files / mesos-framework index.js +

+
+
+ 100% + Statements + 6/6 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 0/0 +
+
+ 100% + Lines + 6/6 +
+
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9  +  +1x +1x +1x +1x +1x +1x + 
"use strict";
+ 
+module.exports.Scheduler = require("./lib/scheduler");
+module.exports.Executor = require("./lib/executor");
+module.exports.Mesos = require("./lib/mesos")();
+module.exports.TaskHealthHelper = require("./lib/taskHealthHelper");
+module.exports.helpers = require("./lib/helpers");
+module.exports.Builder = require("./lib/builder");
+ 
+
+
+ + + + + + + diff --git a/docs/coverage/mesos-framework/lib/builder.js.html b/docs/coverage/mesos-framework/lib/builder.js.html new file mode 100644 index 0000000..7e73d28 --- /dev/null +++ b/docs/coverage/mesos-framework/lib/builder.js.html @@ -0,0 +1,137 @@ + + + + Code coverage report for mesos-framework/lib/builder.js + + + + + + + +
+
+

+ All files / mesos-framework/lib builder.js +

+
+
+ 85.71% + Statements + 6/7 +
+
+ 50% + Branches + 1/2 +
+
+ 100% + Functions + 1/1 +
+
+ 85.71% + Lines + 6/7 +
+
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25  +  +1x +1x +  +  +1x +  +  +  +  +  +  +  +  +880x +  +  +880x +  +  +  +  +1x + 
"use strict";
+ 
+var path = require("path");
+var protoBuf = require("protobufjs");
+ 
+// Load Mesos protobuf definitions
+var builder = protoBuf.loadProtoFile(path.join(__dirname, "../", "proto/all.proto"));
+ 
+/**
+ * Represents a variable builder for protobuf to JavaScript instantiations.
+ * @constructor
+ * @param {string} messageType - The message type as string, e.g. `mesos.HealthCheck`.
+ */
+function Builder (messageType) {
+ 
+    Iif (!(this instanceof Builder)) {
+        return new Builder(messageType);
+    } else {
+        return new (builder.build(messageType))();
+    }
+ 
+}
+ 
+module.exports = Builder;
+ 
+
+
+ + + + + + + diff --git a/docs/coverage/mesos-framework/lib/executor.js.html b/docs/coverage/mesos-framework/lib/executor.js.html new file mode 100644 index 0000000..e42db72 --- /dev/null +++ b/docs/coverage/mesos-framework/lib/executor.js.html @@ -0,0 +1,914 @@ + + + + Code coverage report for mesos-framework/lib/executor.js + + + + + + + +
+
+

+ All files / mesos-framework/lib executor.js +

+
+
+ 12.37% + Statements + 12/97 +
+
+ 0% + Branches + 0/45 +
+
+ 0% + Functions + 0/13 +
+
+ 12.37% + Lines + 12/97 +
+
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284  +  +1x +1x +1x +1x +  +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x + 
"use strict";
+ 
+var http = require("http");
+var EventEmitter = require('events').EventEmitter;
+var util = require('util');
+var uuid = require('uuid');
+ 
+var helpers = require("./helpers");
+var executorHandlers = require("./executorHandlers");
+var mesos = require("./mesos")().getMesos();
+ 
+/**
+ * Represents a Mesos framework executor.
+ * @constructor
+ * @param {object} options - The option map object.
+ */
+function Executor (options) {
+ 
+    if (!(this instanceof Executor)) {
+        return new Executor(options);
+    }
+ 
+    // Inherit from EventEmitter
+    EventEmitter.call(this);
+ 
+    var self = this;
+    self.options = {};
+ 
+    // Optional env variables
+    var envMap = {
+        "MESOS_CHECKPOINT": "checkpointEnabled",
+        "MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD": "shutdownGracePeriod",
+        "MESOS_RECOVERY_TIMEOUT": "recoveryTimeout",
+        "MESOS_SUBSCRIPTION_BACKOFF_MAX": "subscriptionBackoffMax"
+    };
+ 
+    // Check for frameworkId
+    if (process.env.MESOS_FRAMEWORK_ID) {
+        self.frameworkId = new mesos.FrameworkID(process.env.MESOS_FRAMEWORK_ID);
+    } else {
+        console.error("No MESOS_FRAMEWORK_ID environment parameter found! Exiting...");
+        process.exit(1);
+    }
+ 
+    // Check fo rexecutorId
+    if (process.env.MESOS_EXECUTOR_ID) {
+        self.executorId = new mesos.ExecutorID(process.env.MESOS_EXECUTOR_ID);
+    } else {
+        console.error("No MESOS_EXECUTOR_ID environment parameter found! Exiting...");
+        process.exit(2);
+    }
+ 
+    // Check for working directory
+    if (process.env.MESOS_DIRECTORY) {
+        self.workingDirectory = process.env.MESOS_DIRECTORY;
+    } else {
+        console.error("No MESOS_DIRECTORY environment parameter found! Exiting...");
+        process.exit(3);
+    }
+ 
+    // Check for agent endpoint
+    if (process.env.MESOS_AGENT_ENDPOINT) {
+        var endpointArray = process.env.MESOS_AGENT_ENDPOINT.split(":");
+        if (endpointArray.length === 2) {
+            self.options.agentUrl = endpointArray[0];
+            self.options.port = parseInt(endpointArray[1]);
+        } else {
+            console.error("MESOS_AGENT_ENDPOINT didn't contain a ip:port combination! Exiting...");
+            process.exit(4);
+        }
+    } else {
+        console.log("No MESOS_AGENT_ENDPOINT environment parameter found! Using default values...");
+        self.options.agentUrl = options.agentUrl || "127.0.0.1";
+        self.options.port = parseInt(options.port) || 5051;
+    }
+ 
+    // Check for other env variables and inline them
+    Object.getOwnPropertyNames(envMap).forEach(function (envVariable) {
+        if (process.env[envVariable]) {
+            self[envMap[envVariable]] = process.env[envVariable];
+        }
+    });
+ 
+    // Template for issuing Mesos Scheduler HTTP API requests
+    self.requestTemplate = {
+        host: self.options.agentUrl,
+        port: self.options.port,
+        path: "/api/v1/executor",
+        method: "POST",
+        headers: {
+            'Content-Type': 'application/json'
+        }
+    };
+ 
+    // Customer event handlers will be registered here
+    self.customEventHandlers = {};
+ 
+    // List of allowed event handler function names and their argument length
+    var allowedEventHandlers = {
+        "SUBSCRIBED": 1,
+        "LAUNCH": 1,
+        "KILL": 1,
+        "ACKNOWLEDGED": 1,
+        "MESSAGE": 1,
+        "ERROR": 1,
+        "SHUTDOWN": 1
+    };
+ 
+    // Add custom event handlers if present
+    if (options.handlers && Object.getOwnPropertyNames(options.handlers).length > 0) {
+        Object.getOwnPropertyNames(options.handlers).forEach(function (handlerName) {
+            // Check if name is allowed, is a function and the length of the function arguments fit to the ones defined in allowedEventHandlers
+            if (Object.getOwnPropertyNames(allowedEventHandlers).indexOf(handlerName.toUpperCase()) > -1 && helpers.isFunction(options.handlers[handlerName]) && options.handlers[handlerName].length === allowedEventHandlers[handlerName]) {
+                self.customEventHandlers[handlerName.toUpperCase()] = options.handlers[handlerName];
+            }
+        });
+    }
+ 
+}
+ 
+// Inhertit from EventEmitter
+util.inherits(Executor, EventEmitter);
+ 
+/**
+ * Subscribes the framework executor to the according Mesos agent.
+ */
+Executor.prototype.subscribe = function () {
+ 
+    var self = this;
+ 
+    /**
+     * The handler funciton for the incoming Mesos agent events for this executor.
+     * @param {object} eventData - The data object for an incoming event. Contains the event details (type etc.).
+     */
+    function handleEvent (eventData) {
+ 
+        try {
+ 
+            var event = JSON.parse(eventData);
+ 
+            // Determine event handler, use custom one if it exists
+            if (self.customEventHandlers[event.type]) {
+                // Call custom handler
+                self.customEventHandlers[event.type].call(self, event[event.type.toLocaleLowerCase()]);
+            } else {
+                // Call default handler
+                schedulerHandlers[event.type].call(self, event[event.type.toLocaleLowerCase()]);
+            }
+ 
+            // Emit original objects
+            self.emit(event.type.toLocaleLowerCase(), event[event.type.toLocaleLowerCase()]);
+ 
+        } catch (error) {
+            self.emit("error", { message: "Couldn't parse as JSON: " + eventData, stack: (error.stack || "") });
+        }
+ 
+    }
+ 
+    var req = http.request(self.requestTemplate, function (res) {
+ 
+        // Set encoding to UTF8
+        res.setEncoding('utf8');
+ 
+        if (res.statusCode === 200) {
+            self.emit("sent_subscribe", { mesosStreamId: self.mesosStreamId });
+ 
+        }
+ 
+        // Local cache for chunked JSON messages
+        var cache = "";
+ 
+        // Watch for data/chunks
+        res.on('data', function (chunk) {
+ 
+            console.log("BODY: " + chunk);
+ 
+            var expectedLength = 0;
+ 
+            if (chunk.indexOf("\n") > -1) {
+                var temp = chunk.split("\n");
+                if (temp.length === 2) {
+                    expectedLength = parseInt(temp[0]);
+                    if (temp[1].length < expectedLength) {
+                        // Add to cache
+                        cache += temp[1];
+                    } else {
+                        // Empty cache
+                        cache = "";
+                        // Handle event
+                        handleEvent(temp[1]);
+                    }
+                } else {
+                    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, replace the erroneous parts
+                    var eventData = cache + chunk;
+                    // Handle event
+                    handleEvent(eventData);
+                    // Empty cache
+                    cache = "";
+                }
+            }
+        });
+ 
+        res.on('end', function () {
+            self.emit("error", { message: "Long-running connection was closed!" });
+        });
+ 
+    });
+ 
+    req.on('error', function (e) {
+        self.emit("error", { message: "There was a problem with the request: " + e.message});
+    });
+ 
+    // write data to request body
+    req.write(JSON.stringify({
+        "type": "SUBSCRIBE",
+        "framework_id": self.frameworkId,
+        "executor_id": self.executorId
+    }));
+ 
+    req.end();
+ 
+};
+ 
+/**
+ *  Communicate the state of managed tasks. It is crucial that a terminal update (e.g., TASK_FINISHED, TASK_KILLED or TASK_FAILED) is sent to the agent as soon as the task terminates, in order to allow Mesos to release the resources allocated to the task.
+ *  The scheduler must explicitly respond to this call through an ACKNOWLEDGE message (see ACKNOWLEDGED in the Events section below for the semantics). The executor must maintain a list of unacknowledged updates. If for some reason, the executor is disconnected from the agent, these updates must be sent as part of SUBSCRIBE request in the unacknowledged_updates field.
+ *  @param {Object} taskStatus The {@link https://github.com/apache/mesos/blob/c6e9ce16850f69fda719d4e32be3f2a2e1d80387/include/mesos/v1/mesos.proto#L1330|TaskStatus} object containing the update details.
+ */
+Executor.prototype.update = function (taskStatus) {
+ 
+    var self = this;
+ 
+    var payload = {
+        "type": "UPDATE",
+        "framework_id": self.frameworkId,
+        "executor_id": self.executorId,
+        "update": {
+            "status": taskStatus
+        }
+    };
+ 
+    helpers.doRequest.call(self, payload, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_update");
+        }
+    });
+    
+};
+ 
+/**
+ * Send arbitrary data to the scheduler. Note that Mesos neither interprets this data nor makes any guarantees about the delivery of this message to the executor.
+ * @param {string} data The string which's raw bytes will be encoded in Base64.
+ */
+Executor.prototype.message = function (data) {
+ 
+    var self = this;
+ 
+    var payload = {
+        "type": "MESSAGE",
+        "framework_id": self.frameworkId,
+        "executor_id": self.executorId,
+        "message": {
+            "data": new Buffer(data).toString('base64')
+        }
+    };
+ 
+    helpers.doRequest.call(self, payload, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_message");
+        }
+    });
+ 
+};
+ 
+module.exports = Executor;
+ 
+
+
+ + + + + + + diff --git a/docs/coverage/mesos-framework/lib/executorHandlers.js.html b/docs/coverage/mesos-framework/lib/executorHandlers.js.html new file mode 100644 index 0000000..338e4a5 --- /dev/null +++ b/docs/coverage/mesos-framework/lib/executorHandlers.js.html @@ -0,0 +1,140 @@ + + + + Code coverage report for mesos-framework/lib/executorHandlers.js + + + + + + + +
+
+

+ All files / mesos-framework/lib executorHandlers.js +

+
+
+ 100% + Statements + 6/6 +
+
+ 100% + Branches + 0/0 +
+
+ 0% + Functions + 0/7 +
+
+ 100% + Lines + 6/6 +
+
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26  +1x +  +1x +1x +  +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
"use strict";
+var uuid = require('uuid');
+ 
+var helpers = require("./helpers");
+var Mesos = new (require("./mesos"))();
+ 
+var mesos = Mesos.getMesos();
+var builder = Mesos.getBuilder();
+ 
+module.exports = {
+    "SUBSCRIBED": function (subscribed) {
+    },
+    "LAUNCH": function (launched) {
+    },
+    "KILL": function (killed) {
+    },
+    "ACKNOWLEDGED": function (acknowledged) {
+    },
+    "MESSAGE": function (message) {
+    },
+    "ERROR": function (error) {
+    },
+    "SHUTDOWN": function (shutdown) {
+    }
+};
+ 
+
+
+ + + + + + + diff --git a/docs/coverage/mesos-framework/lib/helpers.js.html b/docs/coverage/mesos-framework/lib/helpers.js.html new file mode 100644 index 0000000..e185476 --- /dev/null +++ b/docs/coverage/mesos-framework/lib/helpers.js.html @@ -0,0 +1,572 @@ + + + + Code coverage report for mesos-framework/lib/helpers.js + + + + + + + +
+
+

+ All files / mesos-framework/lib helpers.js +

+
+
+ 100% + Statements + 69/69 +
+
+ 100% + Branches + 55/55 +
+
+ 100% + Functions + 16/16 +
+
+ 100% + Lines + 69/69 +
+
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170  +  +1x +1x +1x +1x +  +1x +  +  +  +152x +  +  +  +  +  +  +  +  +  +  +  +152x +  +  +  +  +7x +  +  +  +  +  +30x +7x +  +23x +10x +  +13x +12x +  +1x +  +  +145x +  +145x +  +162x +  +162x +3x +3x +2x +  +  +  +  +160x +  +163x +163x +163x +86x +  +163x +  +  +  +  +143x +  +  +  +  +  +5x +  +  +5x +1x +  +  +5x +  +  +4x +  +  +4x +  +4x +4x +  +  +  +4x +1x +  +  +4x +3x +1x +  +2x +  +  +  +  +  +  +5x +1x +  +  +  +5x +  +  +5x +  +  +  +  +1732x +1732x +11565x +11565x +695x +  +  +695x +  +  +  +351x +  +  +1732x +  +  +  +1730x +1730x +1730x +8519x +605x +7914x +189x +  +189x +927x +922x +  +5x +  +  +189x +  +  +1730x +  +  +  +2x +  +  + 
"use strict";
+ 
+var http = require("http");
+var pathReq = require("path");
+var _ = require('lodash');
+var winston = require('winston');
+ 
+module.exports = {
+ 
+    getLogger: function(path, fileName, logLevel) {
+ 
+        var logger = new (winston.Logger)({
+            transports: [
+                new (winston.transports.Console)({ level: logLevel || "info" }),
+                new (require("winston-daily-rotate-file"))({
+                    filename: pathReq.join(__dirname, "../", (path && fileName ? path + "/" + fileName : "logs/mesos-framework.log")),
+                    level: logLevel || "info",
+                    prepend: true,
+                    json: false
+                })
+            ]
+        });
+ 
+        return logger;
+ 
+    },
+ 
+    cloneDeep: function(obj) {
+        return _.cloneDeep(obj);
+    },
+ 
+    sortTasksByPriority: function (tasks) {
+ 
+        function prioSort(a,b) {
+            if (a.priority < b.priority) {
+                return -1;
+            }
+            if (a.priority > b.priority) {
+                return 1;
+            }
+            if (a.name < b.name) {
+                return -1;
+            }
+            return 1;
+        }
+ 
+        var tasksArray = [];
+ 
+        Object.getOwnPropertyNames(tasks).forEach(function (task) {
+ 
+            var instances = tasks[task].instances || 1;
+ 
+            if (tasks[task].resources && tasks[task].resources.staticPorts) {
+                tasks[task].resources.staticPorts.sort();
+                if (!tasks[task].resources.ports || tasks[task].resources.staticPorts.length > tasks[task].resources.ports) {
+                    throw new Error("Static ports must be included in the general port count for the task.");
+                }
+            }
+ 
+            // Add to tasks array
+            for (var i = 1; i <= instances; i++) {
+                // Set defaults
+                tasks[task].isSubmitted = false;
+                tasks[task].name = task + "-" + i.toString();
+                if (!tasks[task].hasOwnProperty("allowScaling")) {
+                    tasks[task].allowScaling = false;
+                }
+                tasksArray.push(_.cloneDeep(tasks[task])); // Important!
+            }
+ 
+        });
+ 
+        return tasksArray.sort(prioSort);
+ 
+    },
+ 
+    doRequest: function (payload, callback) {
+ 
+        var self = this;
+ 
+        // Add mesos-stream-id to header
+        if (self.mesosStreamId) {
+            self.requestTemplate.headers["mesos-stream-id"] = self.mesosStreamId;
+        }
+ 
+        var req = http.request(self.requestTemplate, function (res) {
+ 
+            // Set encoding
+            res.setEncoding('utf8');
+ 
+            // Buffer for the response body
+            var body = "";
+ 
+            res.on('data', function (chunk) {
+                body += chunk;
+            });
+ 
+            // Watch for errors of the response
+            res.on('error', function (e) {
+                callback({ message: "There was a problem with the response: " + e.message }, null);
+            });
+ 
+            res.on('end', function () {
+                if (res.statusCode !== 202) {
+                    callback({ message: "Request was not accepted properly. Reponse status code was '" + res.statusCode + "'. Body was '" + body + "'." }, null);
+                } else {
+                    callback(null, { statusCode: res.statusCode, body: body });
+                }
+            });
+ 
+        });
+ 
+        // Watch for errors of the request
+        req.on('error', function (e) {
+            callback({ message: "There was a problem with the request: " + e.message }, null);
+        });
+ 
+        // Write data to request body
+        req.write(JSON.stringify(payload));
+ 
+        // End request
+        req.end();
+ 
+    },
+ 
+    stringifyEnums: function (message) {
+        message = _.clone(message); // We should not modify the source message in place, it causes issues with repeating calls
+        _.forEach(message.$type.children, function(child) {
+            var type = _.get(child, 'element.resolvedType', null);
+            if (type && type.className === 'Enum' && type.children) {
+                var metaValue = _.find(type.children, {
+                    id: message[child.name]
+                });
+                if (metaValue && metaValue.name)
+                // Alternatively you can do something like:
+                // message[child.name + '_string'] = metaValue.name;
+                // To get access to both the raw value and the string.
+                    message[child.name] = metaValue.name;
+            }
+        });
+        return message;
+    },
+ 
+    fixEnums: function (message) {
+        var self = this;
+        var newMessage = self.stringifyEnums(message);
+        _.forEach(message, function(subMessage, key) {
+            if (_.isObject(subMessage) && subMessage.$type) {
+                newMessage[key] = self.fixEnums(message[key]);
+            } else if (_.isArray(subMessage) && subMessage.length > 0) {
+                var arrayItems = [];
+                var index;
+                for (index = 0; index < subMessage.length; index += 1) {
+                    if (_.isObject(subMessage[index]) && subMessage[index].$type) {
+                        arrayItems.push(self.fixEnums(subMessage[index]));
+                    } else {
+                        arrayItems.push(subMessage[index]);
+                    }
+                }
+                newMessage[key] = arrayItems;
+            }
+        });
+        return newMessage;
+    },
+ 
+    isFunction: function(obj) {
+        return !!(obj && obj.constructor && obj.call && obj.apply);
+    }
+ 
+};
+
+
+ + + + + + + diff --git a/docs/coverage/mesos-framework/lib/index.html b/docs/coverage/mesos-framework/lib/index.html new file mode 100644 index 0000000..99a06bd --- /dev/null +++ b/docs/coverage/mesos-framework/lib/index.html @@ -0,0 +1,197 @@ + + + + Code coverage report for mesos-framework/lib + + + + + + + +
+
+

+ All files mesos-framework/lib +

+
+
+ 87.6% + Statements + 897/1024 +
+
+ 85.26% + Branches + 538/631 +
+
+ 78.06% + Functions + 121/155 +
+
+ 87.6% + Lines + 897/1024 +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
builder.js
85.71%6/750%1/2100%1/185.71%6/7
executor.js
12.37%12/970%0/450%0/1312.37%12/97
executorHandlers.js
100%6/6100%0/00%0/7100%6/6
helpers.js
100%69/69100%55/55100%16/16100%69/69
mesos.js
93.33%14/15100%2/280%4/593.33%14/15
scheduler.js
90.77%364/40185.28%197/23184.62%55/6590.77%364/401
schedulerHandlers.js
98.83%254/25793.05%174/18786.36%19/2298.83%254/257
taskHealthHelper.js
100%88/88100%61/61100%15/15100%88/88
taskHelper.js
100%84/84100%48/48100%11/11100%84/84
+
+
+ + + + + + + diff --git a/docs/coverage/mesos-framework/lib/mesos.js.html b/docs/coverage/mesos-framework/lib/mesos.js.html new file mode 100644 index 0000000..a09bc34 --- /dev/null +++ b/docs/coverage/mesos-framework/lib/mesos.js.html @@ -0,0 +1,239 @@ + + + + Code coverage report for mesos-framework/lib/mesos.js + + + + + + + +
+
+

+ All files / mesos-framework/lib mesos.js +

+
+
+ 93.33% + Statements + 14/15 +
+
+ 100% + Branches + 2/2 +
+
+ 80% + Functions + 4/5 +
+
+ 93.33% + Lines + 14/15 +
+
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59  +  +1x +1x +  +  +1x +  +  +1x +  +  +  +  +  +  +  +  +20x +9x +  +  +  +  +  +  +  +  +1x +9x +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +1x +  +  +1x + 
"use strict";
+ 
+var protoBuf = require("protobufjs");
+var path = require("path");
+ 
+// Load Mesos protobuf definitions
+var builder = protoBuf.loadProtoFile(path.join(__dirname, "../", "proto/all.proto"));
+ 
+// Instantiate protobuf definitions
+var mesos = builder.build("mesos");
+ 
+/**
+ * The Mesos protocol buffers helper
+ * @returns {object} An object with the Mesos protocol buffer definitions
+ * @constructor
+ */
+function Mesos () {
+ 
+    if (!(this instanceof Mesos)) {
+        return new Mesos();
+    }
+ 
+}
+ 
+/**
+ *
+ * @returns {Mesos}
+ */
+Mesos.prototype.getMesos = function () {
+    return mesos;
+};
+ 
+/**
+ * Get a ProtoBuf.Builder instance
+ * @returns {?ProtoBuf.Builder|undefined|ProtoBuf.Builder} A ProtoBuf.Builder instance
+ */
+Mesos.prototype.getBuilder = function () {
+    return builder;
+};
+ 
+/**
+ * Convenience method to get a ProtoBuf.Message instance of the specified `messageType`
+ * @param {string} messageType The
+ * @returns {?ProtoBuf.Message|undefined|ProtoBuf.Message} A ProtoBuf.Message instance
+ */
+Mesos.prototype.build = function (messageType) {
+    return new (builder.build(messageType))()
+};
+ 
+/**
+ * Get a reference to the protobuf.js module
+ * @returns {function} A reference to the protobuf.js module
+ */
+Mesos.prototype.getProtoBuf = function () {
+    return protoBuf;
+};
+ 
+module.exports = Mesos;
+ 
+
+
+ + + + + + + diff --git a/docs/coverage/mesos-framework/lib/scheduler.js.html b/docs/coverage/mesos-framework/lib/scheduler.js.html new file mode 100644 index 0000000..d7db93d --- /dev/null +++ b/docs/coverage/mesos-framework/lib/scheduler.js.html @@ -0,0 +1,3386 @@ + + + + Code coverage report for mesos-framework/lib/scheduler.js + + + + + + + +
+
+

+ All files / mesos-framework/lib scheduler.js +

+
+
+ 90.77% + Statements + 364/401 +
+
+ 85.28% + Branches + 197/231 +
+
+ 84.62% + Functions + 55/65 +
+
+ 90.77% + Lines + 364/401 +
+
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +982 +983 +984 +985 +986 +987 +988 +989 +990 +991 +992 +993 +994 +995 +996 +997 +998 +999 +1000 +1001 +1002 +1003 +1004 +1005 +1006 +1007 +1008 +1009 +1010 +1011 +1012 +1013 +1014 +1015 +1016 +1017 +1018 +1019 +1020 +1021 +1022 +1023 +1024 +1025 +1026 +1027 +1028 +1029 +1030 +1031 +1032 +1033 +1034 +1035 +1036 +1037 +1038 +1039 +1040 +1041 +1042 +1043 +1044 +1045 +1046 +1047 +1048 +1049 +1050 +1051 +1052 +1053 +1054 +1055 +1056 +1057 +1058 +1059 +1060 +1061 +1062 +1063 +1064 +1065 +1066 +1067 +1068 +1069 +1070 +1071 +1072 +1073 +1074 +1075 +1076 +1077 +1078 +1079 +1080 +1081 +1082 +1083 +1084 +1085 +1086 +1087 +1088 +1089 +1090 +1091 +1092 +1093 +1094 +1095 +1096 +1097 +1098 +1099 +1100 +1101 +1102 +1103 +1104 +1105 +1106 +1107 +1108  +  +1x +1x +1x +1x +  +1x +1x +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +112x +12x +  +  +  +100x +  +100x +  +100x +100x +100x +100x +100x +100x +100x +100x +100x +100x +100x +100x +  +  +100x +100x +100x +  +  +100x +  +100x +  +  +100x +  +100x +1x +  +  +  +100x +100x +  +  +100x +100x +100x +100x +  +  +100x +  +  +100x +70x +  +  +100x +  +100x +100x +100x +100x +  +  +100x +77x +75x +  +  +  +  +100x +  +  +100x +  +100x +104x +  +  +  +  +  +  +  +  +  +  +  +100x +  +  +100x +  +  +100x +  +  +  +  +  +  +  +  +  +  +  +  +  +100x +3x +3x +  +3x +2x +  +  +  +  +  +100x +70x +70x +  +75x +  +  +  +  +  +  +75x +  +  +  +100x +70x +  +  +  +100x +  +  +100x +  +11x +  +  +11x +  +  +11x +  +  +11x +  +  +11x +9x +  +  +  +11x +  +11x +4x +  +  +  +11x +  +11x +  +  +11x +  +11x +11x +  +7x +  +7x +  +4x +  +  +4x +  +3x +  +3x +  +  +3x +  +3x +1x +1x +1x +  +2x +2x +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +4x +4x +  +  +  +  +3x +  +  +4x +2x +  +2x +  +2x +  +  +  +  +  +  +  +  +11x +  +  +  +89x +89x +  +  +  +  +  +  +1x +  +  +  +  +1x +  +41x +  +  +  +  +  +  +  +25x +  +25x +  +  +23x +  +1x +  +  +22x +  +  +  +20x +  +14x +  +14x +14x +  +14x +6x +  +2x +  +2x +4x +  +1x +3x +  +1x +  +  +2x +  +  +  +6x +  +  +  +  +  +  +  +4x +  +  +4x +  +  +4x +  +  +4x +  +  +4x +1x +1x +  +3x +  +  +4x +  +  +4x +  +  +  +41x +  +41x +  +41x +  +41x +  +  +2x +  +  +2x +  +39x +34x +1x +  +  +  +33x +  +  +33x +  +  +33x +  +  +33x +33x +  +  +33x +  +30x +2x +  +  +30x +26x +26x +25x +25x +  +2x +  +  +23x +23x +  +23x +  +  +1x +  +  +4x +  +2x +  +2x +  +2x +2x +2x +  +1x +  +  +  +  +33x +6x +6x +6x +6x +  +  +6x +6x +6x +6x +  +  +  +33x +6x +  +  +33x +1x +  +  +  +  +  +5x +5x +4x +  +1x +  +  +  +  +  +  +41x +4x +  +  +  +41x +7x +7x +7x +3x +3x +3x +  +3x +3x +  +  +  +  +  +3x +  +  +3x +  +1x +1x +1x +1x +  +1x +  +2x +  +  +  +  +2x +  +2x +2x +  +2x +  +2x +  +  +  +  +2x +1x +1x +1x +1x +1x +  +  +  +  +  +  +  +  +41x +  +  +  +  +  +  +  +  +  +  +41x +  +  +41x +  +  +  +  +  +41x +  +31x +  +  +31x +  +  +  +  +  +  +  +  +  +  +1x +  +2x +  +  +2x +  +  +  +  +2x +  +  +2x +  +  +  +  +  +2x +  +2x +2x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +1x +  +2x +  +  +2x +  +  +  +  +2x +  +  +  +  +  +2x +  +2x +2x +1x +  +1x +  +  +  +  +  +  +  +  +  +1x +  +2x +  +2x +  +  +  +  +2x +  +2x +2x +1x +  +1x +  +  +  +  +  +  +  +  +1x +  +2x +  +2x +  +  +  +  +2x +  +2x +2x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +1x +  +6x +  +6x +  +  +  +  +  +  +  +  +6x +  +6x +  +6x +2x +  +6x +6x +1x +  +5x +  +  +  +  +  +  +  +  +  +  +  +1x +  +2x +  +2x +  +  +  +  +  +  +  +  +2x +  +2x +2x +1x +  +1x +  +  +  +  +  +  +  +  +  +1x +  +3x +  +3x +1x +1x +  +  +2x +  +  +  +  +  +  +  +  +  +2x +  +2x +2x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +1x +  +12x +  +12x +  +12x +7x +  +  +  +  +  +  +  +  +  +  +7x +  +5x +  +  +  +  +  +  +5x +  +  +12x +  +12x +8x +1x +  +7x +  +  +  +  +  +  +  +  +  +  +  +1x +  +2x +  +2x +  +  +  +  +  +  +  +  +  +2x +  +2x +2x +1x +  +1x +  +  +  +  +  +  +  +  +  +1x +  +2x +  +2x +  +  +  +  +  +  +  +2x +  +2x +2x +1x +  +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +1x +  +1x +1x +2x +  +  +  +1x +  +  +  +  +  +  +1x +16x +16x +6x +4x +  +2x +1x +  +  +16x +16x +2x +1x +  +  +16x +4x +  +16x +16x +5x +  +  +  +  +  +  +1x +17x +17x +17x +17x +10x +  +17x +1x +  +17x +  +  +1x + 
"use strict";
+ 
+var http = require("http");
+var EventEmitter = require("events").EventEmitter;
+var util = require("util");
+var uuid = require("uuid");
+ 
+var helpers = require("./helpers");
+var schedulerHandlers = require("./schedulerHandlers");
+var mesos = require("./mesos")().getMesos();
+var Builder = require("./builder");
+var TaskHelper = require("./taskHelper");
+ 
+var zookeeper = require("node-zookeeper-client");
+ 
+/**
+ * Represents a Mesos framework scheduler.
+ * @constructor
+ * @param {object} options - The option map object.
+ */
+function Scheduler (options) {
+ 
+    if (!(this instanceof Scheduler)) {
+        return new Scheduler(options);
+    }
+ 
+    // Inherit from EventEmitter
+    EventEmitter.call(this);
+ 
+    var self = this;
+ 
+    self.options = {};
+    self.options.frameworkName = (options.frameworkName ? options.frameworkName.replace(/ /g, "-") : "mesos-framework." + uuid.v4());
+    self.options.user = options.user || "root";
+    self.options.role = options.role || "*";
+    self.options.restartStates = options.restartStates || ["TASK_FAILED", "TASK_LOST", "TASK_ERROR"]; // Task in TASK_FINISHED will NOT be restarted by default!
+    self.options.frameworkFailoverTimeout = options.frameworkFailoverTimeout || 604800; // One week
+    self.options.masterConnectionTimeout = options.masterConnectionTimeout * 1000 || 10000; // Ten seconds
+    self.options.exponentialBackoffFactor = options.exponentialBackoffFactor || 1.5;
+    self.options.exponentialBackoffMinimum = options.exponentialBackoffMinimum * 1000 || 1000; // One second
+    self.options.exponentialBackoffMaximum = options.exponentialBackoffMaximum * 1000 || 15000; // 15 seconds
+    self.options.killUnknownTasks = options.killUnknownTasks || false;
+    self.options.serialNumberedTasks = (options.serialNumberedTasks !== false);
+ 
+    // 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));
+ 
+    self.subscribeBackoffTime = 0;
+ 
+    // 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;
+ 
+    // "Globals"
+    self.frameworkId = null;
+    self.mesosStreamId = null;
+    self.lastHeartbeat = null;
+    self.zkClient = null;
+ 
+    // Tasks
+    self.tasks = [];
+ 
+    // Add tasks if there are any
+    if (options.hasOwnProperty("tasks")) {
+        self.tasks = helpers.sortTasksByPriority(options.tasks);
+    }
+ 
+    self.logger.debug(JSON.stringify(self.tasks));
+ 
+    self.pendingTasks = [];
+    self.launchedTasks = [];
+    self.reconcileTasks = [];
+    self.killTasks = [];
+ 
+    // Add to pending tasks if not yet submitted
+    self.tasks.forEach(function (task) {
+        if (!task.isSubmitted) {
+            self.pendingTasks.push(task);
+        }
+    });
+ 
+    // Runtime info
+    self.runtimeInfo = {};
+ 
+    // Template for issuing Mesos Scheduler HTTP API requests
+    self.requestTemplate = {};
+ 
+    self.generateRequestTemplate = function () {
+        self.requestTemplate = {
+            host: self.options.masterUrl,
+            port: self.options.port,
+            path: "/api/v1/scheduler",
+            method: "POST",
+            headers: {
+                'Content-Type': 'application/json'
+            }
+        };
+    };
+ 
+    // Fill the requestTemplate
+    self.generateRequestTemplate();
+ 
+    // Customer event handlers will be registered here
+    self.customEventHandlers = {};
+ 
+    // List of allowed event handler function names and their argument length
+    var allowedEventHandlers = {
+        "SUBSCRIBED": 1,
+        "OFFERS": 1,
+        "INVERSE_OFFERS": 1,
+        "RESCIND":1,
+        "RESCIND_INVERSE_OFFER": 1,
+        "UPDATE": 1,
+        "MESSAGE": 1,
+        "FAILURE": 1,
+        "ERROR": 1,
+        "HEARTBEAT": 1
+    };
+ 
+    // Add custom event handlers if present
+    if (options.handlers && Object.getOwnPropertyNames(options.handlers).length > 0) {
+        Object.getOwnPropertyNames(options.handlers).forEach(function (handlerName) {
+            var ucHandlerName = handlerName.toUpperCase();
+            // Check if name is allowed, is a function and the length of the function arguments fit to the ones defined in allowedEventHandlers
+            if (Object.getOwnPropertyNames(allowedEventHandlers).indexOf(ucHandlerName) > -1 && helpers.isFunction(options.handlers[handlerName]) && options.handlers[handlerName].length === allowedEventHandlers[ucHandlerName]) {
+                self.customEventHandlers[ucHandlerName] = options.handlers[handlerName];
+            }
+        });
+    }
+ 
+    // Fill runtimeInfo from given Tasks
+    if (options.tasks && Object.getOwnPropertyNames(options.tasks).length > 0) {
+        var tempPriority = 1;
+        Object.getOwnPropertyNames(options.tasks).forEach(function (task) {
+            // Populate runtimeInfo for each task
+            self.runtimeInfo[task] = {
+                "desiredInstances": options.tasks[task].instances || 1,
+                "requestedInstances": 0,
+                "runningInstances": {},
+                "priority": options.tasks[task].priority || tempPriority
+            };
+            // Increase priority
+            tempPriority++;
+        });
+    }
+ 
+    if (options.hasOwnProperty("tasks")) {
+        self.logger.debug(JSON.stringify(helpers.sortTasksByPriority(options.tasks)));
+    }
+ 
+    // Store the long-running request
+    self.httpRequest = {};
+ 
+    // Handling of ZooKeeper-related stuff
+    if (self.options.useZk) {
+ 
+        self.logger.debug("Using ZooKeeper for persistency. Connection is " + self.options.zkUrl);
+ 
+        // Set default path for the service
+        self.zkServicePath = self.options.zkPrefix + self.options.frameworkName;
+ 
+        // Create ZK client (getting from options is only to be used for unit test!)
+        self.zkClient = options.zkClient || zookeeper.createClient(self.options.zkUrl);
+ 
+        // Instantiate TaskHelper (getting from options is only to be used for unit test!)
+        self.taskHelper = options.taskHelper || new TaskHelper(self);
+ 
+        // For unit test
+        if (options.taskHelper) {
+            self.taskHelper.scheduler = self;
+        }
+ 
+        // Set path for the framework id
+        var zkPath = self.zkServicePath + "/framework-id";
+ 
+        self.zkClient.on("error", function (error) {
+            self.logger.error(error);
+        });
+ 
+        // Once connected, check if path exists
+        self.zkClient.once("connected", function () {
+ 
+            self.logger.debug("Connected to ZooKeeper on " + self.options.zkUrl);
+ 
+            // Check if path with framework id exists
+            self.zkClient.getData(zkPath, null, function (error, data, stat) {
+ 
+                self.logger.debug("error before if:" + JSON.stringify(error));
+                if (error) {
+ 
+                    self.logger.debug("error:" + JSON.stringify(error));
+                    // Check if node doesn't exist yet
+                    if (error.getCode() === zookeeper.Exception.NO_NODE) {
+ 
+                        self.logger.debug("Node " + zkPath + " doesn't exist yet. Will be created on framework launch");
+ 
+                        // Add event handler for the SUBSCRIBE event, to set the framework id to ZooKeeper
+                        self.once("subscribed", function (obj) {
+ 
+                            self.logger.debug("Got subscribed event");
+ 
+                            self.logger.debug("now creating path " + zkPath);
+ 
+                            // Seperating path creation from data save due to various client bugs.
+                            self.zkClient.mkdirp(zkPath, function (error, stat) {
+ 
+                                if (error) {
+                                    self.logger.error("Got error when creating a ZK node for the framework ID: " + error.stack);
+                                    self.options.useZk = false;
+                                    self.zkClient.close();
+                                } else {
+                                    self.zkClient.setData(zkPath, new Buffer(self.frameworkId), function (error, stat) {
+                                        if (error) {
+                                            self.logger.error("Got error when saving the framework ID on ZK: " + error.stack);
+                                            self.options.useZk = false;
+                                            self.zkClient.close();
+                                        } else {
+                                            self.logger.debug("Successfully set framework ID")
+                                        }
+                                    });
+                                }
+ 
+                            });
+ 
+                        });
+ 
+                        // We're ready to subscribe
+                        // Timeout to let init finish
+                        setTimeout(function() {
+                            self.emit("ready");
+                        }, 100);
+ 
+                    } else {
+                        // Other error
+                        self.logger.error(error.stack);
+                    }
+ 
+                } else if (data) {
+                    self.logger.debug("Got framework ID from ZooKeeper:" + data.toString());
+                    // Set framework id to existing one from ZooKeeper
+                    self.frameworkId = data.toString();
+                    // Load tasks from ZooKeeper
+                    self.taskHelper.loadTasks();
+                    // "ready" event is emitted after successfully loading the tasks!
+                }
+ 
+            });
+ 
+        });
+ 
+        // Connect to ZooKeeper
+        self.zkClient.connect();
+ 
+    } else {
+        // Timeout to let init finish
+        setTimeout(function() {
+            self.emit("ready");
+        }, 100);
+    }
+ 
+}
+ 
+// Inhertit from EventEmitter
+util.inherits(Scheduler, EventEmitter);
+ 
+/**
+ * Subscribes the scheduler with the master to receive events. A scheduler must send other calls only after it has received the SUBCRIBED event.
+ */
+Scheduler.prototype.subscribe = function () {
+ 
+    var self = this;
+ 
+    /**
+     * The handler funciton for the incoming Mesos master events for this framework.
+     * @param {object} eventData - The data object for an incoming event. Contains the event details (type etc.).
+     */
+    function handleEvent (eventData) {
+ 
+        try {
+ 
+            var event = JSON.parse(eventData);
+ 
+            // Determine event handler, use custom one if it exists
+            if (self.customEventHandlers[event.type]) {
+                // Call custom handler
+                self.customEventHandlers[event.type].call(self, event[event.type.toLocaleLowerCase()]);
+            } else {
+                // Call default handler
+                schedulerHandlers[event.type].call(self, event[event.type.toLocaleLowerCase()]);
+            }
+ 
+            // Emit events per type
+            if (event.type === "SUBSCRIBED") {
+                // Set frameworkId
+                self.frameworkId = event[event.type.toLocaleLowerCase()].framework_id.value;
+                // TODO: Check!
+                self.sync();
+                self.subscribeBackoffTime = 0;
+                // Emit with usable object details
+                self.emit("subscribed", { frameworkId: event[event.type.toLocaleLowerCase()].framework_id.value, mesosStreamId: self.mesosStreamId });
+            } else if (event.type === "HEARTBEAT") {
+                // Set lastHeartbeat timestamp
+                self.lastHeartbeat = new Date().getTime();
+                // Emit with current timestamp
+                self.emit(event.type.toLocaleLowerCase(), self.lastHeartbeat);
+            } 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()]);
+            }
+ 
+        } catch (error) {
+            self.emit("error", { message: "Couldn't parse as JSON: " + eventData, stack: (error.stack || "") });
+        }
+ 
+    }
+ 
+    function handleRedirect(location) {
+ 
+        // Redirection to another Master received
+        self.logger.info("SUBSCRIBE: Redirect Location: " + location);
+ 
+        // Derive the leader info
+        var leaderInfo = location.replace(/\/\//g, "").split(":");
+ 
+        // Check for scheme and move window accordingly
+        var schemeIndex = leaderInfo.length > 2 ? 0 : -1;
+ 
+        // Set new leading master info
+        self.options.masterUrl = leaderInfo[schemeIndex + 1];
+ 
+        // If the port part contains slashes -> URLs, then fiix it by just getting the port
+        if (leaderInfo[schemeIndex + 2].indexOf("\/") > -1) {
+            var temp = leaderInfo[schemeIndex + 2].split("/");
+            self.options.port = temp[0];
+        } else {
+            self.options.port = leaderInfo[schemeIndex + 2];
+        }
+ 
+        self.logger.info("SUBSCRIBE: Leader info: " + self.options.masterUrl + ":" + self.options.port);
+ 
+        // Fill the requestTemplate
+        self.generateRequestTemplate();
+ 
+    }
+ 
+    var handledTimeout = false;
+ 
+    self.httpRequest = http.request(self.requestTemplate, function (res) {
+ 
+        self.logger.info("SUBSCRIBE: Response status: " + res.statusCode);
+ 
+        if (res.statusCode === 307 && res.headers["location"]) {
+ 
+            // Handle redirect information
+            handleRedirect(res.headers["location"]);
+ 
+            // Try to re-register
+            self.subscribe();
+ 
+        } else if (res.statusCode === 200) {
+            if (!res.headers["mesos-stream-id"]) {
+                self.emit("error", { message: "Mesos-Stream-Id header field was not found!"})
+            } else {
+ 
+                // Set mesosStreamId
+                self.mesosStreamId = res.headers["mesos-stream-id"];
+ 
+                // Set encoding to UTF8
+                res.setEncoding('utf8');
+ 
+                // Emit sent_subscribe event
+                self.emit("sent_subscribe", { mesosStreamId: self.mesosStreamId });
+ 
+                // Local cache for chunked JSON messages
+                var cache = "";
+                var expectedLength = 0;
+ 
+                // Watch for data/chunks
+                res.on('data', function (chunk) {
+ 
+                    if (chunk instanceof Buffer) {
+                        chunk = chunk.toString();
+                    }
+ 
+                    if (chunk.indexOf("\n") > -1) {
+                        var temp = chunk.split("\n");
+                        if (temp.length === 2) {
+                            expectedLength = parseInt(temp[0]);
+                            if (temp[1].length < expectedLength) {
+                                // Add to cache
+                                cache += temp[1];
+                            } else {
+                                // Empty cache
+                                cache = "";
+                                expectedLength = 0;
+                                // Handle event
+                                handleEvent(temp[1]);
+                            }
+                        } else {
+                            self.emit("error", { message: "Other linebreak count found than expected! Actual count: " + temp.length });
+                        }
+                    } else {
+                        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;
+                        }
+                    }
+                });
+ 
+                res.on('end', function () {
+                    self.emit("error", { message: "Long-running connection was closed!" });
+                    self.logger.info("Long-running connection was closed!");
+                    Eif (!handledTimeout) {
+                        self.backOff();
+                        // 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 () {
+                    self.logger.info("FINISH!");
+                });
+ 
+                res.on('close', function () {
+                    self.logger.info("CLOSE!");
+                });
+ 
+            }
+ 
+        } else {
+            res.on("data",function (chunk) {
+                if (chunk.length > 0) {
+                    self.emit("error", {message: "Error registering with mesos: " + chunk.toString() + " , code: " + res.statusCode.toString()});
+                } else {
+                    self.emit("error", {message: "Error registering with mesos - empty response, code: " + res.statusCode.toString()});
+                }
+            });
+        }
+ 
+    });
+ 
+    self.httpRequest.on('error', function (e) {
+        self.emit("error", { message: "There was a problem with the request: " + (e.message ? e.message : JSON.stringify(e)) });
+    });
+ 
+    // Register a timeout for triggering of re-registrations of the scheduler
+    self.httpRequest.on('socket', function (socket) {
+        var httpRequest = self.httpRequest;
+        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!");
+            handledTimeout = true;
+            socket.destroy();
+            // Make sure the timeout is not re-emitted.
+            socket.setTimeout(0);
+            Iif (httpRequest !== self.httpRequest) {
+                self.logger.info("Already reconnected, not attempting again.");
+                return;
+            }
+ 
+            // Backing off before resubscribe
+            self.backOff();
+ 
+            // 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();
+            } else {
+                self.logger.info("Not using Mesos DNS, try to get new leader through redirection!");
+                // If not, it's more difficult. When a IP address is passed for the Master, and the Master is unavailable,
+                // we cannot use the Master detection via location headers, as outlined at http://mesos.apache.org/documentation/latest/scheduler-http-api/ (chapter "Master detection"),
+                // because the request will not be successful. So, first we'll try the redirect method (in case of a leader change), if that is not possible, we have to shut down our framework
+                // unless there is a better way in the future.
+                var redirectRequest = http.request(self.requestTemplate, function (res) {
+                    // Check if we received a redirect
+                    Eif (res.statusCode === 307 && res.headers["location"]) {
+                        self.logger.info("Received redirection information. Will attempt to re-register the framework scheduler!");
+                        // Handle redirect information
+                        handleRedirect(res.headers["location"]);
+                        // Subscribe
+                        self.subscribe();
+                    }
+                });
+                // Set timeout for redirect request. When it's triggered, we know that the last leading master is down and that we cannot get the current leader information from it.
+                // So, we have to shutdown the framework scheduler, because we're out of options.
+                redirectRequest.on('socket', function (socket) {
+                    socket.setTimeout(self.options.masterConnectionTimeout);
+                    socket.on('timeout', function() {
+                        self.logger.error("Couldn't receive a response for the redirect request from the last leading master!");
+                        self.logger.error("There's no way to recover, the framework scheduler will halt now!");
+                        process.exit(1);
+                    });
+                });
+            }
+ 
+        });
+    });
+ 
+    // Set the Subscribe object
+    var Subscribe = new Builder("mesos.scheduler.Call.Subscribe")
+        .setFrameworkInfo(new Builder("mesos.FrameworkInfo")
+            .setUser(self.options.user)
+            .setRole(self.options.role)
+            .setName(self.options.frameworkName)
+            .setId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+            .setFailoverTimeout(self.options.frameworkFailoverTimeout)
+            .setHostname(process.env.HOST ? process.env.HOST : null)
+            .setWebuiUrl(process.env.HOST && process.env.PORT0 ? "http://" + process.env.HOST + ":" + process.env.PORT0 : null)
+        );
+ 
+    self.logger.info("SUBSCRIBE: " + JSON.stringify(Subscribe));
+ 
+    // Set the Call object
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.SUBSCRIBE)
+        .setSubscribe(Subscribe)
+    );
+ 
+    setTimeout(function () {
+        // Write data to request body
+        self.httpRequest.write(JSON.stringify(Call));
+ 
+        // End request
+        self.httpRequest.end();
+    }, self.subscribeBackoffTime);
+ 
+};
+ 
+/**
+ * Accept incoming offers to actually start the framework scheduler.
+ * @param {array} offersIds - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be accepted.
+ * @param {array} operations - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1452|Operation} objects.
+ * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object.
+ */
+Scheduler.prototype.accept = function (offersIds, operations, filters) {
+ 
+    var self = this;
+ 
+    // Set the Accept object
+    var Accept = new Builder("mesos.scheduler.Call.Accept")
+            .setOfferIds(offersIds)
+            .setOperations(operations)
+            .setFilters(filters);
+ 
+    self.logger.info("ACCEPT: " + JSON.stringify(Accept));
+ 
+    // Set the Call object
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(new mesos.FrameworkID(self.frameworkId))
+        .setType(mesos.scheduler.Call.Type.ACCEPT)
+        .setAccept(Accept)
+    );
+ 
+    self.logger.debug("Assembled ACCEPT call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_accept");
+        }
+    });
+ 
+};
+ 
+/**
+ * Decline incoming offers because they are not needed by the framework scheduler currently.
+ * @param {array} offersIds - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be declined.
+ * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object.
+ */
+Scheduler.prototype.decline = function (offersIds, filters) {
+ 
+    var self = this;
+ 
+    // Set the Decline object
+    var Decline = new Builder("mesos.scheduler.Call.Decline")
+        .setOfferIds(offersIds)
+        .setFilters(filters);
+ 
+    // Set the Call object
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(new mesos.FrameworkID(self.frameworkId))
+        .setType(mesos.scheduler.Call.Type.DECLINE)
+        .setDecline(Decline)
+    );
+ 
+    self.logger.debug("Assembled DECLINE call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_decline");
+        }
+    });
+ 
+};
+ 
+/**
+ * Tear down the framework scheduler. When Mesos receives this request it will shut down all executors (and consequently kill tasks).
+ * It then removes the framework and closes all open connections from this scheduler to the Master.
+ */
+Scheduler.prototype.teardown = function () {
+ 
+    var self = this;
+ 
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.TEARDOWN)
+    );
+ 
+    self.logger.debug("Assembled TEARDOWN call: " + JSON.stringify(Call));
+    
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_teardown");
+        }
+    });
+ 
+};
+ 
+/**
+ * Remove any/all filters that it has previously set via ACCEPT or DECLINE calls.
+ */
+Scheduler.prototype.revive = function () {
+ 
+    var self = this;
+ 
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.REVIVE)
+    );
+ 
+    self.logger.debug("Assembled REVIVE call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_revive");
+        }
+    });
+ 
+};
+ 
+/**
+ *  Kill a specific task. If the scheduler has a custom executor, the kill is forwarded to the executor; it is up to the executor to kill the task and send a TASK_KILLED (or TASK_FAILED) update.
+ *  Mesos releases the resources for a task once it receives a terminal update for the task. If the task is unknown to the master, a TASK_LOST will be generated.
+ * @param {Object} taskId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L71|TaskID} to kill.
+ * @param {Object} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on.
+ */
+Scheduler.prototype.kill = function (taskId, agentId) {
+ 
+    var self = this;
+ 
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.KILL)
+        .setKill(new Builder("mesos.scheduler.Call.Kill")
+            .setTaskId(new Builder("mesos.TaskID").setValue(taskId))
+            .setAgentId(new Builder("mesos.AgentID").setValue(agentId))
+        )
+    );
+ 
+    self.logger.debug("Assembled KILL call: " + JSON.stringify(Call));
+ 
+    self.logger.debug("Killing task ID: " + taskId);
+ 
+    if (self.options.useZk)
+        self.taskHelper.deleteTask(taskId);
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_kill");
+        }
+    });
+ 
+};
+ 
+/**
+ * shutdown a specific custom executor (NOTE: This is a new call that was not present in the old API). When an executor gets a shutdown event, it is expected to kill all its tasks (and send TASK_KILLED updates) and terminate.
+ * If an executor doesn’t terminate within a certain timeout (configurable via “–executor_shutdown_grace_period” agent flag), the agent will forcefully destroy the container (executor and its tasks) and transitions its active tasks to TASK_LOST.
+ * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on.
+ * @param {string} executorId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L81|ExecutorID} whcih runs the task.
+ */
+Scheduler.prototype.shutdown = function (agentId, executorId) {
+ 
+    var self = this;
+ 
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.SHUTDOWN)
+        .setShutdown(new Builder("mesos.scheduler.Call.Shutdown")
+            .setExecutorId(new Builder("mesos.ExecutorID").setValue(executorId))
+            .setAgentId(new Builder("mesos.AgentID").setValue(agentId))
+        )
+    );
+ 
+    self.logger.debug("Assembled SHUTDOWN call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_shutdown");
+        }
+    });
+ 
+};
+ 
+/**
+ * Acknowledge a status update.
+ * @param {object} update The status update to acknowledge.
+ */
+Scheduler.prototype.acknowledge = function (update) {
+ 
+    var self = this;
+ 
+    if (!update.status.uuid) {
+        self.logger.debug("An update without UUID received, acknowledge skipped. Update: " + JSON.stringify(update));
+        return;
+    }
+ 
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.ACKNOWLEDGE)
+        .setAcknowledge(new Builder("mesos.scheduler.Call.Acknowledge")
+            .setTaskId(new Builder("mesos.TaskID").setValue(update.status.task_id))
+            .setAgentId(new Builder("mesos.AgentID").setValue(update.status.agent_id))
+            .setUuid(update.status.uuid)
+        )
+    );
+ 
+    self.logger.debug("Assembled ACKNOWLEDGE call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_acknowledge");
+        }
+    });
+ 
+};
+ 
+/**
+ * query the status of non-terminal tasks. This causes the master to send back UPDATE events for each task in the list. Tasks that are no longer known to Mesos will result in TASK_LOST updates.
+ * If the list of tasks is empty, master will send UPDATE events for all currently known tasks of the framework.
+ * @param {string} taskId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L71|TaskID} to kill.
+ * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on.
+ */
+Scheduler.prototype.reconcile = function (taskId, agentId) {
+ 
+    var self = this;
+ 
+    var Call = null;
+ 
+    if (taskId && agentId) {
+        Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+            .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+            .setType(mesos.scheduler.Call.Type.RECONCILE)
+            .setReconcile(new Builder("mesos.scheduler.Call.Reconcile")
+                .setTasks(new Builder("mesos.scheduler.Call.Reconcile.Task")
+                    .setTaskId(new Builder("mesos.TaskID").setValue(taskId))
+                    .setAgentId(new Builder("mesos.AgentID").setValue(agentId)
+                    )
+                )
+            )
+        );
+        self.logger.debug("Reconciling task ID: " + taskId);
+    } else {
+        Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+            .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+            .setType(mesos.scheduler.Call.Type.RECONCILE)
+            .setReconcile(new Builder("mesos.scheduler.Call.Reconcile")
+                .setTasks([])
+            )
+        );
+        self.logger.debug("Reconciling all tasks ");
+    }
+ 
+    self.logger.debug("Assembled RECONCILE call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_reconcile");
+        }
+    });
+ 
+};
+ 
+/**
+ * Send arbitrary data to the executor. Note that Mesos neither interprets this data nor makes any guarantees about the delivery of this message to the executor.
+ * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on.
+ * @param {string} executorId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L81|ExecutorID} which runs the task.
+ * @param {string} data The string which's raw bytes will be encoded in Base64.
+ */
+Scheduler.prototype.message = function (agentId, executorId, data) {
+ 
+    var self = this;
+ 
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.MESSAGE)
+        .setMessage(new Builder("mesos.scheduler.Call.Message")
+            .setExecutorId(new Builder("mesos.ExecutorID").setValue(executorId))
+            .setAgentId(new Builder("mesos.AgentID").setValue(agentId))
+            .setData(new Buffer(data).toString("base64"))
+        )
+    );
+ 
+    self.logger.debug("Assembled MESSAGE call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_message");
+        }
+    });
+ 
+};
+ 
+/**
+ * Request resources from the master/allocator. The built-in hierarchical allocator simply ignores this request but other allocators (modules) can interpret this in a customizable fashion.
+ * @param {array} requests The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1410|Request} objects which should be sent to the server.
+ */
+Scheduler.prototype.request = function (requests) {
+ 
+    var self = this;
+ 
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.REQUEST)
+        .setRequest(new Builder("mesos.scheduler.Call.Request")
+            .setRequests(requests)
+        )
+    );
+ 
+    self.logger.debug("Assembled REQUEST call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_request");
+        }
+    });
+ 
+};
+ 
+/**
+ * Suppress offers for the specified roles. If `roles` is empty, the `SUPPRESS` call will suppress offers for all of the roles the framework is currently subscribed to.
+ * @param {array} roles The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2696|Role} objects which should be sent to the server.
+ */
+Scheduler.prototype.suppress = function (roles) {
+ 
+    var self = this;
+ 
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.SUPPRESS)
+        .setSuppress(new Builder("mesos.scheduler.Call.Suppress")
+            .setRoles(roles)
+        )
+    );
+ 
+    self.logger.debug("Assembled SUPPRESS call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_suppress");
+        }
+    });
+ 
+};
+ 
+/**
+ * Accepts an inverse offer. Inverse offers should only be accepted if the resources in the offer can be safely evacuated before the provided unavailability.
+ * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server.
+ * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server.
+ */
+Scheduler.prototype.acceptInverseOffers = function (inverseOffersIds, filters) {
+ 
+    var self = this;
+ 
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.ACCEPT_INVERSE_OFFERS)
+        .setAcceptInverseOffers(new Builder("mesos.scheduler.Call.AcceptInverseOffers")
+            .setInverseOfferIds(inverseOffersIds)
+            .setFilter(filters)
+        )
+    );
+ 
+    self.logger.debug("Assembled ACCEPT_INVERSE_OFFERS call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_accept_inverse_offers");
+        }
+    });
+ 
+};
+ 
+/**
+ * Declines an inverse offer. Inverse offers should be declined if the resources in the offer might not be safely evacuated before the provided unavailability.
+ * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server.
+ * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server.
+ */
+Scheduler.prototype.declineInverseOffers = function (inverseOffersIds, filters) {
+ 
+    var self = this;
+ 
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.DECLINE_INVERSE_OFFERS)
+        .setDeclineInverseOffers(new Builder("mesos.scheduler.Call.DeclineInverseOffers")
+            .setInverseOfferIds(inverseOffersIds)
+            .setFilter(filters)
+        )
+    );
+ 
+    self.logger.debug("Assembled DECLINE_INVERSE_OFFERS call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_decline_inverse_offers");
+        }
+    });
+ 
+};
+ 
+/**
+ * Acknowledges the receipt of an operation status update. Schedulers are responsible for explicitly acknowledging the receipt of updates which have the 'UpdateOperationStatus.status().uuid()' field set. Such status updates are retried by the agent or resource provider until they are acknowledged by the scheduler.
+ * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on.
+ * @param {string} resourceProviderId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L102|ResourceProviderId}
+ * @param {string} operationId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L111|OperationID}
+ * @param {string} uuid The uuid of the Operation
+ */
+Scheduler.prototype.acknowledgeOperationStatus = function (agentId, resourceProviderId, operationId, uuid) {
+ 
+    var self = this;
+ 
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.ACKNOWLEDGE_OPERATION_STATUS)
+        .setAcknowledgeOperationStatus(new Builder("mesos.scheduler.Call.AcknowledgeOperationStatus")
+            .setAgentId(new Builder("mesos.AgentID").setValue(agentId))
+            .setResourceProviderId(new Builder("mesos.ResourceProviderId").setValue(resourceProviderId))
+            .setOperationId(new Builder("mesos.ResourceProviderId").setValue(operationId))
+            .setUuid(uuid)
+        )
+    );
+ 
+    self.logger.debug("Assembled ACKNOWLEDGE_OPERATION_STATUS call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_acknowledge_operation_status");
+        }
+    });
+ 
+};
+ 
+/**
+ * Allows the scheduler to query the status of operations. This causes the master to send back the latest status for each operation in 'operations', if possible. If 'operations' is empty, then the master will send the latest status for each operation currently known.
+ * @param {array} operations An array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/scheduler/scheduler.proto#L420|Operation} objects to query.
+ */
+Scheduler.prototype.reconcileOperations = function (operations) {
+ 
+    var self = this;
+ 
+    var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call")
+        .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null)
+        .setType(mesos.scheduler.Call.Type.RECONCILE_OPERATIONS)
+        .setReconcileOperations(new Builder("mesos.scheduler.Call.ReconcileOperations")
+            .setOperations(operations)
+        )
+    );
+ 
+    self.logger.debug("Assembled RECONCILE_OPERATIONS call: " + JSON.stringify(Call));
+ 
+    helpers.doRequest.call(self, Call, function (error, response) {
+        if (error) {
+            self.emit("error", error.message);
+        } else {
+            self.emit("sent_reconcile_operations");
+        }
+    });
+ 
+};
+ 
+/**
+ * Get the running tasks of this framework scheduler.
+ * @returns {Array} The running task array.
+ */
+Scheduler.prototype.getRunningTasks = function () {
+ 
+    var self = this;
+    var runningTasks = [];
+ 
+    Object.getOwnPropertyNames(self.runtimeInfo).forEach(function (taskType) {
+        Object.getOwnPropertyNames(self.runtimeInfo[taskType].runningInstances).forEach(function (task) {
+            runningTasks.push(task);
+        });
+    });
+ 
+    return runningTasks;
+ 
+};
+ 
+/**
+ * Synchronize the tasks of this scheduler.
+ */
+Scheduler.prototype.sync = function () {
+    var self = this;
+    for (var i = 0; i < self.reconcileTasks.length; i++) {
+        if (self.reconcileTasks[i].runtimeInfo.agentId) {
+            self.reconcile(self.reconcileTasks[i].taskId, self.reconcileTasks[i].runtimeInfo.agentId);
+        } else {
+            if (self.options.useZk)
+                self.taskHelper.deleteTask(self.reconcileTasks[i].taskId);
+        }
+    }
+    self.reconcileTasks = [];
+    self.launchedTasks.forEach(function (task) {
+        if (task.runtimeInfo.agentId) {
+            self.reconcile(task.taskId, task.runtimeInfo.agentId);
+        }
+    });
+    for (var i = 0; i < self.killTasks.length; i++) {
+        self.kill(self.killTasks[i].taskId, self.killTasks[i].runtimeInfo.agentId);
+    }
+    self.killTasks = [];
+    if (self.options.useZk) {
+        self.reconcile();
+    }
+};
+ 
+/**
+ * Calculate the backOff time (for reconnection trials)
+ */
+Scheduler.prototype.backOff = function () {
+    var self = this;
+    self.subscribeBackoffTime *= self.options.exponentialBackoffFactor;
+    self.subscribeBackoffTime = Math.round(self.subscribeBackoffTime);
+    if (self.subscribeBackoffTime === 0) {
+        self.subscribeBackoffTime = self.options.exponentialBackoffMinimum;
+    }
+    if (self.subscribeBackoffTime > self.options.exponentialBackoffMaximum) {
+        self.subscribeBackoffTime = self.options.exponentialBackoffMaximum;
+    }
+    self.logger.debug("Backoff time: " + self.subscribeBackoffTime);
+};
+ 
+module.exports = Scheduler;
+ 
+
+
+ + + + + + + diff --git a/docs/coverage/mesos-framework/lib/schedulerHandlers.js.html b/docs/coverage/mesos-framework/lib/schedulerHandlers.js.html new file mode 100644 index 0000000..6a42927 --- /dev/null +++ b/docs/coverage/mesos-framework/lib/schedulerHandlers.js.html @@ -0,0 +1,1823 @@ + + + + Code coverage report for mesos-framework/lib/schedulerHandlers.js + + + + + + + +
+
+

+ All files / mesos-framework/lib schedulerHandlers.js +

+
+
+ 98.83% + Statements + 254/257 +
+
+ 93.05% + Branches + 174/187 +
+
+ 86.36% + Functions + 19/22 +
+
+ 98.83% + Lines + 254/257 +
+
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587  +1x +  +1x +1x +1x +1x +1x +  +  +  +12x +12x +  +12x +12x +  +  +  +  +  +  +12x +32x +  +32x +10x +10x +10x +10x +10x +13x +  +13x +  +9x +  +13x +13x +2x +  +13x +  +10x +8x +  +10x +22x +7x +  +  +7x +14x +7x +  +  +  +7x +7x +7x +7x +7x +7x +  +7x +  +4x +  +7x +7x +  +7x +2x +  +7x +  +7x +5x +  +7x +  +15x +  +  +  +12x +10x +10x +10x +  +12x +  +  +1x +  +14x +  +  +  +19x +  +19x +  +  +19x +  +19x +19x +19x +  +  +  +  +  +  +  +  +19x +  +1x +  +  +1x +  +1x +  +  +  +  +  +19x +77x +57x +20x +19x +  +57x +  +57x +  +779x +  +  +  +  +  +  +19x +  +18x +  +  +18x +18x +16x +  +  +16x +  +16x +  +  +  +  +  +16x +16x +  +16x +15x +  +15x +  +  +16x +15x +15x +15x +15x +  +15x +12x +12x +12x +12x +12x +  +  +  +15x +15x +18x +18x +18x +18x +  +18x +  +18x +  +158x +  +158x +  +  +18x +7x +  +  +18x +  +  +15x +  +15x +  +  +15x +178x +  +  +  +15x +  +  +  +  +  +  +  +  +15x +  +  +14x +14x +11x +  +3x +3x +  +3x +3x +3x +  +  +  +3x +  +  +  +  +  +14x +12x +  +12x +176x +176x +  +  +  +  +  +  +  +  +  +16x +  +  +16x +13x +13x +  +  +16x +3x +  +  +13x +  +10x +  +3x +  +  +  +13x +  +  +13x +  +  +13x +2x +2x +  +  +  +  +  +  +  +2x +  +  +  +13x +  +  +13x +1x +  +  +13x +  +  +13x +  +  +  +  +  +  +  +  +  +  +  +  +  +13x +  +  +13x +12x +12x +12x +12x +  +  +  +  +  +  +1x +1x +1x +  +  +  +  +  +  +13x +  +  +13x +  +  +13x +  +  +13x +2x +  +  +13x +  +13x +  +  +16x +  +  +2x +  +  +  +  +  +19x +  +13x +  +13x +  +  +  +13x +  +  +13x +  +  +  +  +19x +  +5x +5x +  +5x +  +  +  +  +  +  +  +  +  +  +  +15x +  +15x +  +  +  +15x +  +  +15x +4x +  +4x +4x +  +4x +5x +  +4x +  +2x +2x +  +2x +1x +  +2x +  +  +2x +2x +  +2x +1x +  +  +  +2x +  +2x +  +2x +  +2x +  +2x +1x +  +1x +  +8x +  +8x +  +  +  +1x +  +1x +  +2x +  +2x +  +1x +  +  +  +11x +  +11x +11x +  +11x +11x +9x +  +9x +6x +6x +  +6x +  +2x +2x +  +2x +1x +  +  +4x +  +4x +  +  +4x +3x +3x +2x +  +  +3x +2x +  +3x +1x +  +3x +  +1x +  +  +4x +  +  +  +  +  +  +4x +  +  +4x +3x +  +  +  +  +  +  +11x +  +3x +1x +1x +  +2x +1x +1x +  +  +  +  +  +  +  +15x +  +  +15x +  +  +  +2x +  +  +  +  +  +1x +  +  +  +  +  +1x +  +  +1x +  +  + 
"use strict";
+var uuid = require('uuid');
+ 
+var lib = require("requirefrom")("lib");
+var Mesos = lib("mesos");
+var Builder = lib("builder");
+var helpers = lib("helpers");
+var mesos = new Mesos().getMesos();
+ 
+function searchPortsInRanges(task, offerResources, usableRanges, neededStaticPorts, neededPorts) {
+ 
+    var tempPortRanges = [];
+    var usedPorts = [];
+ 
+    var begin = 0;
+    var stop = false;
+    var range;
+    var newBegin;
+    var newEnd;
+    var i;
+    var index;
+    var port;
+    while (neededStaticPorts > 0 && !stop && offerResources.portRanges && offerResources.portRanges.length > 0) {
+        range = offerResources.portRanges.splice(0, 1)[0]; // Get first remaining range
+ 
+        if (range.begin <= task.resources.staticPorts[begin] && range.end >= task.resources.staticPorts[task.resources.staticPorts.length - 1]) {
+            usableRanges.push(new mesos.Value.Range(range.begin, task.resources.staticPorts[task.resources.staticPorts.length - 1]));
+            newBegin = range.begin;
+            newEnd = range.end;
+            i = begin;
+            while (i < task.resources.staticPorts.length) {
+                port = task.resources.staticPorts[i];
+ 
+                if (newBegin < port) {
+                    // Re-add range below port
+                    tempPortRanges.push(new mesos.Value.Range(newBegin, port - 1));
+                }
+                newBegin = port + 1;
+                if (newEnd === port) {
+                    newEnd -= 1;
+                }
+                i += 1;
+            }
+            if (newBegin <= newEnd) {
+                tempPortRanges.push(new mesos.Value.Range(newBegin, newEnd));
+            }
+            neededStaticPorts = 0;
+        } else if (range.begin <= task.resources.staticPorts[begin] && range.end >= task.resources.staticPorts[begin]) {
+            usableRanges.push(range);
+            // Count the number of ports that are not served.
+ 
+            for (i = begin; i < task.resources.staticPorts.length; i++) {
+                if (task.resources.staticPorts[i] > range.end) {
+                    break;
+                }
+            }
+ 
+            neededStaticPorts -= i - begin;
+            newBegin = range.begin;
+            newEnd = range.end;
+            index = begin;
+            while (index < i) {
+                port = task.resources.staticPorts[index];
+ 
+                if (newBegin < port) {
+                    // Re-add range below port
+                    tempPortRanges.push(new mesos.Value.Range(newBegin, port - 1));
+                }
+                Eif (newBegin <= port) {
+                    newBegin = port + 1;
+                }
+                if (newEnd === port) {
+                    newEnd -= 1;
+                }
+                index += 1;
+            }
+            if (newBegin <= newEnd) {
+                tempPortRanges.push(new mesos.Value.Range(newBegin, newEnd));
+            }
+            begin = i;
+        } else {
+            tempPortRanges.push(range);
+        }
+    }
+ 
+    if (neededStaticPorts === 0) {
+        neededPorts -= task.resources.staticPorts.length;
+        usedPorts = task.resources.staticPorts;
+        offerResources.portRanges = offerResources.portRanges.concat(tempPortRanges);
+    }
+    return {usedPorts: usedPorts, neededPorts: neededPorts, neededStaticPorts: neededStaticPorts};
+}
+ 
+module.exports = {
+    "SUBSCRIBED": function (subscribed) {
+        this.logger.debug("SUBSCRIBED: " + JSON.stringify(subscribed));
+    },
+    "OFFERS": function (Offers) {
+ 
+        var self = this;
+ 
+        self.logger.debug("OFFERS: " + JSON.stringify(Offers));
+ 
+        // Iterate over all Offers
+        Offers.offers.forEach(function (offer) {
+ 
+            var toLaunch = [];
+            var declinedNoPending = false;
+            var offerResources = {
+                cpus: 0,
+                mem: 0,
+                disk: 0,
+                ports: [],
+                portRanges: []
+            };
+ 
+            // Decline Offer directly if there are no pending tasks
+            if (self.pendingTasks.length === 0) {
+ 
+                self.logger.debug("DECLINE: Declining Offer " + offer.id.value);
+ 
+                // Decline offer
+                self.decline([offer.id], null);
+                // To prevent double decline
+                declinedNoPending = true;
+ 
+            }
+ 
+            // Iterate over the Resources of the Offer and fill the offerResources object
+            // (will be used to match against the requested task resources)
+            offer.resources.forEach(function (resource) {
+                if (resource.type === "SCALAR" && ["cpus", "mem", "disk"].indexOf(resource.name) > -1) {
+                    offerResources[resource.name] += resource.scalar.value;
+                } else if (resource.type === "RANGES" && resource.name === "ports") {
+                    resource.ranges.range.forEach(function (range) {
+                        // Add to ranges
+                        offerResources.portRanges.push(range);
+                        // Populate port list
+                        for (var p = range.begin; p <= range.end; p++) {
+                            // Add port to port array
+                            offerResources.ports.push(p);
+                        }
+                    });
+                }
+            });
+ 
+            // Now, iterate over all tasks that still need to be run
+            self.pendingTasks.forEach(function (task) {
+ 
+                self.logger.debug("pendingTask: " + JSON.stringify(task));
+ 
+                // Match the task resources to the offer resources
+                self.logger.debug("CPUs in offer:" + offerResources.cpus.toString() + " Memory in offer: " + offerResources.mem.toString() + " Port num in offer: " + offerResources.ports.length.toString());
+                if (task.resources.cpus <= offerResources.cpus && task.resources.mem <= offerResources.mem && task.resources.disk <= offerResources.disk && (task.resources.ports <= offerResources.ports.length || (self.options.staticPorts && task.resources.staticPorts && task.resources.staticPorts.length <= offerResources.ports.length))) {
+                    self.logger.debug("Offer " + offer.id.value + " has resources left");
+ 
+                    // Environment variables
+                    var envVars = [];
+ 
+                    var demandedResources = [
+                        helpers.fixEnums(new Builder("mesos.Resource").setName("cpus").setType(mesos.Value.Type.SCALAR).setScalar(new mesos.Value.Scalar(task.resources.cpus))),
+                        helpers.fixEnums(new Builder("mesos.Resource").setName("mem").setType(mesos.Value.Type.SCALAR).setScalar(new mesos.Value.Scalar(task.resources.mem)))
+                    ];
+ 
+                    // Reduce available offer cpu and mem resources by requested task resources
+                    offerResources.cpus -= task.resources.cpus;
+                    offerResources.mem -= task.resources.mem;
+ 
+                    if (task.resources.disk > 0) {
+                        demandedResources.push(helpers.fixEnums(new Builder("mesos.Resource").setName("disk").setType(mesos.Value.Type.SCALAR).setScalar(new mesos.Value.Scalar(task.resources.disk))));
+                        // Reduce disk resources by requested task resources
+                        offerResources.disk -= task.resources.disk;
+                    }
+ 
+                    if (task.resources.ports > 0) {
+                        var neededPorts = task.resources.ports;
+                        var usableRanges = [];
+                        var usedPorts = [];
+                        var neededStaticPorts = task.resources.staticPorts ? task.resources.staticPorts.length : 0;
+ 
+                        if (self.options.staticPorts && task.resources.staticPorts && task.resources.staticPorts.length > 0) { // Using fixed ports defined in the framework configuration
+                            usedPorts = task.resources.staticPorts;
+                            var __ret = searchPortsInRanges.call(self, task, offerResources, usableRanges, neededStaticPorts, neededPorts);
+                            usedPorts = __ret.usedPorts;
+                            neededPorts = __ret.neededPorts;
+                            neededStaticPorts = __ret.neededStaticPorts;
+                        }
+                        // Using dynamic ports (in addition or instead of fixed ports)
+ 
+                        self.logger.debug("portRanges: " + JSON.stringify(offerResources.portRanges));
+                        while (neededPorts > 0 && offerResources.portRanges && offerResources.portRanges.length > 0) {
+                            var range = offerResources.portRanges.splice(0, 1)[0]; // Get first remaining range
+                            self.logger.debug("actualRange: " + JSON.stringify(range));
+                            var availablePorts = (range.end - range.begin + 1);
+                            var willUsePorts = (availablePorts >= neededPorts ? neededPorts : availablePorts);
+                            // Add to usable ranges
+                            usableRanges.push(new mesos.Value.Range(range.begin, range.begin + willUsePorts - 1));
+                            // Add to used ports array
+                            for (var port = range.begin; port <= (range.begin + willUsePorts - 1); port++) {
+                                // Add to used ports
+                                usedPorts.push(port);
+                                // Remove from ports array / reduce available ports by requested task resources
+                                offerResources.ports.splice(offerResources.ports.indexOf(port), 1);
+                            }
+                            // Push range back portRanges if there are ports left
+                            if (availablePorts > willUsePorts) {
+                                offerResources.portRanges.push(new mesos.Value.Range(range.begin + willUsePorts, range.end))
+                            }
+                            // Decrease needed ports number by used ports
+                            neededPorts -= willUsePorts;
+                        }
+ 
+                        self.logger.debug("usableRanges: " + JSON.stringify(usableRanges));
+ 
+                        var usedPortRanges = [];
+                        var index;
+ 
+                        for (index = 0; index < usedPorts.length; index += 1) {
+                            usedPortRanges.push(new mesos.Value.Range(usedPorts[index], usedPorts[index]));
+                        }
+ 
+                        // Add to demanded resources
+                        demandedResources.push(
+                            helpers.fixEnums(
+                                new Builder("mesos.Resource").setName("ports")
+                                    .setType(mesos.Value.Type.RANGES)
+                                    .setRanges(new Builder("mesos.Value.Ranges").setRange(usedPortRanges))
+                            )
+                        );
+ 
+                        // Check if task is a container task, and if so, it the networking mode is BRIDGE and there are port mappings defined
+                        if (task.containerInfo) {
+ 
+                            // Add the port mappings if needed
+                            Eif (task.containerInfo.docker.network === mesos.ContainerInfo.DockerInfo.Network.BRIDGE && task.portMappings && task.portMappings.length > 0) {
+                                if (usedPorts.length !== task.portMappings.length) {
+                                    self.logger.debug("No match between task's port mapping count and the used/requested port count!");
+                                } else {
+                                    var portMappings = [],
+                                        counter = 0;
+                                    // Iterate over given port mappings, and create mapping
+                                    task.portMappings.forEach(function (portMapping) {
+                                        portMappings.push(new mesos.ContainerInfo.DockerInfo.PortMapping(usedPorts[counter], portMapping.port, portMapping.protocol));
+                                        counter++;
+                                    });
+ 
+                                    // Overwrite port mappings
+                                    task.containerInfo.docker.port_mappings = portMappings;
+                                }
+ 
+                            }
+ 
+                            // Add the PORTn environment variables
+                            if (usedPorts.length > 0) {
+                                var portIndex = 0;
+                                // Create environment variables for the used ports (schema is "PORT" appended by port index)
+                                usedPorts.forEach(function (port) {
+                                    envVars.push(new Builder("mesos.Environment.Variable").setName("PORT" + portIndex).setValue(port.toString()));
+                                    portIndex++;
+                                });
+ 
+                            }
+ 
+                        }
+                    }
+ 
+ 
+                    // Add HOST
+                    envVars.push(new Builder("mesos.Environment.Variable").setName("HOST").setValue(offer.url.address.ip));
+ 
+                    // Add env var for serial task number
+                    if (self.options.serialNumberedTasks) {
+                        var taskNameArray = task.name.split("-");
+                        envVars.push(new Builder("mesos.Environment.Variable").setName("TASK_" + taskNameArray[0].toUpperCase() + "_SERIAL_NUMBER").setValue(taskNameArray[1]));
+                    }
+ 
+                    if (neededPorts > 0 || neededStaticPorts > 0) {
+                        self.logger.error("Couldn't find enough ports!");
+                    } else {
+                        //Check if there are already environment variables set
+                        if (task.commandInfo.environment && task.commandInfo.environment.variables && task.commandInfo.environment.variables.length > 0) {
+                            // Merge the arrays
+                            task.commandInfo.environment.variables = task.commandInfo.environment.variables.concat(envVars);
+                        } else { // Just set them
+                            task.commandInfo.environment = new mesos.Environment(envVars);
+                        }
+ 
+                        // Get unique taskId
+                        var taskId = self.options.frameworkName + "." + task.name.replace(/\//, "_") + "." + uuid.v4();
+ 
+                        // Set taskId
+                        task.taskId = taskId;
+ 
+                        // HTTP health checks
+                        if (task.healthCheck && task.healthCheck.http) {
+                            var healthCheckPort = task.healthCheck.http.port ? task.healthCheck.http.port : usedPorts[0]; // TODO: Check how to make this more reliable
+                            task.mesosHealthCheck = new Builder("mesos.HealthCheck")
+                                .setType(mesos.HealthCheck.Type.HTTP)
+                                .setHttp(new Builder("mesos.HealthCheck.HTTPCheckInfo")
+                                    .setScheme(task.healthCheck.http.scheme || "http")
+                                    .setPort(healthCheckPort)
+                                    .setPath(task.healthCheck.http.path || "/")
+                                    .setStatuses(task.healthCheck.http.statuses || [200])
+                                );
+                            self.logger.debug("Http healthCheck" + JSON.stringify(task.mesosHealthCheck));
+                        }
+ 
+                        //
+                        task.mesosName = task.name.replace(/\//, "_");
+ 
+                        // Remove serial number from mesos task name if not activated (added by default)
+                        if (!self.options.serialNumberedTasks) {
+                            task.mesosName = task.mesosName.replace(/-[0-9]+$/, "");
+                        }
+ 
+                        self.logger.debug("Mesos task name: " + task.mesosName + " is using serialNumberedTasks: " + self.options.serialNumberedTasks.toString());
+ 
+                        // Push TaskInfo to toLaunch
+                        toLaunch.push(
+                            new Builder("mesos.TaskInfo")
+                                .setName(task.mesosName)
+                                .setTaskId(new mesos.TaskID(taskId))
+                                .setAgentId(offer.agent_id)
+                                .setResources(demandedResources)
+                                .setExecutor((task.executorInfo ? helpers.fixEnums(task.executorInfo) : null))
+                                .setCommand((task.commandInfo ? helpers.fixEnums(task.commandInfo) : null))
+                                .setContainer((task.containerInfo ? helpers.fixEnums(task.containerInfo) : null))
+                                .setHealthCheck((task.mesosHealthCheck ? helpers.fixEnums(task.mesosHealthCheck) : null))
+                                .setLabels((task.labels ? task.labels : null))
+                        );
+ 
+                        // Set submit status
+                        task.isSubmitted = true;
+ 
+                        // Set network runtime info from offer and used ports
+                        if (!task.runtimeInfo) {
+                            task.runtimeInfo = {};
+                            task.runtimeInfo.agentId = offer.agent_id.value || null;
+                            task.runtimeInfo.state = "TASK_STAGING";
+                            task.runtimeInfo.network = {
+                                "hostname": offer.hostname,
+                                "ip": offer.url.address.ip || null,
+                                "ports": usedPorts
+                            };
+ 
+                        } else {
+                            task.runtimeInfo.state = "TASK_STAGING";
+                            task.runtimeInfo.agentId = offer.agent_id.value || null;
+                            task.runtimeInfo.network = {
+                                "hostname": offer.hostname,
+                                "ip": offer.url.address.ip || null,
+                                "ports": usedPorts
+                            };
+                        }
+ 
+                        self.logger.debug("task details for taskId " + task.taskId + ": " + JSON.stringify(task));
+ 
+                        // Remove from pendingTasks!
+                        self.pendingTasks.splice(self.pendingTasks.indexOf(task), 1);
+ 
+                        // Add to launched tasks
+                        self.launchedTasks.push(task);
+ 
+                        // Save to ZooKeeper
+                        if (self.options.useZk && self.taskHelper) {
+                            self.taskHelper.saveTask(task);
+                        }
+ 
+                        self.logger.debug("launchedTasks length: " + self.launchedTasks.length + "; pendingTask length: " + self.pendingTasks.length);
+ 
+                        declinedNoPending = true;
+                    }
+ 
+                    self.logger.debug("Offer " + offer.id.value + ": Available resources: " + offerResources.cpus + " - " + offerResources.mem + " - " + offerResources.disk + " - " + offerResources.ports.length)
+ 
+                } else {
+                    self.logger.error("Offer " + offer.id.value + " has no fitting resources left");
+                }
+ 
+            });
+ 
+            // Only trigger a launch if there's actually something to launch :-)
+            if (toLaunch.length > 0) {
+ 
+                process.nextTick(function () {
+                    // Set the Operations object
+                    var Operations = new Builder("mesos.Offer.Operation")
+                        .setType(mesos.Offer.Operation.Type.LAUNCH)
+                        .setLaunch(new mesos.Offer.Operation.Launch(toLaunch));
+ 
+                    self.logger.debug("Operation before accept: " + JSON.stringify(helpers.fixEnums(Operations)));
+ 
+                    // Trigger acceptance
+                    self.accept([offer.id], Operations, null);
+                });
+            }
+ 
+            // Decline offer if not used
+            if (!declinedNoPending) {
+ 
+                process.nextTick(function () {
+                    self.logger.debug("DECLINE: Declining Offer " + offer.id.value);
+                    // Trigger decline
+                    self.decline([offer.id], null);
+                });
+ 
+            }
+        });
+ 
+    },
+    "INVERSE_OFFERS": function (reverseOffers) {
+        this.logger.debug("INVERSE_OFFERS: " + JSON.stringify(reverseOffers));
+    },
+    "UPDATE": function (update) {
+ 
+        var self = this;
+ 
+        self.logger.debug("UPDATE: " + JSON.stringify(update));
+ 
+        function handleUpdate(status) {
+ 
+            self.logger.debug("UPDATE: Got state " + status.state + " for TaskID " + status.task_id.value);
+ 
+            // Check if the state is defined as a restart state
+            if (self.options.restartStates.indexOf(status.state) > -1) {
+                self.logger.error("TaskId " + status.task_id.value + " got restartable state: " + status.state);
+                // Track launchedTasks array index
+                var foundIndex = 0;
+                var tempLaunchedTasks = self.launchedTasks.slice();
+                // Restart task by splicing it from the launchedTasks array, and afterwards putting it in the pendingTasks array after a cleanup
+                tempLaunchedTasks.forEach(function (task) {
+                    if (status.task_id.value === task.taskId) {
+                        // Check if task was restarted, it means it was already replaced.
+                        if (task.runtimeInfo.restarting) {
+                            // Remove task from launchedTasks array
+                            self.launchedTasks.splice(self.launchedTasks.indexOf(task), 1);
+                            self.logger.debug("TaskId " + status.task_id.value + " was killed and removed from the launchedTasks");
+ 
+                            if (self.options.useZk) {
+                                self.taskHelper.deleteTask(status.task_id.value);
+                            }
+                            return;
+                        }
+                        // Splice from launchedTasks if found
+                        var taskToRestart = helpers.cloneDeep(self.launchedTasks.splice(foundIndex, 1)[0]);
+                        self.logger.debug("taskToRestart before cleaning: " + JSON.stringify(taskToRestart));
+ 
+                        if (self.options.useZk) {
+                            self.taskHelper.deleteTask(taskToRestart.taskId);
+                        }
+ 
+                        // Reset isSubmitted status
+                        taskToRestart.isSubmitted = false;
+                        // Remove old taskId
+                        delete taskToRestart.taskId;
+                        // Remove old runtimeInfo
+                        delete taskToRestart.runtimeInfo;
+                        // Remove old health check (it changes by allocated ports)
+                        delete task.mesosHealthCheck;
+                        // Remove previously set HOST and PORTn environment variables
+                        if (taskToRestart.commandInfo.environment.variables && taskToRestart.commandInfo.environment.variables.length > 0) {
+                            var usableVariables = [];
+                            // Iterate over all environment variables
+                            taskToRestart.commandInfo.environment.variables.forEach(function (variable) {
+                                // Check if variable name contains either HOST or PORT -> Set by this framework when starting a task
+                                Eif (variable.name.match(/^HOST$/g) === null && variable.name.match(/^PORT[0-9]+$/g) === null) {
+                                    // Add all non-matching (user-defined) environment variables
+                                    usableVariables.push(variable);
+                                }
+                            });
+                            // Remove old variables
+                            delete taskToRestart.commandInfo.environment.variables;
+                            // Add the user-defined variables again
+                            taskToRestart.commandInfo.environment.variables = usableVariables;
+                        }
+                        self.logger.debug("taskToRestart after cleaning: " + JSON.stringify(taskToRestart));
+                        // Restart task by putting it in the pendingTasks array
+                        self.pendingTasks.push(taskToRestart);
+                    } else {
+                        foundIndex++;
+                    }
+                });
+            } else {
+                self.logger.debug("TaskId " + status.task_id.value + " got state: " + status.state);
+                // Keep track of index
+                var index = 0;
+                var match = false;
+ 
+                self.logger.debug("Iterate over launched tasks...");
+                for (index = 0; index < self.launchedTasks.length; index++) {
+                    var task = self.launchedTasks[index];
+ 
+                    if (status.task_id.value === task.taskId) {
+                        self.logger.debug("Matched TaskId " + status.task_id.value);
+                        match = true;
+                        // Check if state is TASK_KILLED and TASK_KILLED is not in restartable states array, same for TASK_FINISHED
+                        if ((self.options.restartStates.indexOf("TASK_KILLED") === -1 && status.state === "TASK_KILLED") || (self.options.restartStates.indexOf("TASK_FINISHED") === -1 && status.state === "TASK_FINISHED") || (task.runtimeInfo.restarting)) {
+                            // Remove task from launchedTasks array
+                            self.launchedTasks.splice(index, 1);
+                            self.logger.debug("TaskId " + status.task_id.value + " was killed and removed from the launchedTasks");
+ 
+                            if (self.options.useZk) {
+                                self.taskHelper.deleteTask(status.task_id.value);
+                            }
+                        } else {
+                            var taskStartTime = Date.now();
+                            // Store network info
+                            var network = {};
+ 
+                            // Remove old runtime info if present
+                            if (Object.getOwnPropertyNames(task.runtimeInfo).length > 0) {
+                                network = helpers.cloneDeep(task.runtimeInfo.network);
+                                if (!status.executor_id || !status.executor_id.value) {
+                                    status.executor_id = {value: task.runtimeInfo.executorId};
+                                }
+                                // Check if we need to emit an event
+                                if (task.runtimeInfo.state === "TASK_STAGING" && status.state === "TASK_RUNNING") {
+                                    self.emit("task_launched", task);
+                                }
+                                if (task.runtimeInfo.startTime) {
+                                    taskStartTime = task.runtimeInfo.startTime
+                                }
+                                delete task.runtimeInfo;
+                            } else {
+                                self.emit("task_launched", task);
+                            }
+                            // Update task runtime info
+                            task.runtimeInfo = {
+                                agentId: status.agent_id.value,
+                                executorId: status.executor_id.value,
+                                state: status.state,
+                                startTime: taskStartTime,
+                                network: network
+                            };
+                            self.logger.debug("TaskId " + status.task_id.value + " updated task runtime info: " + JSON.stringify(task.runtimeInfo));
+ 
+                            // Save task to ZooKeeper
+                            if (self.options.useZk) {
+                                self.taskHelper.saveTask(task);
+                            }
+                        }
+ 
+                    }
+                }
+                // TODO: Check!
+                if (!match && index >= self.launchedTasks.length && status.reason === "REASON_RECONCILIATION") {
+                    // Cleaning up unknown tasks
+                    if (self.options.killUnknownTasks && status.state === "TASK_RUNNING") {
+                        self.logger.info("Killing unknown task ID: " + status.task_id.value + " on agent: " + status.agent_id.value);
+                        self.kill(status.task_id.value, status.agent_id.value);
+                        // Cleaning up stale tasks from ZK.
+                    } else if (status.state !== "TASK_RUNNING" && self.options.useZk) {
+                        self.logger.info("Cleaning up an unknown task from ZK: " + status.task_id.value);
+                        self.taskHelper.deleteTask(status.task_id.value);
+                    }
+                }
+ 
+            }
+        }
+ 
+        // Handle status update
+        handleUpdate(update.status);
+ 
+        // Acknowledge update
+        self.acknowledge(update);
+ 
+    },
+    "RESCIND": function (offerId) {
+        this.logger.debug("RESCIND: " + JSON.stringify(offerId));
+    },
+    "RESCIND_INVERSE_OFFER": function (offerId) {
+        this.logger.debug("RESCIND_INVERSE_OFFER: " + JSON.stringify(offerId));
+    },
+    "MESSAGE": function (message) {
+        this.logger.debug("MESSAGE: " + JSON.stringify(message));
+    },
+    "FAILURE": function (failure) {
+        this.logger.debug("FAILURE: " + JSON.stringify(failure));
+    },
+    "ERROR": function (error) {
+        this.logger.debug("ERROR: " + JSON.stringify(error));
+    },
+    "HEARTBEAT": function (heartbeat) {
+        this.logger.debug("HEARTBEAT: " + JSON.stringify(heartbeat));
+    }
+};
+ 
+
+
+ + + + + + + diff --git a/docs/coverage/mesos-framework/lib/taskHealthHelper.js.html b/docs/coverage/mesos-framework/lib/taskHealthHelper.js.html new file mode 100644 index 0000000..1ef12b5 --- /dev/null +++ b/docs/coverage/mesos-framework/lib/taskHealthHelper.js.html @@ -0,0 +1,560 @@ + + + + Code coverage report for mesos-framework/lib/taskHealthHelper.js + + + + + + + +
+
+

+ All files / mesos-framework/lib taskHealthHelper.js +

+
+
+ 100% + Statements + 88/88 +
+
+ 100% + Branches + 61/61 +
+
+ 100% + Functions + 15/15 +
+
+ 100% + Lines + 88/88 +
+
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166  +  +1x +  +  +  +  +  +  +  +  +29x +1x +  +  +28x +  +28x +28x +28x +28x +28x +28x +28x +28x +28x +28x +28x +28x +  +28x +27x +  +1x +  +  +27x +1x +  +  +  +  +  +  +  +  +27x +  +2x +  +2x +4x +  +  +  +  +1x +10x +10x +3x +  +7x +  +  +1x +  +26x +  +26x +7x +  +26x +26x +5x +5x +5x +5x +21x +2x +  +  +  +  +1x +  +11x +  +11x +10x +9x +7x +  +6x +  +6x +3x +  +3x +6x +  +  +3x +3x +3x +  +3x +1x +1x +1x +  +2x +  +  +  +  +3x +3x +3x +  +  +  +1x +  +7x +  +9x +2x +2x +  +9x +  +  +  +  +1x +8x +8x +  +8x +7x +7x +4x +  +7x +  +  +  +  +1x +6x +  +6x +1x +1x +  +  +  +1x +3x +  +3x +3x +  +  +1x + 
"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.propertyPrefix = options.propertyPrefix || "";
+    self.options.errorEvent = options.errorEvent || self.options.propertyPrefix + "task_unhealthy";
+    self.options.additionalProperties = options.additionalProperties || [];
+    self.options.taskNameFilter = options.taskNameFilter || null;
+    self.options.statusCodes = options.statusCodes || [200];
+    self.options.checkBodyFunction = options.checkBodyFunction || null;
+ 
+    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;
+    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.setProperties(task, false);
+        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) {
+ 
+                    var value = false;
+ 
+                    if (self.options.checkBodyFunction) {
+                        var responseBodyBuilder = '';
+ 
+                        res.on("data", function (chunk) {
+                            responseBodyBuilder += chunk;
+                        });
+ 
+                        res.on("end", function () {
+                            value = self.options.checkBodyFunction.call(self, task, responseBodyBuilder);
+                            self.logger.debug("Checking the response body: " + value);
+ 
+                            if (value) {
+                                task.runtimeInfo[self.options.propertyPrefix + "checkFailCount"] = 0;
+                                task.runtimeInfo[self.options.propertyPrefix + "healthy"] = value;
+                                self.setProperties(task, value);
+                            } else {
+                                self.setCheckFailed.call(self, task);
+                            }
+ 
+                        });
+                    } else {
+                        task.runtimeInfo[self.options.propertyPrefix + "checkFailCount"] = 0;
+                        task.runtimeInfo[self.options.propertyPrefix + "healthy"] = true;
+                        self.setProperties(task, true);
+                    }
+ 
+                } 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.setProperties = function (task, value) {
+    var self = this;
+    self.options.additionalProperties.forEach(function (property) {
+        // If healthy or setting unhealthy
+        if (value || property.setUnhealthy) {
+            var propertyValue = value;
+            if (property.inverse) {
+                propertyValue = !value;
+            }
+            task.runtimeInfo[property.name] = propertyValue;
+        }
+    });
+};
+ 
+TaskHealthHelper.prototype.stopHealthCheck = function () {
+    var self = this;
+ 
+    if (self.interval) {
+        clearInterval(self.interval);
+        self.interval = null;
+    }
+};
+ 
+TaskHealthHelper.prototype.setupHealthCheck = function () {
+    var self = this;
+ 
+    self.stopHealthCheck();
+    self.interval = setInterval(self.checkRunningInstances, self.options.interval * 1000);
+};
+ 
+module.exports = TaskHealthHelper;
+ 
+
+
+ + + + + + + diff --git a/docs/coverage/mesos-framework/lib/taskHelper.js.html b/docs/coverage/mesos-framework/lib/taskHelper.js.html new file mode 100644 index 0000000..f6e6b10 --- /dev/null +++ b/docs/coverage/mesos-framework/lib/taskHelper.js.html @@ -0,0 +1,518 @@ + + + + Code coverage report for mesos-framework/lib/taskHelper.js + + + + + + + +
+
+

+ All files / mesos-framework/lib taskHelper.js +

+
+
+ 100% + Statements + 84/84 +
+
+ 100% + Branches + 48/48 +
+
+ 100% + Functions + 11/11 +
+
+ 100% + Lines + 84/84 +
+
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152  +  +1x +1x +1x +  +  +  +  +  +  +  +21x +1x +  +20x +20x +20x +20x +20x +  +  +  +  +  +1x +9x +9x +9x +1x +  +1x +8x +7x +7x +17x +17x +3x +3x +1x +  +3x +3x +3x +  +2x +  +3x +  +14x +14x +14x +14x +14x +14x +  +  +  +12x +  +8x +  +  +14x +13x +13x +13x +12x +7x +7x +7x +4x +1x +  +  +  +4x +1x +  +  +4x +  +7x +7x +7x +  +5x +  +12x +12x +  +  +14x +2x +2x +  +14x +14x +14x +14x +  +5x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +1x +3x +3x +  +3x +3x +1x +1x +  +2x +2x +1x +1x +  +1x +  +  +  +  +  +  +  +  +1x +8x +8x +8x +1x +  +7x +  +  +  +  +1x + 
"use strict";
+ 
+var lib = require("requirefrom")("lib");
+var Mesos = require("./mesos")().getMesos();
+var Builder = lib("builder");
+ 
+/**
+ * Represents a TaskHelper object
+ * @constructor
+ * @param {object} scheduler - The scheduler object.
+ */
+function TaskHelper(scheduler) {
+    if (!(this instanceof TaskHelper)) {
+        return new TaskHelper(scheduler);
+    }
+    var self = this;
+    self.zkClient = scheduler.zkClient;
+    self.scheduler = scheduler;
+    self.logger = scheduler.logger;
+    self.zkServicePath = self.scheduler.zkServicePath;
+}
+ 
+/**
+ * Load the task nodes belonging to the framework from ZooKeeper.
+ */
+TaskHelper.prototype.loadTasks = function() {
+    var self = this;
+    self.zkClient.getChildren(self.zkServicePath + "/tasks", function (error, children, stat) {
+        if (error) {
+            self.logger.error("Could not load task information.");
+            // We're ready to subscribe
+            self.scheduler.emit("ready");
+        } else if (children && children.length) {
+            var childStates = {};
+            children.forEach(function (child) {
+                self.zkClient.getData(self.zkServicePath + "/tasks/" + child, function (error, data, stat) {
+                    if (error || !data) {
+                        self.logger.error("Could not load task information for " + child);
+                        if (!error) {
+                            self.deleteTask(child);
+                        }
+                        childStates[child] = {'loaded': false};
+                        self.logger.debug("childStates length " + Object.keys(childStates).length.toString() + " children.length " + children.length.toString());
+                        if (Object.keys(childStates).length === children.length) {
+                            // We're ready to subscribe
+                            self.scheduler.emit("ready");
+                        }
+                        return;
+                    }
+                    var pending = self.scheduler.pendingTasks;
+                    self.scheduler.pendingTasks = [];
+                    var task = JSON.parse(data.toString());
+                    self.logger.debug("Loading task: " + JSON.stringify(task));
+                    var found = false;
+                    var i = 0;
+                    var pendingTask;
+                    function addVars(variable) {
+                        // Check if variable name is either HOST or PORT# -> Set by this framework when starting a task - copy it to the loaded task
+                        if (variable.name.match(/^HOST$/) !== null || variable.name.match(/^PORT[0-9]+/) !== null) {
+                            // Add all matching (non-user-defined) environment variables
+                            pendingTask.commandInfo.environment.variables.push(variable);
+                        }
+                    }
+                    for (i = 0; i < pending.length; i += 1) {
+                        pendingTask = pending[i];
+                        self.logger.debug("Pending task: \"" + JSON.stringify(pendingTask) + "\"");
+                        if (pendingTask.name === task.name) {
+                            if (task.runtimeInfo && task.runtimeInfo.agentId && (task.runtimeInfo.state === "TASK_RUNNING" || task.runtimeInfo.state === "TASK_STAGING")) {
+                                pendingTask.runtimeInfo = task.runtimeInfo;
+                                pendingTask.taskId = task.taskId;
+                                if (task.commandInfo && task.commandInfo.environment && task.commandInfo.environment.variables && task.commandInfo.environment.variables.length > 0) {
+                                    if (!pendingTask.commandInfo) {
+                                        pendingTask.commandInfo = new Builder("mesos.CommandInfo")
+                                            .setEnvironment(new Mesos.Environment([]))
+                                            .setShell(false);
+                                    }
+                                    if (!pendingTask.commandInfo.environment) {
+                                        pendingTask.commandInfo.environment = new Mesos.Environment([]);
+                                    }
+                                    // Iterate over all environment variables
+                                    task.commandInfo.environment.variables.forEach(addVars);
+                                }
+                                self.scheduler.launchedTasks.push(pendingTask);
+                                pending.splice(i, 1);
+                                self.scheduler.reconcileTasks.push(pendingTask);
+                            } else {
+                                self.deleteTask(task.taskId);
+                            }
+                            found = true;
+                            break;
+                        }
+                    }
+                    if (!found) {
+                        self.logger.info("Setting task ID " + task.taskId + " to be killed");
+                        self.scheduler.killTasks.push(task);
+                    }
+                    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) {
+                        // We're ready to subscribe
+                        self.scheduler.emit("ready");
+                    }
+                });
+            });
+        } else {
+            // We're ready to subscribe - no tasks
+            self.scheduler.emit("ready");
+        }
+    });
+};
+ 
+/**
+ * Save task nodes from ZooKeeper.
+ * @param {object} task - The task object which should be persisted to ZooKeeper.
+ */
+TaskHelper.prototype.saveTask = function (task) {
+    var self = this;
+    var data = new Buffer(JSON.stringify(task));
+    // Seperating path creation from data save due to various client bugs.
+    self.zkClient.mkdirp(self.zkServicePath+"/tasks/" + task.taskId, function (error, stat){
+        if (error) {
+            self.logger.error("Got error when creating task node in ZK " + task.name + " ID " + task.taskId + " data: " + error);
+            return;
+        }
+        self.zkClient.setData(self.zkServicePath+"/tasks/" + task.taskId, data, function (error, stat) {
+            if (error) {
+                self.logger.error("Got error when saving task " + task.name + " ID " + task.taskId + " data: " + error);
+                return;
+            }
+            self.logger.debug("Saved task " + task.name + " ID " + task.taskId);
+        });
+    });
+};
+ 
+/**
+ * Delete task nodes from ZooKeeper.
+ * @param {string} taskId - The id of the task which should be deleted from ZooKeeper.
+ */
+TaskHelper.prototype.deleteTask = function (taskId) {
+    var self = this;
+    self.zkClient.remove(self.zkServicePath + "/tasks/" + taskId, function (error) {
+        if (error) {
+            self.logger.error("Error deleting task ID " + taskId + " from zookeeper");
+        } else {
+            self.logger.debug("Deleted task " + taskId + " from zookeeper");
+        }
+    });
+};
+ 
+module.exports = TaskHelper;
+ 
+
+
+ + + + + + + diff --git a/docs/coverage/prettify.css b/docs/coverage/prettify.css new file mode 100644 index 0000000..b317a7c --- /dev/null +++ b/docs/coverage/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/docs/coverage/prettify.js b/docs/coverage/prettify.js new file mode 100644 index 0000000..ef51e03 --- /dev/null +++ b/docs/coverage/prettify.js @@ -0,0 +1 @@ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/docs/coverage/sort-arrow-sprite.png b/docs/coverage/sort-arrow-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..03f704a609c6fd0dbfdac63466a7d7c958b5cbf3 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jii$m5978H@?Fn+^JD|Y9yzj{W`447Gxa{7*dM7nnnD-Lb z6^}Hx2)'; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function (a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function (a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function () { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i =0 ; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function () { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(cols); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/docs/executor.js.html b/docs/executor.js.html index a22afdf..4aea169 100644 --- a/docs/executor.js.html +++ b/docs/executor.js.html @@ -24,7 +24,7 @@
@@ -334,7 +334,7 @@

executor.js


- Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/index.html b/docs/index.html index f94b272..432d27b 100644 --- a/docs/index.html +++ b/docs/index.html @@ -24,7 +24,7 @@
@@ -50,7 +50,7 @@

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 version is 1.2.0.

+It can be used to write Mesos frameworks in pure JavaScript. The currently supported Mesos version is 1.5.0.

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.

It implements all existing Calls as methods for both the Scheduler and Executor classes, meaning that they can be used without having to write the HTTP communication yourself. Additionally, it exposes all Events for both classes, as definied in the Mesos docs. It also adds some custom events for the Scheduler class for better task handling.

@@ -66,6 +66,7 @@

Installation

You can use mesos-framework in your own pro } });

Basically this is the mechanism to create custom framework logic. Please have a look at the examples folder to see examples for command-based and Docker-based schedulers.

API docs

The API docs can be accessed via API docs hosted on GitHub pages.

+

Coverage reports

The Coverage Reports are hosted on GitHub pages as well.

Scheduler

The Scheduler is the "heart" of a Mesos framework. It is very well possible to create a Mesos framework only by implementing the Scheduler with the standard CommandInfo and ContainerInfo objects.

The option properties you can specify to create a Scheduler are the following:

    @@ -74,6 +75,8 @@

    Scheduler

    The Scheduler is the "heart" of a Me

  • useZk: Should be set to true if you want to use ZooKeeper to persist the task information. Default is false.
  • zkUrl: The ZooKeeper connection url. Default is master.mesos:2181.
  • zkPrefix: The prefix of the ZooKeeper node where the data for this framework shall be stored. Default is /dcos-service-.
  • +
  • user: The system user name to use (must exist on the agents!). Default is root.
  • +
  • role: The Mesos role to use when subscribing to the master. Default is *.
  • frameworkName: The desired framework name (will choose a standard name if not specified). Default is mesos-framework. concatented with a unique UUID.
  • restartStates: An array of TaskState objects which should trigger a restart of a task. For example, regularly finished tasks (in state TASK_FINISHED) are not restarted by default.
  • masterConnectionTimeout: The number of seconds to wait before a connection to the leading Mesos master is considered as timed out (default: 10).
  • @@ -119,20 +122,22 @@

    Events

    Events from Master
    The following events fr

    Events from Scheduler
    The following events from the Scheduler calls are exposed:

    • ready: Is emitted when the scheduler is instantiated and ready to subscribe to the Mesos master. Every scheduler.subscribe() call should be wrapped by an event handle reacting to this event. See the examples.
    • -
    • sent_subscribe: Is emitted when the scheduler has sent the SUBSCRIBE request.
    • -
    • sent_accept: Is emitted when the scheduler has sent an ACCEPT request to accept an offer from the Master.
    • -
    • sent_decline: Is emitted when the scheduler has sent a DECLINE request to decline an offer from the Master.
    • -
    • sent_teardown: Is emitted when the scheduler has sent the TEARDOWN request to stop the framework to the Master.
    • -
    • sent_revive: Is emitted when the scheduler has sent a REVIVE request to the Master to remove any/all filters that it has previously set via ACCEPT or DECLINE calls.
    • -
    • sent_kill: Is emitted when the scheduler has sent a KILL request to the Master to kill a specific task.
    • -
    • sent_acknowledge: Is emitted when the scheduler has sent an ACKNOWLEDGE request to the Master to acknowledge a status update.
    • -
    • sent_shutdown: Is emitted when the scheduler has sent a SHUTDOWN request to the Master to shutdown a specific custom executor.
    • -
    • sent_reconcile: Is emitted when the scheduler has sent a RECONCILE request to the Master to query the status of non-terminal tasks.
    • -
    • sent_message: Is emitted when the scheduler has sent a MESSAGE request to the Master to send arbitrary binary data to the executor.
    • -
    • sent_request: Is emitted when the scheduler has sent a REQUEST request to the Master to request new resources.
    • -
    • sent_supress: Is emitted when the scheduler has sent a SUPPRESS request to the Master to suppress new resource offers.
    • -
    • sent_accept_inverse_offers: Is emitted when the scheduler has sent a ACCEPT_INVERSE_OFFERS request to the Master to accept inverse offers.
    • -
    • sent_decline_inverse_offers: Is emitted when the scheduler has sent a DECLINE_INVERSE_OFFERS request to the Master to decline inverse offers.
    • +
    • sent_subscribe: Is emitted when the scheduler has sent the SUBSCRIBE call.
    • +
    • sent_accept: Is emitted when the scheduler has sent an ACCEPT call to accept an offer from the Master.
    • +
    • sent_decline: Is emitted when the scheduler has sent a DECLINE call to decline an offer from the Master.
    • +
    • sent_teardown: Is emitted when the scheduler has sent the TEARDOWN call to stop the framework to the Master.
    • +
    • sent_revive: Is emitted when the scheduler has sent a REVIVE call to the Master to remove any/all filters that it has previously set via ACCEPT or DECLINE calls.
    • +
    • sent_kill: Is emitted when the scheduler has sent a KILL call to the Master to kill a specific task.
    • +
    • sent_acknowledge: Is emitted when the scheduler has sent an ACKNOWLEDGE call to the Master to acknowledge a status update.
    • +
    • sent_shutdown: Is emitted when the scheduler has sent a SHUTDOWN call to the Master to shutdown a specific custom executor.
    • +
    • sent_reconcile: Is emitted when the scheduler has sent a RECONCILE call to the Master to query the status of non-terminal tasks.
    • +
    • sent_message: Is emitted when the scheduler has sent a MESSAGE call to the Master to send arbitrary binary data to the executor.
    • +
    • sent_request: Is emitted when the scheduler has sent a REQUEST call to the Master to call new resources.
    • +
    • sent_supress: Is emitted when the scheduler has sent a SUPPRESS call to the Master to suppress new resource offers.
    • +
    • sent_accept_inverse_offers: Is emitted when the scheduler has sent a ACCEPT_INVERSE_OFFERS call to the Master to accept inverse offers.
    • +
    • sent_decline_inverse_offers: Is emitted when the scheduler has sent a DECLINE_INVERSE_OFFERS call to the Master to decline inverse offers.
    • +
    • sent_acknowledge_operation_status: Is emitted when the scheduler has sent the ACKNOWLEDGE_OPERATION_STATUS call.
    • +
    • sent_reconcile_operations: Is emitted when the scheduler has sent the RECONCILE_OPERATIONS call.
    • 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.
    • @@ -144,25 +149,18 @@

      Example

      Also, you can have a look at the examples folder var Mesos = require("mesos-framework").Mesos.getMesos(); var scheduler = new Scheduler({ - "masterUrl": "172.17.10.101", // If Mesos DNS is used this would be "leader.mesos", otherwise use the actual IP address of the leading master + "masterUrl": "172.17.11.102", // If Mesos DNS is used this would be "leader.mesos", otherwise use the actual IP address of the leading master "port": 5050, "frameworkName": "My first Command framework", "logging": { - "level": "debug" // Set log Level to debug (default is info) + "level": "debug" }, - "restartStates": ["TASK_FAILED", "TASK_KILLED", "TASK_LOST", "TASK_ERROR", "TASK_FINISHED"], // Overwrite the restartStates (by default, TASK_FINISHED tasks are NOT restarted!) + "restartStates": ["TASK_FAILED", "TASK_KILLED", "TASK_LOST", "TASK_ERROR", "TASK_FINISHED"], "tasks": { "sleepProcesses": { "priority": 1, "instances": 3, - "commandInfo": new Mesos.CommandInfo( - null, // URI - null, // Environment - true, // Is shell? - "sleep 10;", // Command - null, // Arguments - null // User - ), + "commandInfo": new Builder("mesos.CommandInfo").setValue("env && sleep 100").setShell(true), "resources": { "cpus": 0.2, "mem": 128, @@ -225,6 +223,8 @@

      Example

      Also, you can have a look at the examples folder CommandInfo allows schedulers to specify, among other things, a number of resources as URIs. These resources are fetched to a sandbox directory on the slave before attempting to execute the ExecutorInfo command. Several URI schemes are supported, including HTTP, FTP, HDFS, and S3.

      + +

      Alternatively, you can pass the frameworks_home configuration option (defaults to: MESOS_HOME/frameworks) to your mesos-slave daemons when you launch them to specify where your framework executors are stored (e.g. on an NFS mount that is available to all slaves), then use a relative path in CommandInfo.uris, and the slave will prepend the value of frameworks_home to the relative path provided.

      @@ -245,7 +245,7 @@

      Events

      Events from Scheduler
      The following events

    • sent_update: Is emitted when the scheduler has sent the UPDATE request to the agent.
    • sent_message: Is emitted when the scheduler has sent the MESSAGE request to send arbitrary binary data to the agent.
    -

    Mesos

    The module also exposes the Mesos protocol buffer object, which is loaded via protobuf.js. It can be used to create the objects which can be then passed to the scheduler/executor methods.

    +

    Mesos

    Creating objects ("natively" via protobufjs)

    The module also exposes the Mesos protocol buffer object, which is loaded via protobuf.js. It can be used to create the objects which can be then passed to the scheduler/executor methods.

    Example:

    var Mesos = require("mesos-framework").Mesos.getMesos();
     
    @@ -257,7 +257,13 @@ 

    Mesos

    The module also exposes the Mesos protocol buffer object, which "value": "my-task-id" }; -var TaskID = new (Builder.build("mesos.TaskID"))(taskId);

    taskHealthHelper

    This module allows for testing of task health (or any metric available via HTTP, for example cluster state, leader, etc...) and emit a scheduler event so the issue will be handled in code.

    +var TaskID = new (Builder.build("mesos.TaskID"))(taskId);

    Creating objects (via builder pattern)

    You can also create Mesos objects via the builder pattern like this:

    +

    Example:

    +
    var Builder = require("mesos-framework").Builder;
    +
    +var commandInfo = new Builder("mesos.CommandInfo")
    +                    .setValue("env && sleep 100")
    +                    .setShell(true);

    taskHealthHelper

    This module allows for testing of task health (or any metric available via HTTP, for example cluster state, leader, etc...) and emit a scheduler event so the issue will be handled in code.

    The option properties you can specify to create a taskHealthHelper are the following:

    • interval: The time interval between checks, in seconds, can be partial seconds (but not recommended), defaults to 30 seconds.
    • @@ -288,7 +294,7 @@

      Mesos

      The module also exposes the Mesos protocol buffer object, which

      - Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
      diff --git a/docs/mesos.js.html b/docs/mesos.js.html index c0523a0..a841b04 100644 --- a/docs/mesos.js.html +++ b/docs/mesos.js.html @@ -24,7 +24,7 @@
      @@ -109,7 +109,7 @@

      mesos.js


      - Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
      diff --git a/docs/scheduler.js.html b/docs/scheduler.js.html index 847bacd..84632ab 100644 --- a/docs/scheduler.js.html +++ b/docs/scheduler.js.html @@ -24,7 +24,7 @@
      @@ -49,6 +49,7 @@

      scheduler.js

      var helpers = require("./helpers"); var schedulerHandlers = require("./schedulerHandlers"); var mesos = require("./mesos")().getMesos(); +var Builder = require("./builder"); var TaskHelper = require("./taskHelper"); var zookeeper = require("node-zookeeper-client"); @@ -72,6 +73,7 @@

      scheduler.js

      self.options = {}; self.options.frameworkName = (options.frameworkName ? options.frameworkName.replace(/ /g, "-") : "mesos-framework." + uuid.v4()); self.options.user = options.user || "root"; + self.options.role = options.role || "*"; self.options.restartStates = options.restartStates || ["TASK_FAILED", "TASK_LOST", "TASK_ERROR"]; // Task in TASK_FINISHED will NOT be restarted by default! self.options.frameworkFailoverTimeout = options.frameworkFailoverTimeout || 604800; // One week self.options.masterConnectionTimeout = options.masterConnectionTimeout * 1000 || 10000; // Ten seconds @@ -79,7 +81,7 @@

      scheduler.js

      self.options.exponentialBackoffMinimum = options.exponentialBackoffMinimum * 1000 || 1000; // One second self.options.exponentialBackoffMaximum = options.exponentialBackoffMaximum * 1000 || 15000; // 15 seconds self.options.killUnknownTasks = options.killUnknownTasks || false; - self.options.serialNumberedTasks = (options.serialNumberedTasks === false) ? false : true; + self.options.serialNumberedTasks = (options.serialNumberedTasks !== false); // ZooKeeper self.options.useZk = options.useZk || false; @@ -210,13 +212,13 @@

      scheduler.js

      // Set default path for the service self.zkServicePath = self.options.zkPrefix + self.options.frameworkName; - // Create ZK client (getting from options is only to be used for unit tests!) + // Create ZK client (getting from options is only to be used for unit test!) self.zkClient = options.zkClient || zookeeper.createClient(self.options.zkUrl); - // Instantiate TaskHelper (getting from options is only to be used for unit tests!) + // Instantiate TaskHelper (getting from options is only to be used for unit test!) self.taskHelper = options.taskHelper || new TaskHelper(self); - // For unit tests + // For unit test if (options.taskHelper) { self.taskHelper.scheduler = self; } @@ -241,7 +243,7 @@

      scheduler.js

      self.logger.debug("error:" + JSON.stringify(error)); // Check if node doesn't exist yet - if (error.getCode() == zookeeper.Exception.NO_NODE) { + if (error.getCode() === zookeeper.Exception.NO_NODE) { self.logger.debug("Node " + zkPath + " doesn't exist yet. Will be created on framework launch"); @@ -571,31 +573,24 @@

      scheduler.js

      }); // Set the Subscribe object - var Subscribe = new mesos.scheduler.Call.Subscribe( - new mesos.FrameworkInfo( - self.options.user, // user - self.options.frameworkName, // name - self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null, // id -> Use existing frameworkId for reconnections! - self.options.frameworkFailoverTimeout, // failover_timeout -> Set to one week for scheduler failover - null, // checkpoint - null, // role - (process.env.HOST ? process.env.HOST : null), // hostname - null, // principal - (process.env.HOST && process.env.PORT0 ? "http://" + process.env.HOST + ":" + process.env.PORT0 : null), // webui_url - null, // capabilities - null // labels - ) - ); + var Subscribe = new Builder("mesos.scheduler.Call.Subscribe") + .setFrameworkInfo(new Builder("mesos.FrameworkInfo") + .setUser(self.options.user) + .setRole(self.options.role) + .setName(self.options.frameworkName) + .setId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setFailoverTimeout(self.options.frameworkFailoverTimeout) + .setHostname(process.env.HOST ? process.env.HOST : null) + .setWebuiUrl(process.env.HOST && process.env.PORT0 ? "http://" + process.env.HOST + ":" + process.env.PORT0 : null) + ); self.logger.info("SUBSCRIBE: " + JSON.stringify(Subscribe)); // Set the Call object - var Call = helpers.fixEnums( - new mesos.scheduler.Call( - self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null, - "SUBSCRIBE", - Subscribe - ) + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.SUBSCRIBE) + .setSubscribe(Subscribe) ); setTimeout(function () { @@ -610,21 +605,30 @@

      scheduler.js

      /** * Accept incoming offers to actually start the framework scheduler. - * @param {array} offers - The array of {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be accepted. - * @param {array} taskInfos - The array of {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L1452|Operation} objects. - * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L1911|Filters} object. + * @param {array} offersIds - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be accepted. + * @param {array} operations - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1452|Operation} objects. + * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object. */ -Scheduler.prototype.accept = function (offers, operations, filters) { +Scheduler.prototype.accept = function (offersIds, operations, filters) { var self = this; // Set the Accept object - var Accept = new mesos.scheduler.Call.Accept(offers, operations, filters); + var Accept = new Builder("mesos.scheduler.Call.Accept") + .setOfferIds(offersIds) + .setOperations(operations) + .setFilters(filters); self.logger.info("ACCEPT: " + JSON.stringify(Accept)); // Set the Call object - var Call = helpers.fixEnums(new mesos.scheduler.Call(new mesos.FrameworkID(self.frameworkId), "ACCEPT", null, Accept)); + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(new mesos.FrameworkID(self.frameworkId)) + .setType(mesos.scheduler.Call.Type.ACCEPT) + .setAccept(Accept) + ); + + self.logger.debug("Assembled ACCEPT call: " + JSON.stringify(Call)); helpers.doRequest.call(self, Call, function (error, response) { if (error) { @@ -638,18 +642,26 @@

      scheduler.js

      /** * Decline incoming offers because they are not needed by the framework scheduler currently. - * @param {array} offers - The array of {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be declined. - * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L1911|Filters} object. + * @param {array} offersIds - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be declined. + * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object. */ -Scheduler.prototype.decline = function (offers, filters) { +Scheduler.prototype.decline = function (offersIds, filters) { var self = this; // Set the Decline object - var Decline = new mesos.scheduler.Call.Decline(offers, filters); + var Decline = new Builder("mesos.scheduler.Call.Decline") + .setOfferIds(offersIds) + .setFilters(filters); // Set the Call object - var Call = helpers.fixEnums(new mesos.scheduler.Call(new mesos.FrameworkID(self.frameworkId), "DECLINE", null, null, Decline)); + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(new mesos.FrameworkID(self.frameworkId)) + .setType(mesos.scheduler.Call.Type.DECLINE) + .setDecline(Decline) + ); + + self.logger.debug("Assembled DECLINE call: " + JSON.stringify(Call)); helpers.doRequest.call(self, Call, function (error, response) { if (error) { @@ -668,15 +680,15 @@

      scheduler.js

      Scheduler.prototype.teardown = function () { var self = this; + + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.TEARDOWN) + ); + + self.logger.debug("Assembled TEARDOWN call: " + JSON.stringify(Call)); - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "TEARDOWN" - }; - - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -693,14 +705,14 @@

      scheduler.js

      var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "REVIVE" - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.REVIVE) + ); + + self.logger.debug("Assembled REVIVE call: " + JSON.stringify(Call)); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -713,34 +725,30 @@

      scheduler.js

      /** * Kill a specific task. If the scheduler has a custom executor, the kill is forwarded to the executor; it is up to the executor to kill the task and send a TASK_KILLED (or TASK_FAILED) update. * Mesos releases the resources for a task once it receives a terminal update for the task. If the task is unknown to the master, a TASK_LOST will be generated. - * @param {Object} taskId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L71|TaskID} to kill. - * @param {Object} agentId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. + * @param {Object} taskId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L71|TaskID} to kill. + * @param {Object} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. */ Scheduler.prototype.kill = function (taskId, agentId) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "KILL", - "kill": { - "task_id": { - "value": taskId - }, - "agent_id": { - "value": agentId - } - } - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.KILL) + .setKill(new Builder("mesos.scheduler.Call.Kill") + .setTaskId(new Builder("mesos.TaskID").setValue(taskId)) + .setAgentId(new Builder("mesos.AgentID").setValue(agentId)) + ) + ); + + self.logger.debug("Assembled KILL call: " + JSON.stringify(Call)); self.logger.debug("Killing task ID: " + taskId); if (self.options.useZk) self.taskHelper.deleteTask(taskId); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -753,29 +761,25 @@

      scheduler.js

      /** * shutdown a specific custom executor (NOTE: This is a new call that was not present in the old API). When an executor gets a shutdown event, it is expected to kill all its tasks (and send TASK_KILLED updates) and terminate. * If an executor doesn’t terminate within a certain timeout (configurable via “–executor_shutdown_grace_period” agent flag), the agent will forcefully destroy the container (executor and its tasks) and transitions its active tasks to TASK_LOST. - * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. - * @param {string} executorId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L81|ExecutorID} whcih runs the task. + * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. + * @param {string} executorId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L81|ExecutorID} whcih runs the task. */ Scheduler.prototype.shutdown = function (agentId, executorId) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "SHUTDOWN", - "kill": { - "executor_id": { - "value": executorId - }, - "agent_id": { - "value": agentId - } - } - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.SHUTDOWN) + .setShutdown(new Builder("mesos.scheduler.Call.Shutdown") + .setExecutorId(new Builder("mesos.ExecutorID").setValue(executorId)) + .setAgentId(new Builder("mesos.AgentID").setValue(agentId)) + ) + ); - helpers.doRequest.call(self, payload, function (error, response) { + self.logger.debug("Assembled SHUTDOWN call: " + JSON.stringify(Call)); + + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -798,19 +802,19 @@

      scheduler.js

      return; } - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "ACKNOWLEDGE", - "acknowledge": { - "agent_id": update.status.agent_id, - "task_id": update.status.task_id, - "uuid": update.status.uuid - } - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.ACKNOWLEDGE) + .setAcknowledge(new Builder("mesos.scheduler.Call.Acknowledge") + .setTaskId(new Builder("mesos.TaskID").setValue(update.status.task_id)) + .setAgentId(new Builder("mesos.AgentID").setValue(update.status.agent_id)) + .setUuid(update.status.uuid) + ) + ); + + self.logger.debug("Assembled ACKNOWLEDGE call: " + JSON.stringify(Call)); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -823,44 +827,42 @@

      scheduler.js

      /** * query the status of non-terminal tasks. This causes the master to send back UPDATE events for each task in the list. Tasks that are no longer known to Mesos will result in TASK_LOST updates. * If the list of tasks is empty, master will send UPDATE events for all currently known tasks of the framework. - * @param {string} taskId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L71|TaskID} to kill. - * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. + * @param {string} taskId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L71|TaskID} to kill. + * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. */ Scheduler.prototype.reconcile = function (taskId, agentId) { var self = this; - var payload = null; + var Call = null; + if (taskId && agentId) { - payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "RECONCILE", - "reconcile": { - "tasks": [{ - "task_id": { - "value": taskId - }, - "agent_id": { - "value": agentId - } - }] - } - }; + Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.RECONCILE) + .setReconcile(new Builder("mesos.scheduler.Call.Reconcile") + .setTasks(new Builder("mesos.scheduler.Call.Reconcile.Task") + .setTaskId(new Builder("mesos.TaskID").setValue(taskId)) + .setAgentId(new Builder("mesos.AgentID").setValue(agentId) + ) + ) + ) + ); self.logger.debug("Reconciling task ID: " + taskId); } else { - payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "RECONCILE", - "reconcile": { "tasks": []} - }; + Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.RECONCILE) + .setReconcile(new Builder("mesos.scheduler.Call.Reconcile") + .setTasks([]) + ) + ); self.logger.debug("Reconciling all tasks "); } - helpers.doRequest.call(self, payload, function (error, response) { + self.logger.debug("Assembled RECONCILE call: " + JSON.stringify(Call)); + + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -872,31 +874,27 @@

      scheduler.js

      /** * Send arbitrary data to the executor. Note that Mesos neither interprets this data nor makes any guarantees about the delivery of this message to the executor. - * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. - * @param {string} executorId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L81|ExecutorID} which runs the task. + * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. + * @param {string} executorId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L81|ExecutorID} which runs the task. * @param {string} data The string which's raw bytes will be encoded in Base64. */ Scheduler.prototype.message = function (agentId, executorId, data) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "MESSAGE", - "message": { - "agent_id": { - "value": agentId - }, - "executor_id": { - "value": executorId - }, - "data": new Buffer(data).toString('base64') - } - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.MESSAGE) + .setMessage(new Builder("mesos.scheduler.Call.Message") + .setExecutorId(new Builder("mesos.ExecutorID").setValue(executorId)) + .setAgentId(new Builder("mesos.AgentID").setValue(agentId)) + .setData(new Buffer(data).toString("base64")) + ) + ); + + self.logger.debug("Assembled MESSAGE call: " + JSON.stringify(Call)); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -908,21 +906,23 @@

      scheduler.js

      /** * Request resources from the master/allocator. The built-in hierarchical allocator simply ignores this request but other allocators (modules) can interpret this in a customizable fashion. - * @param {array} requests The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L1410|Request} objects which should be sent to the server. + * @param {array} requests The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1410|Request} objects which should be sent to the server. */ Scheduler.prototype.request = function (requests) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "REQUEST", - "requests": requests - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.REQUEST) + .setRequest(new Builder("mesos.scheduler.Call.Request") + .setRequests(requests) + ) + ); - helpers.doRequest.call(self, payload, function (error, response) { + self.logger.debug("Assembled REQUEST call: " + JSON.stringify(Call)); + + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -934,21 +934,23 @@

      scheduler.js

      /** * Suppress offers for the specified roles. If `roles` is empty, the `SUPPRESS` call will suppress offers for all of the roles the framework is currently subscribed to. - * @param {array} roles The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L2696|Role} objects which should be sent to the server. + * @param {array} roles The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2696|Role} objects which should be sent to the server. */ Scheduler.prototype.suppress = function (roles) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "SUPPRESS", - "roles": roles - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.SUPPRESS) + .setSuppress(new Builder("mesos.scheduler.Call.Suppress") + .setRoles(roles) + ) + ); + + self.logger.debug("Assembled SUPPRESS call: " + JSON.stringify(Call)); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -960,23 +962,25 @@

      scheduler.js

      /** * Accepts an inverse offer. Inverse offers should only be accepted if the resources in the offer can be safely evacuated before the provided unavailability. - * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server. - * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server. + * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server. + * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server. */ Scheduler.prototype.acceptInverseOffers = function (inverseOffersIds, filters) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "ACCEPT_INVERSE_OFFERS", - "inverse_offer_ids": inverseOffersIds, - "filters": filters - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.ACCEPT_INVERSE_OFFERS) + .setAcceptInverseOffers(new Builder("mesos.scheduler.Call.AcceptInverseOffers") + .setInverseOfferIds(inverseOffersIds) + .setFilter(filters) + ) + ); + + self.logger.debug("Assembled ACCEPT_INVERSE_OFFERS call: " + JSON.stringify(Call)); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -988,23 +992,25 @@

      scheduler.js

      /** * Declines an inverse offer. Inverse offers should be declined if the resources in the offer might not be safely evacuated before the provided unavailability. - * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server. - * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server. + * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server. + * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server. */ Scheduler.prototype.declineInverseOffers = function (inverseOffersIds, filters) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "DECLINE_INVERSE_OFFERS", - "inverse_offer_ids": inverseOffersIds, - "filters": filters - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.DECLINE_INVERSE_OFFERS) + .setDeclineInverseOffers(new Builder("mesos.scheduler.Call.DeclineInverseOffers") + .setInverseOfferIds(inverseOffersIds) + .setFilter(filters) + ) + ); + + self.logger.debug("Assembled DECLINE_INVERSE_OFFERS call: " + JSON.stringify(Call)); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -1014,6 +1020,68 @@

      scheduler.js

      }; +/** + * Acknowledges the receipt of an operation status update. Schedulers are responsible for explicitly acknowledging the receipt of updates which have the 'UpdateOperationStatus.status().uuid()' field set. Such status updates are retried by the agent or resource provider until they are acknowledged by the scheduler. + * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. + * @param {string} resourceProviderId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L102|ResourceProviderId} + * @param {string} operationId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L111|OperationID} + * @param {string} uuid The uuid of the Operation + */ +Scheduler.prototype.acknowledgeOperationStatus = function (agentId, resourceProviderId, operationId, uuid) { + + var self = this; + + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.ACKNOWLEDGE_OPERATION_STATUS) + .setAcknowledgeOperationStatus(new Builder("mesos.scheduler.Call.AcknowledgeOperationStatus") + .setAgentId(new Builder("mesos.AgentID").setValue(agentId)) + .setResourceProviderId(new Builder("mesos.ResourceProviderId").setValue(resourceProviderId)) + .setOperationId(new Builder("mesos.ResourceProviderId").setValue(operationId)) + .setUuid(uuid) + ) + ); + + self.logger.debug("Assembled ACKNOWLEDGE_OPERATION_STATUS call: " + JSON.stringify(Call)); + + helpers.doRequest.call(self, Call, function (error, response) { + if (error) { + self.emit("error", error.message); + } else { + self.emit("sent_acknowledge_operation_status"); + } + }); + +}; + +/** + * Allows the scheduler to query the status of operations. This causes the master to send back the latest status for each operation in 'operations', if possible. If 'operations' is empty, then the master will send the latest status for each operation currently known. + * @param {array} operations An array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/scheduler/scheduler.proto#L420|Operation} objects to query. + */ +Scheduler.prototype.reconcileOperations = function (operations) { + + var self = this; + + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.RECONCILE_OPERATIONS) + .setReconcileOperations(new Builder("mesos.scheduler.Call.ReconcileOperations") + .setOperations(operations) + ) + ); + + self.logger.debug("Assembled RECONCILE_OPERATIONS call: " + JSON.stringify(Call)); + + helpers.doRequest.call(self, Call, function (error, response) { + if (error) { + self.emit("error", error.message); + } else { + self.emit("sent_reconcile_operations"); + } + }); + +}; + /** * Get the running tasks of this framework scheduler. * @returns {Array} The running task array. @@ -1090,7 +1158,7 @@

      scheduler.js


      - Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
      diff --git a/docs/taskHealthHelper.js.html b/docs/taskHealthHelper.js.html index a92a042..db5f55d 100644 --- a/docs/taskHealthHelper.js.html +++ b/docs/taskHealthHelper.js.html @@ -24,7 +24,7 @@
      @@ -176,8 +176,6 @@

      taskHealthHelper.js

      TaskHealthHelper.prototype.setProperties = function (task, value) { var self = this; self.options.additionalProperties.forEach(function (property) { - //self.logger.debug("Setting " + property.name + " to " + value); - // If healthy or setting unhealthy if (value || property.setUnhealthy) { var propertyValue = value; @@ -196,7 +194,7 @@

      taskHealthHelper.js

      clearInterval(self.interval); self.interval = null; } -} +}; TaskHealthHelper.prototype.setupHealthCheck = function () { var self = this; @@ -205,7 +203,8 @@

      taskHealthHelper.js

      self.interval = setInterval(self.checkRunningInstances, self.options.interval * 1000); }; -module.exports = TaskHealthHelper; +module.exports = TaskHealthHelper; +
@@ -217,7 +216,7 @@

taskHealthHelper.js


- Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/taskHelper.js.html b/docs/taskHelper.js.html index e7ab8d7..1711fcc 100644 --- a/docs/taskHelper.js.html +++ b/docs/taskHelper.js.html @@ -24,7 +24,7 @@
@@ -41,7 +41,9 @@

taskHelper.js

"use strict";
 
+var lib = require("requirefrom")("lib");
 var Mesos = require("./mesos")().getMesos();
+var Builder = lib("builder");
 
 /**
  * Represents a TaskHelper object
@@ -80,7 +82,7 @@ 

taskHelper.js

} childStates[child] = {'loaded': false}; 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"); } @@ -109,14 +111,9 @@

taskHelper.js

pendingTask.taskId = task.taskId; if (task.commandInfo && task.commandInfo.environment && task.commandInfo.environment.variables && task.commandInfo.environment.variables.length > 0) { if (!pendingTask.commandInfo) { - pendingTask.commandInfo = new Mesos.CommandInfo( - null, // URI - new Mesos.Environment([]), // Environment - false, // Is shell? - null, // Command - null, // Arguments - null // User - ); + pendingTask.commandInfo = new Builder("mesos.CommandInfo") + .setEnvironment(new Mesos.Environment([])) + .setShell(false); } if (!pendingTask.commandInfo.environment) { pendingTask.commandInfo.environment = new Mesos.Environment([]); @@ -205,7 +202,7 @@

taskHelper.js


- Generated by JSDoc 3.4.3 on Thu Jun 22 2017 13:08:19 GMT+0200 (CEST) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme.
From 5d1499b2970e0ddab77d68384cee570dea204f6d Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sun, 4 Mar 2018 17:23:56 +0100 Subject: [PATCH 09/13] Remove gulp and its dependencies, use nyc instead for coverage --- .travis.yml | 2 +- gulpfile.js | 83 - package-lock.json | 4275 ++++++++++++++++++--------------------------- package.json | 19 +- 4 files changed, 1714 insertions(+), 2665 deletions(-) delete mode 100644 gulpfile.js diff --git a/.travis.yml b/.travis.yml index cf5b9af..bc862e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ script: - - "npm run test-ci" + - "npm run test" language: node_js diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 4179296..0000000 --- a/gulpfile.js +++ /dev/null @@ -1,83 +0,0 @@ -"use strict"; - -var gulp = require("gulp"); -var runSequence = require("run-sequence"); -var istanbul = require("gulp-istanbul"); -var mocha = require("gulp-mocha"); -var chalk = require("chalk"); -var rimraf = require("rimraf"); - -var chai = require("chai"); -global.expect = chai.expect; - -var paths = { - libJsFiles: "./lib/*.js", - testFiles: "./tests/**/*.js", - gulpfile: "./gulpfile.js" -}; - -gulp.task("dev", ["watch", "validate"]); - -gulp.task("watch", function () { - - gulp.watch([ - paths.libJsFiles, - paths.testFiles, - paths.gulpfile - ], [ - "validate" - ]); - -}); - -gulp.task("validate", function (done) { - runSequence("test", done); -}); - -gulp.task("test", ["clean"], function (done) { - - var coverageVariable = "$$cov_" + new Date().getTime() + "$$"; - - gulp.src(paths.libJsFiles) - .pipe(istanbul({ - coverageVariable: coverageVariable - })) - .pipe(istanbul.hookRequire()) - .on("finish", function () { - - gulp.src(paths.testFiles) - .pipe(mocha()) - .on("error", function (err) { - console.error(String(err)); - console.error(chalk.bold.bgRed(" TESTS FAILED ")); - done(new Error(" TESTS FAILED ")); - }) - .pipe(istanbul.writeReports({ - reporters: ["lcov"], - coverageVariable: coverageVariable - })) - .on("end", done); - - }); - -}); - -gulp.task("test-without-coverage", function () { - - return gulp.src(paths.testFiles) - .pipe(mocha()) - .on("error", function () { - console.log(chalk.bold.bgRed(" TESTS FAILED ")); - }); - -}); - -gulp.task("clean", ["clean-coverage"]); - -gulp.task("clean-coverage", function (done) { - rimraf("./coverage", done); -}); - -gulp.task("ci", function (done) { - runSequence("test-without-coverage", done); -}); diff --git a/package-lock.json b/package-lock.json index c8921df..d4f21b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,46 +4,12 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, "always-error": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/always-error/-/always-error-1.0.0.tgz", "integrity": "sha1-lchAQs+obzjIbKbCzELAoBA0QbI=", "dev": true }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, "ansi-align": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", @@ -86,15 +52,6 @@ } } }, - "ansi-cyan": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", - "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, "ansi-escapes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", @@ -110,15 +67,6 @@ "ansi-wrap": "0.1.0" } }, - "ansi-red": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", - "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -136,51 +84,12 @@ "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "1.0.3" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, "array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", "dev": true }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, "array-filter": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", @@ -199,12 +108,6 @@ "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", "dev": true }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -220,12 +123,6 @@ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", "dev": true }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -253,23 +150,11 @@ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, "async": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" }, - "atob": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", - "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", - "dev": true - }, "babylon": { "version": "7.0.0-beta.19", "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", @@ -308,32 +193,6 @@ } } }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.1", - "pascalcase": "0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "1.0.2" - } - } - } - }, "beeper": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", @@ -444,46 +303,6 @@ "concat-map": "0.0.1" } }, - "braces": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", - "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", - "dev": true, - "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "kind-of": "6.0.2", - "repeat-element": "1.1.2", - "snapdragon": "0.8.1", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.2" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "1.0.2" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, "browser-stdout": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", @@ -504,23 +323,6 @@ "long": "3.2.0" } }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "1.0.0", - "component-emitter": "1.2.1", - "get-value": "2.0.6", - "has-value": "1.0.0", - "isobject": "3.0.1", - "set-value": "2.0.0", - "to-object-path": "0.3.0", - "union-value": "1.0.0", - "unset-value": "1.0.0" - } - }, "camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", @@ -541,26 +343,6 @@ "underscore-contrib": "0.3.0" } }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "optional": true, - "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" - }, - "dependencies": { - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, - "optional": true - } - } - }, "chai": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", @@ -629,86 +411,6 @@ "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", "dev": true }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, "cli-boxes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", @@ -766,16 +468,6 @@ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" - } - }, "color-convert": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", @@ -816,12 +508,6 @@ "graceful-readlink": "1.0.1" } }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -849,12 +535,6 @@ } } }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -944,38 +624,17 @@ "integrity": "sha1-SzHc5KISGnczY4RXTYk/vtX7KT0=", "dev": true }, - "dargs": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", - "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=", - "dev": true - }, "dateformat": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", "dev": true }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, "deep-eql": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", @@ -999,43 +658,6 @@ "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", "dev": true }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "1.0.3" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" - } - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, "diff": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", @@ -1084,26 +706,6 @@ "os-family": "1.0.0" } }, - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "1.3.3" - }, - "dependencies": { - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - } - } - }, "error-ex": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", @@ -1119,264 +721,36 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "requires": { - "esprima": "2.7.3", - "estraverse": "1.9.3", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.2.0" - }, - "dependencies": { - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", "dev": true }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" }, - "execa": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.6.3.tgz", - "integrity": "sha1-V7aaWU8IF1nGnlNw8NF7nLEWWP4=", + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" } }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.1", - "to-regex": "3.0.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1" - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.1", - "to-regex": "3.0.2" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "1.0.2" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" - }, - "fancy-log": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true, - "requires": { - "ansi-gray": "0.1.1", - "color-support": "1.1.3", - "time-stamp": "1.1.0" - } - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" }, "dependencies": { "object-assign": { @@ -1387,35 +761,6 @@ } } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -1425,58 +770,6 @@ "locate-path": "2.0.0" } }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "1.0.0", - "is-glob": "3.1.0", - "micromatch": "3.1.9", - "resolve-dir": "1.0.1" - } - }, - "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true, - "requires": { - "expand-tilde": "2.0.2", - "is-plain-object": "2.0.4", - "object.defaults": "1.1.0", - "object.pick": "1.3.0", - "parse-filepath": "1.0.2" - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, "formatio": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", @@ -1486,15 +779,6 @@ "samsam": "1.1.2" } }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "0.2.2" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1541,27 +825,12 @@ "inherits": "2.0.3" } }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "0.1.0" - } - }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, "ggit": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/ggit/-/ggit-2.4.2.tgz", @@ -1639,83 +908,6 @@ "path-is-absolute": "1.0.1" } }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" - }, - "dependencies": { - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0" - } - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "0.5.2" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "0.1.1" - } - }, "global-dirs": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", @@ -1725,30 +917,6 @@ "ini": "1.3.5" } }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "1.0.2", - "is-windows": "1.0.2", - "resolve-dir": "1.0.1" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "2.0.2", - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", - "is-windows": "1.0.2", - "which": "1.3.0" - } - }, "globby": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-4.1.0.tgz", @@ -1790,58 +958,6 @@ } } }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "3.1.21", - "lodash": "1.0.2", - "minimatch": "0.2.14" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "1.2.3", - "inherits": "1.0.2", - "minimatch": "0.2.14" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - } - } - }, "glogg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", @@ -1870,15 +986,6 @@ "url-parse-lax": "1.0.0" } }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "1.1.1" - } - }, "graceful-readlink": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", @@ -1891,72 +998,15 @@ "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", "dev": true }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "deprecated": "0.0.1", - "gulp-util": "3.0.8", - "interpret": "1.1.0", - "liftoff": "2.5.0", - "minimist": "1.2.0", - "orchestrator": "0.3.8", - "pretty-hrtime": "1.0.3", - "semver": "4.3.6", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "vinyl-fs": "0.3.14" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "gulp-istanbul": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gulp-istanbul/-/gulp-istanbul-1.1.3.tgz", - "integrity": "sha512-uMLSdqPDnBAV/B9rNyOgVMgrVC1tPbe+5GH6P13UOyxbRDT/w4sKYHWftPMA8j9om+NFvfeRlqpDXL2fixFWNA==", - "dev": true, - "requires": { - "istanbul": "0.4.5", - "istanbul-threshold-checker": "0.2.1", - "lodash": "4.17.5", - "plugin-error": "0.1.2", - "through2": "2.0.3", - "vinyl-sourcemaps-apply": "0.2.1" - } - }, - "gulp-mocha": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/gulp-mocha/-/gulp-mocha-4.3.1.tgz", - "integrity": "sha1-d5ULQ7z/gWWVdnwHNOD9p9Fz3Nk=", - "dev": true, - "requires": { - "dargs": "5.1.0", - "execa": "0.6.3", - "gulp-util": "3.0.8", - "mocha": "3.5.3", - "npm-run-path": "2.0.2", - "through2": "2.0.3" - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", "chalk": "1.1.3", "dateformat": "2.2.0", "fancy-log": "1.3.2", @@ -1991,35 +1041,6 @@ "glogg": "1.0.1" } }, - "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "dev": true, - "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.8.29" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -2044,53 +1065,12 @@ "sparkles": "1.0.0" } }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "1.0.0" - } - }, "hosted-git-info": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", @@ -2150,48 +1130,17 @@ "through": "2.3.8" } }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "1.0.0", - "is-windows": "1.0.2" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, "is-builtin-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", @@ -2201,38 +1150,6 @@ "builtin-modules": "1.1.1" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -2241,15 +1158,6 @@ "number-is-nan": "1.0.1" } }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - }, "is-installed-globally": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", @@ -2266,49 +1174,12 @@ "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", "dev": true }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, - "is-odd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", - "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", - "dev": true, - "requires": { - "is-number": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, "is-path-inside": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", @@ -2318,30 +1189,12 @@ "path-is-inside": "1.0.2" } }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, "is-redirect": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", "dev": true }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "1.0.0" - } - }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", @@ -2354,27 +1207,12 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "0.1.2" - } - }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -2387,103 +1225,11 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "requires": { - "abbrev": "1.0.9", - "async": "1.5.2", - "escodegen": "1.8.1", - "esprima": "2.7.3", - "glob": "5.0.15", - "handlebars": "4.0.11", - "js-yaml": "3.10.0", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "once": "1.4.0", - "resolve": "1.1.7", - "supports-color": "3.2.3", - "which": "1.3.0", - "wordwrap": "1.0.0" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "istanbul-threshold-checker": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/istanbul-threshold-checker/-/istanbul-threshold-checker-0.2.1.tgz", - "integrity": "sha1-xdyU6PLMXNP/0zVFL4S1U8QkgzE=", - "dev": true, - "requires": { - "istanbul": "0.4.5", - "lodash": "4.17.5" - } - }, - "js-yaml": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", - "dev": true, - "requires": { - "argparse": "1.0.10", - "esprima": "4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true - } - } - }, "js2xmlparser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz", @@ -2533,12 +1279,6 @@ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, "klaw": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz", @@ -2571,15 +1311,6 @@ "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", "dev": true }, - "lazy-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", - "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", - "dev": true, - "requires": { - "set-getter": "0.1.0" - } - }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", @@ -2588,32 +1319,6 @@ "invert-kv": "1.0.0" } }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" - } - }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true, - "requires": { - "extend": "3.0.1", - "findup-sync": "2.0.0", - "fined": "1.1.0", - "flagged-respawn": "1.0.0", - "is-plain-object": "2.0.4", - "object.map": "1.0.1", - "rechoir": "0.6.2", - "resolve": "1.5.0" - } - }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -2838,24 +1543,12 @@ "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, "lowercase-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", "dev": true }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, "make-dir": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", @@ -2865,68 +1558,12 @@ "pify": "3.0.0" } }, - "make-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz", - "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "1.0.1" - } - }, "marked": { "version": "0.3.17", "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.17.tgz", "integrity": "sha512-+AKbNsjZl6jFfLPwHhWmGTqE009wTKn3RTmn9K8oUKHrX/abPJjtcRtXpYB/FFrwPJRUA86LX/de3T0knkPCmQ==", "dev": true }, - "micromatch": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.9.tgz", - "integrity": "sha512-SlIz6sv5UPaAVVFRKodKjCg48EbNoIhgetzfK/Cy0v5U52Z6zB136M8tp0UC9jM53LYbmIRihJszvvqpKkfm9g==", - "dev": true, - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.1", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.9", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.1", - "to-regex": "3.0.2" - } - }, "minami": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/minami/-/minami-1.2.3.tgz", @@ -2946,27 +1583,6 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, - "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -3077,32 +1693,6 @@ "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", "dev": true }, - "nanomatch": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", - "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", - "dev": true, - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "fragment-cache": "0.2.1", - "is-odd": "2.0.0", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.1", - "to-regex": "3.0.2" - } - }, - "natives": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz", - "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==", - "dev": true - }, "node-emoji": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.8.1.tgz", @@ -3121,15 +1711,6 @@ "underscore": "1.4.4" } }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1.0.9" - } - }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -3448,216 +2029,1665 @@ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "nyc": { + "version": "11.4.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-11.4.1.tgz", + "integrity": "sha512-5eCZpvaksFVjP2rt1r60cfXmt3MUtsQDw8bAzNqNEr4WLvUMLgiVENMf/B9bE9YAX0mGVvaGA3v9IS9ekNqB1Q==", "dev": true, "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" + "archy": "1.0.0", + "arrify": "1.0.1", + "caching-transform": "1.0.1", + "convert-source-map": "1.5.1", + "debug-log": "1.0.1", + "default-require-extensions": "1.0.0", + "find-cache-dir": "0.1.1", + "find-up": "2.1.0", + "foreground-child": "1.5.6", + "glob": "7.1.2", + "istanbul-lib-coverage": "1.1.1", + "istanbul-lib-hook": "1.1.0", + "istanbul-lib-instrument": "1.9.1", + "istanbul-lib-report": "1.1.2", + "istanbul-lib-source-maps": "1.2.2", + "istanbul-reports": "1.1.3", + "md5-hex": "1.3.0", + "merge-source-map": "1.0.4", + "micromatch": "2.3.11", + "mkdirp": "0.5.1", + "resolve-from": "2.0.0", + "rimraf": "2.6.2", + "signal-exit": "3.0.2", + "spawn-wrap": "1.4.2", + "test-exclude": "4.1.1", + "yargs": "10.0.3", + "yargs-parser": "8.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "align-text": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true, + "dev": true + }, + "append-transform": { + "version": "0.4.0", + "bundled": true, "dev": true, "requires": { - "is-descriptor": "0.1.6" + "default-require-extensions": "1.0.0" } }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "archy": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "bundled": true, "dev": true, "requires": { - "kind-of": "3.2.2" + "arr-flatten": "1.1.0" } }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "arr-flatten": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "arrify": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "async": { + "version": "1.5.2", + "bundled": true, + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "bundled": true, "dev": true, "requires": { - "kind-of": "3.2.2" + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-generator": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.4", + "source-map": "0.5.7", + "trim-right": "1.0.1" } }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "babel-messages": { + "version": "6.23.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "bundled": true, + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "bundled": true, + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "caching-transform": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "md5-hex": "1.3.0", + "mkdirp": "0.5.1", + "write-file-atomic": "1.3.4" + } + }, + "camelcase": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cliui": { + "version": "2.1.0", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" }, "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "wordwrap": { + "version": "0.0.2", + "bundled": true, + "dev": true, + "optional": true } } }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "commondir": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "bundled": true, + "dev": true + }, + "core-js": { + "version": "2.5.3", + "bundled": true, + "dev": true + }, + "cross-spawn": { + "version": "4.0.2", + "bundled": true, "dev": true, "requires": { - "is-buffer": "1.1.6" + "lru-cache": "4.1.1", + "which": "1.3.0" } - } - } - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "1.0.1", - "array-slice": "1.1.0", - "for-own": "1.0.0", - "isobject": "3.0.1" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "1.0.0", - "make-iterator": "1.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.3" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-log": { + "version": "1.0.1", + "bundled": true, "dev": true - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" - } - }, - "optjs": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", - "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" - }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "requires": { - "end-of-stream": "0.1.5", - "sequencify": "0.0.7", - "stream-consume": "0.1.1" - } - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, - "os-family": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/os-family/-/os-family-1.0.0.tgz", - "integrity": "sha1-0SMIxCSjYwKhwQapUoe73VyiR38=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "requires": { - "lcid": "1.0.0" - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "1.2.0", + }, + "decamelize": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "default-require-extensions": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "strip-bom": "2.0.0" + } + }, + "detect-indent": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true, + "dev": true + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + } + } + }, + "expand-brackets": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "bundled": true, + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extglob": { + "version": "0.3.2", + "bundled": true, + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "bundled": true, + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-cache-dir": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "requires": { + "commondir": "1.0.1", + "mkdirp": "0.5.1", + "pkg-dir": "1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "for-own": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreground-child": { + "version": "1.5.6", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "4.0.2", + "signal-exit": "3.0.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "get-caller-file": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "bundled": true, + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "9.18.0", + "bundled": true, + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "handlebars": { + "version": "4.0.11", + "bundled": true, + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "bundled": true, + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "hosted-git-info": { + "version": "2.5.0", + "bundled": true, + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true, + "dev": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "invariant": { + "version": "2.2.2", + "bundled": true, + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "bundled": true, + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "bundled": true, + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "isobject": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "istanbul-lib-coverage": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "append-transform": "0.4.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.9.1", + "bundled": true, + "dev": true, + "requires": { + "babel-generator": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "istanbul-lib-coverage": "1.1.1", + "semver": "5.4.1" + } + }, + "istanbul-lib-report": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "istanbul-lib-coverage": "1.1.1", + "mkdirp": "0.5.1", + "path-parse": "1.0.5", + "supports-color": "3.2.3" + }, + "dependencies": { + "supports-color": { + "version": "3.2.3", + "bundled": true, + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.2", + "bundled": true, + "dev": true, + "requires": { + "debug": "3.1.0", + "istanbul-lib-coverage": "1.1.1", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "source-map": "0.5.7" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "istanbul-reports": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "handlebars": "4.0.11" + } + }, + "js-tokens": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "jsesc": { + "version": "1.3.0", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "lazy-cache": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "optional": true + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "bundled": true, + "dev": true + } + } + }, + "lodash": { + "version": "4.17.4", + "bundled": true, + "dev": true + }, + "longest": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "lru-cache": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "md5-hex": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "md5-o-matic": "0.1.1" + } + }, + "md5-o-matic": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "merge-source-map": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "micromatch": { + "version": "2.3.11", + "bundled": true, + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mimic-fn": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "p-limit": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-limit": "1.1.0" + } + }, + "parse-glob": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-exists": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "path-type": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true, + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "bundled": true, + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "find-up": "1.1.2" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + } + } + }, + "preserve": { + "version": "0.2.0", + "bundled": true, + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "read-pkg": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + } + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "bundled": true, + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "bundled": true, + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "bundled": true, + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "bundled": true, + "dev": true + }, + "repeating": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "resolve-from": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "right-align": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "semver": { + "version": "5.4.1", + "bundled": true, + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "slide": { + "version": "1.1.6", + "bundled": true, + "dev": true + }, + "source-map": { + "version": "0.5.7", + "bundled": true, + "dev": true + }, + "spawn-wrap": { + "version": "1.4.2", + "bundled": true, + "dev": true, + "requires": { + "foreground-child": "1.5.6", + "mkdirp": "0.5.1", + "os-homedir": "1.0.2", + "rimraf": "2.6.2", + "signal-exit": "3.0.2", + "which": "1.3.0" + } + }, + "spdx-correct": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "bundled": true, + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "bundled": true, + "dev": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "test-exclude": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "requires": { + "arrify": "1.0.1", + "micromatch": "2.3.11", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "bundled": true, + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "yargs": { + "version": "3.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "which": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "window-size": { + "version": "0.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.3", + "bundled": true, + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "write-file-atomic": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + }, + "y18n": { + "version": "3.2.1", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true, + "dev": true + }, + "yargs": { + "version": "10.0.3", + "bundled": true, + "dev": true, + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "8.0.0" + }, + "dependencies": { + "cliui": { + "version": "3.2.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + } + } + }, + "yargs-parser": { + "version": "8.0.0", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "bundled": true, + "dev": true + } + } + } + } + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, + "os-family": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/os-family/-/os-family-1.0.0.tgz", + "integrity": "sha1-0SMIxCSjYwKhwQapUoe73VyiR38=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", "dev": true, @@ -3700,17 +3730,6 @@ } } }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "1.0.0", - "map-cache": "0.2.2", - "path-root": "0.1.1" - } - }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -3720,18 +3739,6 @@ "error-ex": "1.3.1" } }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -3755,27 +3762,6 @@ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "0.1.2" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", @@ -3825,64 +3811,12 @@ "pkgd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/pkgd/-/pkgd-1.1.2.tgz", - "integrity": "sha1-aaumxykr0s8Dun8+LqqBydOj5Gk=", - "dev": true, - "requires": { - "fstream-npm": "1.2.1", - "normalize-path": "2.1.1", - "pinkie-promise": "2.0.1" - } - }, - "plugin-error": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", - "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", - "dev": true, - "requires": { - "ansi-cyan": "0.1.1", - "ansi-red": "0.1.1", - "arr-diff": "1.1.0", - "arr-union": "2.1.0", - "extend-shallow": "1.1.4" - }, - "dependencies": { - "arr-diff": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", - "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", - "dev": true, - "requires": { - "arr-flatten": "1.1.0", - "array-slice": "0.2.3" - } - }, - "arr-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", - "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", - "dev": true - }, - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "extend-shallow": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", - "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", - "dev": true, - "requires": { - "kind-of": "1.1.0" - } - }, - "kind-of": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", - "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", - "dev": true - } + "integrity": "sha1-aaumxykr0s8Dun8+LqqBydOj5Gk=", + "dev": true, + "requires": { + "fstream-npm": "1.2.1", + "normalize-path": "2.1.1", + "pinkie-promise": "2.0.1" } }, "pluralize": { @@ -3897,30 +3831,12 @@ "integrity": "sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M=", "dev": true }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, "prepend-http": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -4060,25 +3976,6 @@ "mute-stream": "0.0.5" } }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "1.5.0" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "3.0.2", - "safe-regex": "1.1.0" - } - }, "registry-auth-token": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", @@ -4104,18 +4001,6 @@ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", "dev": true }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, "replace-ext": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", @@ -4144,31 +4029,6 @@ } } }, - "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "2.0.2", - "global-modules": "1.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", @@ -4179,22 +4039,6 @@ "onetime": "1.1.0" } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "optional": true, - "requires": { - "align-text": "0.1.4" - } - }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -4235,15 +4079,6 @@ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "dev": true }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "0.1.15" - } - }, "samsam": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", @@ -4273,44 +4108,6 @@ } } }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true - }, - "set-getter": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", - "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", - "dev": true, - "requires": { - "to-object-path": "0.3.0" - } - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -4338,12 +4135,6 @@ "jsonify": "0.0.0" } }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -4362,308 +4153,49 @@ "util": "0.10.3" } }, - "snapdragon": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=", - "dev": true, - "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.1", - "use": "2.0.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "1.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", - "dev": true, - "requires": { - "atob": "2.0.3", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, "sparkles": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", - "dev": true - }, - "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true, - "requires": { - "spdx-expression-parse": "3.0.0", - "spdx-license-ids": "3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "2.1.0", - "spdx-license-ids": "3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "3.0.2" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" } }, - "stream-consume": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", "dev": true }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -4688,16 +4220,6 @@ "ansi-regex": "2.1.1" } }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" - } - }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -4796,15 +4318,6 @@ } } }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, "time-stamp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", @@ -4817,136 +4330,12 @@ "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", "dev": true }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "regex-not": "1.0.2", - "safe-regex": "1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" - } - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "1.1.2" - } - }, "type-detect": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", "dev": true }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "optional": true, - "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, - "optional": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "optional": true, - "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, - "optional": true - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, - "optional": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "optional": true, - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } - } - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, "underscore": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", @@ -4969,47 +4358,6 @@ } } }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" - } - } - } - }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, "unique-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", @@ -5019,52 +4367,6 @@ "crypto-random-string": "1.0.0" } }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, "unzip-response": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", @@ -5125,12 +4427,6 @@ } } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, "url-parse-lax": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", @@ -5140,91 +4436,6 @@ "prepend-http": "1.0.4" } }, - "use": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", - "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=", - "dev": true, - "requires": { - "define-property": "0.2.5", - "isobject": "3.0.1", - "lazy-cache": "2.0.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, "util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", @@ -5253,15 +4464,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "1.1.1" - } - }, "validate-npm-package-license": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", @@ -5283,71 +4485,6 @@ "replace-ext": "0.0.1" } }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "1.0.3", - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "0.5.7" - } - }, "weak-map": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz", @@ -5438,12 +4575,6 @@ "mkdirp": "0.5.1" } }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", diff --git a/package.json b/package.json index 4dfb06a..c2da499 100644 --- a/package.json +++ b/package.json @@ -14,14 +14,19 @@ ], "main": "index.js", "scripts": { - "test": "./node_modules/.bin/gulp test", - "test-ci": "./node_modules/.bin/gulp ci", - "generate-docs": "node_modules/.bin/jsdoc --configure .jsdoc.json --verbose", + "docs": "jsdoc --configure .jsdoc.json --verbose", "publish-please": "publish-please", - "prepublish": "publish-please guard" + "prepublishOnly": "publish-please guard", + "test": "nyc mocha" }, "author": "TobiLG", "license": "Apache-2.0", + "nyc": { + "reporter": [ + "html" + ], + "report-dir": "./docs/coverage" + }, "dependencies": { "lodash": "^4.17.5", "node-zookeeper-client": "^0.2.2", @@ -35,17 +40,13 @@ "chai": "^3.5.0", "chai-as-promised": "^6.0.0", "chalk": "~1.1.3", - "gulp": "~3.9.1", - "gulp-istanbul": "~1.1.2", - "gulp-mocha": "~4.3.1", - "istanbul": "0.4.5", "jsdoc": "^3.5.5", "minami": "^1.2.3", "mocha": "^3.4.2", "mock-req": "^0.2.0", "mock-res": "^0.3.3", + "nyc": "^11.4.1", "publish-please": "~2.3.1", - "rimraf": "~2.6.1", "run-sequence": "~1.2.2", "sinon": "^1.17.7" }, From c68567b6a5fb1404a873d0a823e5c93d508a69b0 Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sun, 4 Mar 2018 17:24:19 +0100 Subject: [PATCH 10/13] Update readme --- README.md | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 7f96aba..72e638f 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,16 @@ It can be used to write Mesos frameworks in pure JavaScript. The currently suppo You can use `mesos-framework` in your own projects by running npm i mesos-framework --save + +## Local test environment + +`docker-compose` can be used for setting up a local test environment. Just run + +```bash +$ docker-compose up -d +``` + +in the base directory of this project. ## Documentation @@ -39,6 +49,10 @@ Basically this is the mechanism to create custom framework logic. Please have a The API docs can be accessed via [API docs](http://tobilg.github.io/mesos-framework/) hosted on GitHub pages. +#### Coverage reports + +The [Coverage Reports](http://tobilg.github.io/mesos-framework/coverage/) are hosted on GitHub pages as well. + ### Scheduler The `Scheduler` is the "heart" of a Mesos framework. It is very well possible to create a Mesos framework only by implementing the `Scheduler` with the standard [CommandInfo](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L397) and [ContainerInfo](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L1744) objects. @@ -50,6 +64,8 @@ The option properties you can specify to create a `Scheduler` are the following: * `useZk`: Should be set to `true` if you want to use ZooKeeper to persist the task information. Default is `false`. * `zkUrl`: The ZooKeeper connection url. Default is `master.mesos:2181`. * `zkPrefix`: The prefix of the ZooKeeper node where the data for this framework shall be stored. Default is `/dcos-service-`. +* `user`: The system user name to use (must exist on the agents!). Default is `root`. +* `role`: The Mesos role to use when subscribing to the master. Default is `*`. * `frameworkName`: The desired framework name (will choose a standard name if not specified). Default is `mesos-framework.` concatented with a unique UUID. * `restartStates`: An array of [TaskState](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L1671) objects which should trigger a restart of a task. For example, regularly finished tasks (in state `TASK_FINISHED`) are not restarted by default. * `masterConnectionTimeout`: The number of seconds to wait before a connection to the leading Mesos master is considered as timed out (default: `10`). @@ -107,20 +123,22 @@ The following events from the leading Mesos master are exposed: The following events from the Scheduler calls are exposed: * `ready`: Is emitted when the scheduler is instantiated and ready to subscribe to the Mesos master. Every `scheduler.subscribe()` call should be wrapped by an event handle reacting to this event. See the examples. -* `sent_subscribe`: Is emitted when the scheduler has sent the `SUBSCRIBE` request. -* `sent_accept`: Is emitted when the scheduler has sent an `ACCEPT` request to accept an offer from the Master. -* `sent_decline`: Is emitted when the scheduler has sent a `DECLINE` request to decline an offer from the Master. -* `sent_teardown`: Is emitted when the scheduler has sent the `TEARDOWN` request to stop the framework to the Master. -* `sent_revive`: Is emitted when the scheduler has sent a `REVIVE` request to the Master to remove any/all filters that it has previously set via `ACCEPT` or `DECLINE` calls. -* `sent_kill`: Is emitted when the scheduler has sent a `KILL` request to the Master to kill a specific task. -* `sent_acknowledge`: Is emitted when the scheduler has sent an `ACKNOWLEDGE` request to the Master to acknowledge a status update. -* `sent_shutdown`: Is emitted when the scheduler has sent a `SHUTDOWN` request to the Master to shutdown a specific custom executor. -* `sent_reconcile`: Is emitted when the scheduler has sent a `RECONCILE` request to the Master to query the status of non-terminal tasks. -* `sent_message`: Is emitted when the scheduler has sent a `MESSAGE` request to the Master to send arbitrary binary data to the executor. -* `sent_request`: Is emitted when the scheduler has sent a `REQUEST` request to the Master to request new resources. -* `sent_supress`: Is emitted when the scheduler has sent a `SUPPRESS` request to the Master to suppress new resource offers. -* `sent_accept_inverse_offers`: Is emitted when the scheduler has sent a `ACCEPT_INVERSE_OFFERS` request to the Master to accept inverse offers. -* `sent_decline_inverse_offers`: Is emitted when the scheduler has sent a `DECLINE_INVERSE_OFFERS` request to the Master to decline inverse offers. +* `sent_subscribe`: Is emitted when the scheduler has sent the `SUBSCRIBE` call. +* `sent_accept`: Is emitted when the scheduler has sent an `ACCEPT` call to accept an offer from the Master. +* `sent_decline`: Is emitted when the scheduler has sent a `DECLINE` call to decline an offer from the Master. +* `sent_teardown`: Is emitted when the scheduler has sent the `TEARDOWN` call to stop the framework to the Master. +* `sent_revive`: Is emitted when the scheduler has sent a `REVIVE` call to the Master to remove any/all filters that it has previously set via `ACCEPT` or `DECLINE` calls. +* `sent_kill`: Is emitted when the scheduler has sent a `KILL` call to the Master to kill a specific task. +* `sent_acknowledge`: Is emitted when the scheduler has sent an `ACKNOWLEDGE` call to the Master to acknowledge a status update. +* `sent_shutdown`: Is emitted when the scheduler has sent a `SHUTDOWN` call to the Master to shutdown a specific custom executor. +* `sent_reconcile`: Is emitted when the scheduler has sent a `RECONCILE` call to the Master to query the status of non-terminal tasks. +* `sent_message`: Is emitted when the scheduler has sent a `MESSAGE` call to the Master to send arbitrary binary data to the executor. +* `sent_request`: Is emitted when the scheduler has sent a `REQUEST` call to the Master to call new resources. +* `sent_supress`: Is emitted when the scheduler has sent a `SUPPRESS` call to the Master to suppress new resource offers. +* `sent_accept_inverse_offers`: Is emitted when the scheduler has sent a `ACCEPT_INVERSE_OFFERS` call to the Master to accept inverse offers. +* `sent_decline_inverse_offers`: Is emitted when the scheduler has sent a `DECLINE_INVERSE_OFFERS` call to the Master to decline inverse offers. +* `sent_acknowledge_operation_status`: Is emitted when the scheduler has sent the `ACKNOWLEDGE_OPERATION_STATUS` call. +* `sent_reconcile_operations`: Is emitted when the scheduler has sent the `RECONCILE_OPERATIONS` call. * `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. @@ -263,7 +281,7 @@ var Builder = require("mesos-framework").Mesos.getBuilder(); var taskId = { "value": "my-task-id" }; - + var TaskID = new (Builder.build("mesos.TaskID"))(taskId); ``` From 55f2f62adee162333f2fe6a9d13c085990d63a84 Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sun, 4 Mar 2018 17:24:32 +0100 Subject: [PATCH 11/13] Update gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 613444d..d9d1541 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ npm-debug.log* .idea/ -coverage/ +.nyc_output From e609a6b92afdcec7e3209836337288efd9c5322d Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sun, 4 Mar 2018 17:25:19 +0100 Subject: [PATCH 12/13] Refactor tests & move to builder pattern --- lib/scheduler.js | 432 +++++++++++++--------- lib/schedulerHandlers.js | 7 +- lib/taskHealthHelper.js | 6 +- lib/taskHelper.js | 15 +- {tests => test}/helpers.test.js | 0 {tests => test}/scheduler.test.js | 25 +- {tests => test}/schedulerHandlers.test.js | 4 +- {tests => test}/taskHealthHelper.test.js | 0 {tests => test}/taskHelper.test.js | 0 9 files changed, 278 insertions(+), 211 deletions(-) rename {tests => test}/helpers.test.js (100%) rename {tests => test}/scheduler.test.js (98%) rename {tests => test}/schedulerHandlers.test.js (99%) rename {tests => test}/taskHealthHelper.test.js (100%) rename {tests => test}/taskHelper.test.js (100%) diff --git a/lib/scheduler.js b/lib/scheduler.js index 33a17e7..bc8fc8e 100644 --- a/lib/scheduler.js +++ b/lib/scheduler.js @@ -8,6 +8,7 @@ var uuid = require("uuid"); var helpers = require("./helpers"); var schedulerHandlers = require("./schedulerHandlers"); var mesos = require("./mesos")().getMesos(); +var Builder = require("./builder"); var TaskHelper = require("./taskHelper"); var zookeeper = require("node-zookeeper-client"); @@ -31,6 +32,7 @@ function Scheduler (options) { self.options = {}; self.options.frameworkName = (options.frameworkName ? options.frameworkName.replace(/ /g, "-") : "mesos-framework." + uuid.v4()); self.options.user = options.user || "root"; + self.options.role = options.role || "*"; self.options.restartStates = options.restartStates || ["TASK_FAILED", "TASK_LOST", "TASK_ERROR"]; // Task in TASK_FINISHED will NOT be restarted by default! self.options.frameworkFailoverTimeout = options.frameworkFailoverTimeout || 604800; // One week self.options.masterConnectionTimeout = options.masterConnectionTimeout * 1000 || 10000; // Ten seconds @@ -38,7 +40,7 @@ function Scheduler (options) { self.options.exponentialBackoffMinimum = options.exponentialBackoffMinimum * 1000 || 1000; // One second self.options.exponentialBackoffMaximum = options.exponentialBackoffMaximum * 1000 || 15000; // 15 seconds self.options.killUnknownTasks = options.killUnknownTasks || false; - self.options.serialNumberedTasks = (options.serialNumberedTasks === false) ? false : true; + self.options.serialNumberedTasks = (options.serialNumberedTasks !== false); // ZooKeeper self.options.useZk = options.useZk || false; @@ -169,13 +171,13 @@ function Scheduler (options) { // Set default path for the service self.zkServicePath = self.options.zkPrefix + self.options.frameworkName; - // Create ZK client (getting from options is only to be used for unit tests!) + // Create ZK client (getting from options is only to be used for unit test!) self.zkClient = options.zkClient || zookeeper.createClient(self.options.zkUrl); - // Instantiate TaskHelper (getting from options is only to be used for unit tests!) + // Instantiate TaskHelper (getting from options is only to be used for unit test!) self.taskHelper = options.taskHelper || new TaskHelper(self); - // For unit tests + // For unit test if (options.taskHelper) { self.taskHelper.scheduler = self; } @@ -530,31 +532,24 @@ Scheduler.prototype.subscribe = function () { }); // Set the Subscribe object - var Subscribe = new mesos.scheduler.Call.Subscribe( - new mesos.FrameworkInfo( - self.options.user, // user - self.options.frameworkName, // name - self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null, // id -> Use existing frameworkId for reconnections! - self.options.frameworkFailoverTimeout, // failover_timeout -> Set to one week for scheduler failover - null, // checkpoint - null, // role - (process.env.HOST ? process.env.HOST : null), // hostname - null, // principal - (process.env.HOST && process.env.PORT0 ? "http://" + process.env.HOST + ":" + process.env.PORT0 : null), // webui_url - null, // capabilities - null // labels - ) - ); + var Subscribe = new Builder("mesos.scheduler.Call.Subscribe") + .setFrameworkInfo(new Builder("mesos.FrameworkInfo") + .setUser(self.options.user) + .setRole(self.options.role) + .setName(self.options.frameworkName) + .setId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setFailoverTimeout(self.options.frameworkFailoverTimeout) + .setHostname(process.env.HOST ? process.env.HOST : null) + .setWebuiUrl(process.env.HOST && process.env.PORT0 ? "http://" + process.env.HOST + ":" + process.env.PORT0 : null) + ); self.logger.info("SUBSCRIBE: " + JSON.stringify(Subscribe)); // Set the Call object - var Call = helpers.fixEnums( - new mesos.scheduler.Call( - self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null, - "SUBSCRIBE", - Subscribe - ) + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.SUBSCRIBE) + .setSubscribe(Subscribe) ); setTimeout(function () { @@ -569,21 +564,30 @@ Scheduler.prototype.subscribe = function () { /** * Accept incoming offers to actually start the framework scheduler. - * @param {array} offers - The array of {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be accepted. - * @param {array} taskInfos - The array of {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L1452|Operation} objects. - * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L1911|Filters} object. + * @param {array} offersIds - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be accepted. + * @param {array} operations - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1452|Operation} objects. + * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object. */ -Scheduler.prototype.accept = function (offers, operations, filters) { +Scheduler.prototype.accept = function (offersIds, operations, filters) { var self = this; // Set the Accept object - var Accept = new mesos.scheduler.Call.Accept(offers, operations, filters); + var Accept = new Builder("mesos.scheduler.Call.Accept") + .setOfferIds(offersIds) + .setOperations(operations) + .setFilters(filters); self.logger.info("ACCEPT: " + JSON.stringify(Accept)); // Set the Call object - var Call = helpers.fixEnums(new mesos.scheduler.Call(new mesos.FrameworkID(self.frameworkId), "ACCEPT", null, Accept)); + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(new mesos.FrameworkID(self.frameworkId)) + .setType(mesos.scheduler.Call.Type.ACCEPT) + .setAccept(Accept) + ); + + self.logger.debug("Assembled ACCEPT call: " + JSON.stringify(Call)); helpers.doRequest.call(self, Call, function (error, response) { if (error) { @@ -597,18 +601,26 @@ Scheduler.prototype.accept = function (offers, operations, filters) { /** * Decline incoming offers because they are not needed by the framework scheduler currently. - * @param {array} offers - The array of {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be declined. - * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L1911|Filters} object. + * @param {array} offersIds - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be declined. + * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object. */ -Scheduler.prototype.decline = function (offers, filters) { +Scheduler.prototype.decline = function (offersIds, filters) { var self = this; // Set the Decline object - var Decline = new mesos.scheduler.Call.Decline(offers, filters); + var Decline = new Builder("mesos.scheduler.Call.Decline") + .setOfferIds(offersIds) + .setFilters(filters); // Set the Call object - var Call = helpers.fixEnums(new mesos.scheduler.Call(new mesos.FrameworkID(self.frameworkId), "DECLINE", null, null, Decline)); + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(new mesos.FrameworkID(self.frameworkId)) + .setType(mesos.scheduler.Call.Type.DECLINE) + .setDecline(Decline) + ); + + self.logger.debug("Assembled DECLINE call: " + JSON.stringify(Call)); helpers.doRequest.call(self, Call, function (error, response) { if (error) { @@ -627,15 +639,15 @@ Scheduler.prototype.decline = function (offers, filters) { Scheduler.prototype.teardown = function () { var self = this; + + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.TEARDOWN) + ); + + self.logger.debug("Assembled TEARDOWN call: " + JSON.stringify(Call)); - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "TEARDOWN" - }; - - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -652,14 +664,14 @@ Scheduler.prototype.revive = function () { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "REVIVE" - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.REVIVE) + ); + + self.logger.debug("Assembled REVIVE call: " + JSON.stringify(Call)); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -672,34 +684,30 @@ Scheduler.prototype.revive = function () { /** * Kill a specific task. If the scheduler has a custom executor, the kill is forwarded to the executor; it is up to the executor to kill the task and send a TASK_KILLED (or TASK_FAILED) update. * Mesos releases the resources for a task once it receives a terminal update for the task. If the task is unknown to the master, a TASK_LOST will be generated. - * @param {Object} taskId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L71|TaskID} to kill. - * @param {Object} agentId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. + * @param {Object} taskId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L71|TaskID} to kill. + * @param {Object} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. */ Scheduler.prototype.kill = function (taskId, agentId) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "KILL", - "kill": { - "task_id": { - "value": taskId - }, - "agent_id": { - "value": agentId - } - } - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.KILL) + .setKill(new Builder("mesos.scheduler.Call.Kill") + .setTaskId(new Builder("mesos.TaskID").setValue(taskId)) + .setAgentId(new Builder("mesos.AgentID").setValue(agentId)) + ) + ); + + self.logger.debug("Assembled KILL call: " + JSON.stringify(Call)); self.logger.debug("Killing task ID: " + taskId); if (self.options.useZk) self.taskHelper.deleteTask(taskId); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -712,29 +720,25 @@ Scheduler.prototype.kill = function (taskId, agentId) { /** * shutdown a specific custom executor (NOTE: This is a new call that was not present in the old API). When an executor gets a shutdown event, it is expected to kill all its tasks (and send TASK_KILLED updates) and terminate. * If an executor doesn’t terminate within a certain timeout (configurable via “–executor_shutdown_grace_period” agent flag), the agent will forcefully destroy the container (executor and its tasks) and transitions its active tasks to TASK_LOST. - * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. - * @param {string} executorId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L81|ExecutorID} whcih runs the task. + * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. + * @param {string} executorId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L81|ExecutorID} whcih runs the task. */ Scheduler.prototype.shutdown = function (agentId, executorId) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "SHUTDOWN", - "kill": { - "executor_id": { - "value": executorId - }, - "agent_id": { - "value": agentId - } - } - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.SHUTDOWN) + .setShutdown(new Builder("mesos.scheduler.Call.Shutdown") + .setExecutorId(new Builder("mesos.ExecutorID").setValue(executorId)) + .setAgentId(new Builder("mesos.AgentID").setValue(agentId)) + ) + ); - helpers.doRequest.call(self, payload, function (error, response) { + self.logger.debug("Assembled SHUTDOWN call: " + JSON.stringify(Call)); + + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -757,19 +761,19 @@ Scheduler.prototype.acknowledge = function (update) { return; } - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "ACKNOWLEDGE", - "acknowledge": { - "agent_id": update.status.agent_id, - "task_id": update.status.task_id, - "uuid": update.status.uuid - } - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.ACKNOWLEDGE) + .setAcknowledge(new Builder("mesos.scheduler.Call.Acknowledge") + .setTaskId(new Builder("mesos.TaskID").setValue(update.status.task_id)) + .setAgentId(new Builder("mesos.AgentID").setValue(update.status.agent_id)) + .setUuid(update.status.uuid) + ) + ); + + self.logger.debug("Assembled ACKNOWLEDGE call: " + JSON.stringify(Call)); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -782,44 +786,42 @@ Scheduler.prototype.acknowledge = function (update) { /** * query the status of non-terminal tasks. This causes the master to send back UPDATE events for each task in the list. Tasks that are no longer known to Mesos will result in TASK_LOST updates. * If the list of tasks is empty, master will send UPDATE events for all currently known tasks of the framework. - * @param {string} taskId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L71|TaskID} to kill. - * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. + * @param {string} taskId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L71|TaskID} to kill. + * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. */ Scheduler.prototype.reconcile = function (taskId, agentId) { var self = this; - var payload = null; + var Call = null; + if (taskId && agentId) { - payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "RECONCILE", - "reconcile": { - "tasks": [{ - "task_id": { - "value": taskId - }, - "agent_id": { - "value": agentId - } - }] - } - }; + Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.RECONCILE) + .setReconcile(new Builder("mesos.scheduler.Call.Reconcile") + .setTasks(new Builder("mesos.scheduler.Call.Reconcile.Task") + .setTaskId(new Builder("mesos.TaskID").setValue(taskId)) + .setAgentId(new Builder("mesos.AgentID").setValue(agentId) + ) + ) + ) + ); self.logger.debug("Reconciling task ID: " + taskId); } else { - payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "RECONCILE", - "reconcile": { "tasks": []} - }; + Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.RECONCILE) + .setReconcile(new Builder("mesos.scheduler.Call.Reconcile") + .setTasks([]) + ) + ); self.logger.debug("Reconciling all tasks "); } - helpers.doRequest.call(self, payload, function (error, response) { + self.logger.debug("Assembled RECONCILE call: " + JSON.stringify(Call)); + + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -831,31 +833,27 @@ Scheduler.prototype.reconcile = function (taskId, agentId) { /** * Send arbitrary data to the executor. Note that Mesos neither interprets this data nor makes any guarantees about the delivery of this message to the executor. - * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. - * @param {string} executorId The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L81|ExecutorID} which runs the task. + * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. + * @param {string} executorId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L81|ExecutorID} which runs the task. * @param {string} data The string which's raw bytes will be encoded in Base64. */ Scheduler.prototype.message = function (agentId, executorId, data) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "MESSAGE", - "message": { - "agent_id": { - "value": agentId - }, - "executor_id": { - "value": executorId - }, - "data": new Buffer(data).toString('base64') - } - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.MESSAGE) + .setMessage(new Builder("mesos.scheduler.Call.Message") + .setExecutorId(new Builder("mesos.ExecutorID").setValue(executorId)) + .setAgentId(new Builder("mesos.AgentID").setValue(agentId)) + .setData(new Buffer(data).toString("base64")) + ) + ); + + self.logger.debug("Assembled MESSAGE call: " + JSON.stringify(Call)); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -867,21 +865,23 @@ Scheduler.prototype.message = function (agentId, executorId, data) { /** * Request resources from the master/allocator. The built-in hierarchical allocator simply ignores this request but other allocators (modules) can interpret this in a customizable fashion. - * @param {array} requests The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L1410|Request} objects which should be sent to the server. + * @param {array} requests The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1410|Request} objects which should be sent to the server. */ Scheduler.prototype.request = function (requests) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "REQUEST", - "requests": requests - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.REQUEST) + .setRequest(new Builder("mesos.scheduler.Call.Request") + .setRequests(requests) + ) + ); - helpers.doRequest.call(self, payload, function (error, response) { + self.logger.debug("Assembled REQUEST call: " + JSON.stringify(Call)); + + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -893,21 +893,23 @@ Scheduler.prototype.request = function (requests) { /** * Suppress offers for the specified roles. If `roles` is empty, the `SUPPRESS` call will suppress offers for all of the roles the framework is currently subscribed to. - * @param {array} roles The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L2696|Role} objects which should be sent to the server. + * @param {array} roles The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2696|Role} objects which should be sent to the server. */ Scheduler.prototype.suppress = function (roles) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "SUPPRESS", - "roles": roles - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.SUPPRESS) + .setSuppress(new Builder("mesos.scheduler.Call.Suppress") + .setRoles(roles) + ) + ); + + self.logger.debug("Assembled SUPPRESS call: " + JSON.stringify(Call)); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -919,23 +921,25 @@ Scheduler.prototype.suppress = function (roles) { /** * Accepts an inverse offer. Inverse offers should only be accepted if the resources in the offer can be safely evacuated before the provided unavailability. - * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server. - * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server. + * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server. + * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server. */ Scheduler.prototype.acceptInverseOffers = function (inverseOffersIds, filters) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "ACCEPT_INVERSE_OFFERS", - "inverse_offer_ids": inverseOffersIds, - "filters": filters - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.ACCEPT_INVERSE_OFFERS) + .setAcceptInverseOffers(new Builder("mesos.scheduler.Call.AcceptInverseOffers") + .setInverseOfferIds(inverseOffersIds) + .setFilter(filters) + ) + ); + + self.logger.debug("Assembled ACCEPT_INVERSE_OFFERS call: " + JSON.stringify(Call)); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -947,23 +951,25 @@ Scheduler.prototype.acceptInverseOffers = function (inverseOffersIds, filters) { /** * Declines an inverse offer. Inverse offers should be declined if the resources in the offer might not be safely evacuated before the provided unavailability. - * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server. - * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.3.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server. + * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server. + * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server. */ Scheduler.prototype.declineInverseOffers = function (inverseOffersIds, filters) { var self = this; - var payload = { - "framework_id": { - "value": self.frameworkId - }, - "type": "DECLINE_INVERSE_OFFERS", - "inverse_offer_ids": inverseOffersIds, - "filters": filters - }; + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.DECLINE_INVERSE_OFFERS) + .setDeclineInverseOffers(new Builder("mesos.scheduler.Call.DeclineInverseOffers") + .setInverseOfferIds(inverseOffersIds) + .setFilter(filters) + ) + ); + + self.logger.debug("Assembled DECLINE_INVERSE_OFFERS call: " + JSON.stringify(Call)); - helpers.doRequest.call(self, payload, function (error, response) { + helpers.doRequest.call(self, Call, function (error, response) { if (error) { self.emit("error", error.message); } else { @@ -973,6 +979,68 @@ Scheduler.prototype.declineInverseOffers = function (inverseOffersIds, filters) }; +/** + * Acknowledges the receipt of an operation status update. Schedulers are responsible for explicitly acknowledging the receipt of updates which have the 'UpdateOperationStatus.status().uuid()' field set. Such status updates are retried by the agent or resource provider until they are acknowledged by the scheduler. + * @param {string} agentId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L59|AgentID} the task is running on. + * @param {string} resourceProviderId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L102|ResourceProviderId} + * @param {string} operationId The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L111|OperationID} + * @param {string} uuid The uuid of the Operation + */ +Scheduler.prototype.acknowledgeOperationStatus = function (agentId, resourceProviderId, operationId, uuid) { + + var self = this; + + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.ACKNOWLEDGE_OPERATION_STATUS) + .setAcknowledgeOperationStatus(new Builder("mesos.scheduler.Call.AcknowledgeOperationStatus") + .setAgentId(new Builder("mesos.AgentID").setValue(agentId)) + .setResourceProviderId(new Builder("mesos.ResourceProviderId").setValue(resourceProviderId)) + .setOperationId(new Builder("mesos.ResourceProviderId").setValue(operationId)) + .setUuid(uuid) + ) + ); + + self.logger.debug("Assembled ACKNOWLEDGE_OPERATION_STATUS call: " + JSON.stringify(Call)); + + helpers.doRequest.call(self, Call, function (error, response) { + if (error) { + self.emit("error", error.message); + } else { + self.emit("sent_acknowledge_operation_status"); + } + }); + +}; + +/** + * Allows the scheduler to query the status of operations. This causes the master to send back the latest status for each operation in 'operations', if possible. If 'operations' is empty, then the master will send the latest status for each operation currently known. + * @param {array} operations An array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/scheduler/scheduler.proto#L420|Operation} objects to query. + */ +Scheduler.prototype.reconcileOperations = function (operations) { + + var self = this; + + var Call = helpers.fixEnums(new Builder("mesos.scheduler.Call") + .setFrameworkId(self.frameworkId ? new mesos.FrameworkID(self.frameworkId) : null) + .setType(mesos.scheduler.Call.Type.RECONCILE_OPERATIONS) + .setReconcileOperations(new Builder("mesos.scheduler.Call.ReconcileOperations") + .setOperations(operations) + ) + ); + + self.logger.debug("Assembled RECONCILE_OPERATIONS call: " + JSON.stringify(Call)); + + helpers.doRequest.call(self, Call, function (error, response) { + if (error) { + self.emit("error", error.message); + } else { + self.emit("sent_reconcile_operations"); + } + }); + +}; + /** * Get the running tasks of this framework scheduler. * @returns {Array} The running task array. diff --git a/lib/schedulerHandlers.js b/lib/schedulerHandlers.js index a733acf..89c3376 100644 --- a/lib/schedulerHandlers.js +++ b/lib/schedulerHandlers.js @@ -222,10 +222,9 @@ module.exports = { // Add to demanded resources demandedResources.push( helpers.fixEnums( - new Builder("mesos.Resource").setName("ports").setType(mesos.Value.Type.RANGES).setRanges( - new Builder("mesos.Value.Ranges") - .setRange(usedPortRanges) - ) + new Builder("mesos.Resource").setName("ports") + .setType(mesos.Value.Type.RANGES) + .setRanges(new Builder("mesos.Value.Ranges").setRange(usedPortRanges)) ) ); diff --git a/lib/taskHealthHelper.js b/lib/taskHealthHelper.js index bd5672a..e28a1b9 100644 --- a/lib/taskHealthHelper.js +++ b/lib/taskHealthHelper.js @@ -135,8 +135,6 @@ TaskHealthHelper.prototype.checkInstance = function (task) { TaskHealthHelper.prototype.setProperties = function (task, value) { var self = this; self.options.additionalProperties.forEach(function (property) { - //self.logger.debug("Setting " + property.name + " to " + value); - // If healthy or setting unhealthy if (value || property.setUnhealthy) { var propertyValue = value; @@ -155,7 +153,7 @@ TaskHealthHelper.prototype.stopHealthCheck = function () { clearInterval(self.interval); self.interval = null; } -} +}; TaskHealthHelper.prototype.setupHealthCheck = function () { var self = this; @@ -164,4 +162,4 @@ TaskHealthHelper.prototype.setupHealthCheck = function () { self.interval = setInterval(self.checkRunningInstances, self.options.interval * 1000); }; -module.exports = TaskHealthHelper; \ No newline at end of file +module.exports = TaskHealthHelper; diff --git a/lib/taskHelper.js b/lib/taskHelper.js index 985670a..411b415 100644 --- a/lib/taskHelper.js +++ b/lib/taskHelper.js @@ -1,6 +1,8 @@ "use strict"; +var lib = require("requirefrom")("lib"); var Mesos = require("./mesos")().getMesos(); +var Builder = lib("builder"); /** * Represents a TaskHelper object @@ -39,7 +41,7 @@ TaskHelper.prototype.loadTasks = function() { } childStates[child] = {'loaded': false}; 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"); } @@ -68,14 +70,9 @@ TaskHelper.prototype.loadTasks = function() { pendingTask.taskId = task.taskId; if (task.commandInfo && task.commandInfo.environment && task.commandInfo.environment.variables && task.commandInfo.environment.variables.length > 0) { if (!pendingTask.commandInfo) { - pendingTask.commandInfo = new Mesos.CommandInfo( - null, // URI - new Mesos.Environment([]), // Environment - false, // Is shell? - null, // Command - null, // Arguments - null // User - ); + pendingTask.commandInfo = new Builder("mesos.CommandInfo") + .setEnvironment(new Mesos.Environment([])) + .setShell(false); } if (!pendingTask.commandInfo.environment) { pendingTask.commandInfo.environment = new Mesos.Environment([]); diff --git a/tests/helpers.test.js b/test/helpers.test.js similarity index 100% rename from tests/helpers.test.js rename to test/helpers.test.js diff --git a/tests/scheduler.test.js b/test/scheduler.test.js similarity index 98% rename from tests/scheduler.test.js rename to test/scheduler.test.js index b006316..c7b971f 100644 --- a/tests/scheduler.test.js +++ b/test/scheduler.test.js @@ -89,7 +89,7 @@ describe("Scheduler constructor", function() { sandbox = sinon.sandbox.create(); sandbox.stub(helpers, "sortTasksByPriority", function(tasks) { return [{name:"task1", isSubmitted:true}, - {name:"task2", isSubmitted:true,instances:3}]; + {name:"task2", isSubmitted:true, instances:3}]; }); }); after(function (done) { @@ -113,14 +113,8 @@ describe("Scheduler constructor", function() { var taskHelper = new TaskHelper({"zkClient": zkClient, "logger": logger, "pendingTasks":[], "launchedTasks":[], scheduler:{}}); beforeEach(function () { sandbox = sinon.sandbox.create(); - clock = sinon.useFakeTimers(); - //sandbox.stub(zookeeper, "createClient" ); - /*sandbox.stub(zookeeper, "on", function(event, cb) { - if (event == "connected") { - cb(); - } - });*/ + sandbox.stub(zkClient, "connect", function() { this.emit("connected"); }); @@ -897,7 +891,13 @@ describe("Scheduler constructor", function() { scheduler.frameworkId = "123445547452563"; scheduler.on("ready", function() { - scheduler.request(["12312312","fasfafas", "sdfasfasfgasgloewy2398y423r5fqwncas"]); + //scheduler.request(["12312312","fasfafas", "sdfasfasfgasgloewy2398y423r5fqwncas"]); + scheduler.request(new Builder("mesos.Request") + .setAgentId(new Builder("mesos.AgentID").setValue("12312312")) + .setResources([ + new Builder("mesos.Resource").setName("cpus").setType(mesos.Value.Type.SCALAR).setScalar(new mesos.Value.Scalar(1.1)) + ]) + ); }); scheduler.on("sent_request", function() { sent = true; @@ -923,7 +923,12 @@ describe("Scheduler constructor", function() { scheduler.frameworkId = "123445547452563"; scheduler.on("ready", function() { - scheduler.request(["12312312","fasfafas", "sdfasfasfgasgloewy2398y423r5fqwncas"]); + scheduler.request(new Builder("mesos.Request") + .setAgentId(new Builder("mesos.AgentID").setValue("12312312")) + .setResources([ + new Builder("mesos.Resource").setName("cpus").setType(mesos.Value.Type.SCALAR).setScalar(new mesos.Value.Scalar(1.1)) + ]) + ); }); scheduler.on("sent_request", function() { sent = true; diff --git a/tests/schedulerHandlers.test.js b/test/schedulerHandlers.test.js similarity index 99% rename from tests/schedulerHandlers.test.js rename to test/schedulerHandlers.test.js index 2dee997..34e5718 100644 --- a/tests/schedulerHandlers.test.js +++ b/test/schedulerHandlers.test.js @@ -16,7 +16,7 @@ var Mesos = lib("mesos")().getMesos(); var expect = require("chai").expect; var sinon = require("sinon"); -describe("Offers handlers tests", function () { +describe("Offers handlers test", function () { var accept = true; @@ -605,7 +605,7 @@ describe("Offers handlers tests", function () { }); -describe("Update handlers tests", function () { +describe("Update handlers test", function () { var acknowleged; var killed; diff --git a/tests/taskHealthHelper.test.js b/test/taskHealthHelper.test.js similarity index 100% rename from tests/taskHealthHelper.test.js rename to test/taskHealthHelper.test.js diff --git a/tests/taskHelper.test.js b/test/taskHelper.test.js similarity index 100% rename from tests/taskHelper.test.js rename to test/taskHelper.test.js From 0868f1bdab24a2a21febaa34cdc691e96bf929f3 Mon Sep 17 00:00:00 2001 From: TobiLG Date: Sun, 4 Mar 2018 17:38:08 +0100 Subject: [PATCH 13/13] Update mesos.proto references in docs --- README.md | 22 +++++++-------- docs/Builder.html | 2 +- docs/Executor.html | 2 +- docs/Mesos.html | 2 +- docs/Scheduler.html | 16 +++++------ docs/TaskHealthHelper.html | 2 +- docs/TaskHelper.html | 2 +- docs/builder.js.html | 2 +- docs/coverage/index.html | 2 +- docs/coverage/mesos-framework/index.html | 2 +- docs/coverage/mesos-framework/index.js.html | 2 +- .../mesos-framework/lib/builder.js.html | 2 +- .../mesos-framework/lib/executor.js.html | 2 +- .../lib/executorHandlers.js.html | 2 +- .../mesos-framework/lib/helpers.js.html | 2 +- docs/coverage/mesos-framework/lib/index.html | 2 +- .../mesos-framework/lib/mesos.js.html | 2 +- .../mesos-framework/lib/scheduler.js.html | 2 +- .../lib/schedulerHandlers.js.html | 2 +- .../lib/taskHealthHelper.js.html | 2 +- .../mesos-framework/lib/taskHelper.js.html | 2 +- docs/executor.js.html | 2 +- docs/index.html | 28 ++++++++++--------- docs/mesos.js.html | 2 +- docs/scheduler.js.html | 16 +++++------ docs/taskHealthHelper.js.html | 2 +- docs/taskHelper.js.html | 2 +- lib/scheduler.js | 14 +++++----- 28 files changed, 72 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 72e638f..c864c4e 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ The [Coverage Reports](http://tobilg.github.io/mesos-framework/coverage/) are ho ### Scheduler -The `Scheduler` is the "heart" of a Mesos framework. It is very well possible to create a Mesos framework only by implementing the `Scheduler` with the standard [CommandInfo](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L397) and [ContainerInfo](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L1744) objects. +The `Scheduler` is the "heart" of a Mesos framework. It is very well possible to create a Mesos framework only by implementing the `Scheduler` with the standard [CommandInfo](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L647) and [ContainerInfo](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1744) objects. The option properties you can specify to create a `Scheduler` are the following: @@ -67,7 +67,7 @@ The option properties you can specify to create a `Scheduler` are the following: * `user`: The system user name to use (must exist on the agents!). Default is `root`. * `role`: The Mesos role to use when subscribing to the master. Default is `*`. * `frameworkName`: The desired framework name (will choose a standard name if not specified). Default is `mesos-framework.` concatented with a unique UUID. -* `restartStates`: An array of [TaskState](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L1671) objects which should trigger a restart of a task. For example, regularly finished tasks (in state `TASK_FINISHED`) are not restarted by default. +* `restartStates`: An array of [TaskState](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1671) objects which should trigger a restart of a task. For example, regularly finished tasks (in state `TASK_FINISHED`) are not restarted by default. * `masterConnectionTimeout`: The number of seconds to wait before a connection to the leading Mesos master is considered as timed out (default: `10`). * `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`). * `exponentialBackoffFactor`: The factor in which to increase (multiply) the backoff timer upon re-subscription (default `1.5`). @@ -83,13 +83,13 @@ A `tasks` sub-object can contain objects with task information: * `instances`: The number of instances (tasks) you want to launch (will be 1 if you don't specify this property). * `priority`: The priority of which the different tasks shall be launched (lower is better). If none is specified, tasks will be launched based on the task naming. * `allowScaling`: A boolean value which indicates whether this task permits scaling operations (default: `false`). -* `commandInfo`: A [Mesos.CommandInfo](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L580) definition (**mandatory**). -* `containerInfo`: A [Mesos.ContainerInfo](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L2360) definition. -* `executorInfo`: A [Mesos.ExecutorInfo](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L642) definition. -* `resources`: The object of [Mesos.Resource](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L876) types, such as `cpu`, `mem`, `ports` and `disk` (**mandatory**) with an optional fixedPorts number array (included in the general port count). +* `commandInfo`: A [Mesos.CommandInfo](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L647) definition (**mandatory**). +* `containerInfo`: A [Mesos.ContainerInfo](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L3093) definition. +* `executorInfo`: A [Mesos.ExecutorInfo](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L709) definition. +* `resources`: The object of [Mesos.Resource](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1163) 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](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L441) definition. -* `labels`: A [Mesos.Labels](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L2475) definition. +* `healthChecks`: A [Mesos.HealthCheck](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L504) definition. +* `labels`: A [Mesos.Labels](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L3273) definition. #### High availability @@ -230,9 +230,9 @@ You should consider writing your own executors if your framework has special req How can the custom executors be used? Taken from the [Mesos framework development guide](http://mesos.apache.org/documentation/latest/app-framework-development-guide/): > One way to distribute your framework executor is to let the Mesos fetcher download it on-demand when your scheduler launches tasks on that slave. -> [ExecutorInfo](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L642) is a Protocol Buffer Message class, and it contains a field of type [CommandInfo](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L397). -> [CommandInfo](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L580) allows schedulers to specify, among other things, a number of resources as URIs. -> These resources are fetched to a sandbox directory on the slave before attempting to execute the [ExecutorInfo](https://github.com/apache/mesos/blob/1.2.x/include/mesos/v1/mesos.proto#L642) command. +> [ExecutorInfo](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L709) is a Protocol Buffer Message class, and it contains a field of type [CommandInfo](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L647). +> [CommandInfo](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L647) allows schedulers to specify, among other things, a number of resources as URIs. +> These resources are fetched to a sandbox directory on the slave before attempting to execute the [ExecutorInfo](https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L709) command. > Several URI schemes are supported, including HTTP, FTP, HDFS, and S3. > Alternatively, you can pass the `frameworks_home` configuration option (defaults to: `MESOS_HOME/frameworks`) to your mesos-slave daemons diff --git a/docs/Builder.html b/docs/Builder.html index 8577eeb..e08eae9 100644 --- a/docs/Builder.html +++ b/docs/Builder.html @@ -217,7 +217,7 @@
Parameters:

- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/Executor.html b/docs/Executor.html index 593c523..4499b14 100644 --- a/docs/Executor.html +++ b/docs/Executor.html @@ -575,7 +575,7 @@
Parameters:

- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/Mesos.html b/docs/Mesos.html index bbaacdc..9a1fe25 100644 --- a/docs/Mesos.html +++ b/docs/Mesos.html @@ -682,7 +682,7 @@
Returns:

- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/Scheduler.html b/docs/Scheduler.html index dbad84e..cd97a37 100644 --- a/docs/Scheduler.html +++ b/docs/Scheduler.html @@ -339,7 +339,7 @@
Parameters:
-

The array of Operation objects.

+

The array of Operation objects.

@@ -365,7 +365,7 @@
Parameters:
-

The Filters object.

+

The Filters object.

@@ -526,7 +526,7 @@
Parameters:
-

The Filters object which should be sent to the server.

+

The Filters object which should be sent to the server.

@@ -1118,7 +1118,7 @@
Parameters:
-

The Filters object.

+

The Filters object.

@@ -1279,7 +1279,7 @@
Parameters:
-

The Filters object which should be sent to the server.

+

The Filters object which should be sent to the server.

@@ -2168,7 +2168,7 @@
Parameters:
-

The Request objects which should be sent to the server.

+

The Request objects which should be sent to the server.

@@ -2631,7 +2631,7 @@
Parameters:
-

The Role objects which should be sent to the server.

+

The Role objects which should be sent to the server.

@@ -2841,7 +2841,7 @@

teardown
- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/TaskHealthHelper.html b/docs/TaskHealthHelper.html index 0ccdb7d..b8df2d7 100644 --- a/docs/TaskHealthHelper.html +++ b/docs/TaskHealthHelper.html @@ -243,7 +243,7 @@
Parameters:

- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/TaskHelper.html b/docs/TaskHelper.html index a82c4c3..76585c2 100644 --- a/docs/TaskHelper.html +++ b/docs/TaskHelper.html @@ -574,7 +574,7 @@
Parameters:

- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/builder.js.html b/docs/builder.js.html index f9ea4c9..1eb5c77 100644 --- a/docs/builder.js.html +++ b/docs/builder.js.html @@ -75,7 +75,7 @@

builder.js


- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/coverage/index.html b/docs/coverage/index.html index 244b778..6f00201 100644 --- a/docs/coverage/index.html +++ b/docs/coverage/index.html @@ -90,7 +90,7 @@

diff --git a/docs/coverage/mesos-framework/index.html b/docs/coverage/mesos-framework/index.html index 0fa20d7..6e994f8 100644 --- a/docs/coverage/mesos-framework/index.html +++ b/docs/coverage/mesos-framework/index.html @@ -77,7 +77,7 @@

diff --git a/docs/coverage/mesos-framework/index.js.html b/docs/coverage/mesos-framework/index.js.html index 9a7ad2d..646d59b 100644 --- a/docs/coverage/mesos-framework/index.js.html +++ b/docs/coverage/mesos-framework/index.js.html @@ -73,7 +73,7 @@

diff --git a/docs/coverage/mesos-framework/lib/builder.js.html b/docs/coverage/mesos-framework/lib/builder.js.html index 7e73d28..6cc9341 100644 --- a/docs/coverage/mesos-framework/lib/builder.js.html +++ b/docs/coverage/mesos-framework/lib/builder.js.html @@ -121,7 +121,7 @@

diff --git a/docs/coverage/mesos-framework/lib/executor.js.html b/docs/coverage/mesos-framework/lib/executor.js.html index e42db72..f8364f9 100644 --- a/docs/coverage/mesos-framework/lib/executor.js.html +++ b/docs/coverage/mesos-framework/lib/executor.js.html @@ -898,7 +898,7 @@

diff --git a/docs/coverage/mesos-framework/lib/executorHandlers.js.html b/docs/coverage/mesos-framework/lib/executorHandlers.js.html index 338e4a5..2678bba 100644 --- a/docs/coverage/mesos-framework/lib/executorHandlers.js.html +++ b/docs/coverage/mesos-framework/lib/executorHandlers.js.html @@ -124,7 +124,7 @@

diff --git a/docs/coverage/mesos-framework/lib/helpers.js.html b/docs/coverage/mesos-framework/lib/helpers.js.html index e185476..6a1bcef 100644 --- a/docs/coverage/mesos-framework/lib/helpers.js.html +++ b/docs/coverage/mesos-framework/lib/helpers.js.html @@ -556,7 +556,7 @@

diff --git a/docs/coverage/mesos-framework/lib/index.html b/docs/coverage/mesos-framework/lib/index.html index 99a06bd..4372f6a 100644 --- a/docs/coverage/mesos-framework/lib/index.html +++ b/docs/coverage/mesos-framework/lib/index.html @@ -181,7 +181,7 @@

diff --git a/docs/coverage/mesos-framework/lib/mesos.js.html b/docs/coverage/mesos-framework/lib/mesos.js.html index a09bc34..e1340ab 100644 --- a/docs/coverage/mesos-framework/lib/mesos.js.html +++ b/docs/coverage/mesos-framework/lib/mesos.js.html @@ -223,7 +223,7 @@

diff --git a/docs/coverage/mesos-framework/lib/scheduler.js.html b/docs/coverage/mesos-framework/lib/scheduler.js.html index d7db93d..b3329b7 100644 --- a/docs/coverage/mesos-framework/lib/scheduler.js.html +++ b/docs/coverage/mesos-framework/lib/scheduler.js.html @@ -3370,7 +3370,7 @@

diff --git a/docs/coverage/mesos-framework/lib/schedulerHandlers.js.html b/docs/coverage/mesos-framework/lib/schedulerHandlers.js.html index 6a42927..d39749f 100644 --- a/docs/coverage/mesos-framework/lib/schedulerHandlers.js.html +++ b/docs/coverage/mesos-framework/lib/schedulerHandlers.js.html @@ -1807,7 +1807,7 @@

diff --git a/docs/coverage/mesos-framework/lib/taskHealthHelper.js.html b/docs/coverage/mesos-framework/lib/taskHealthHelper.js.html index 1ef12b5..89ceabd 100644 --- a/docs/coverage/mesos-framework/lib/taskHealthHelper.js.html +++ b/docs/coverage/mesos-framework/lib/taskHealthHelper.js.html @@ -544,7 +544,7 @@

diff --git a/docs/coverage/mesos-framework/lib/taskHelper.js.html b/docs/coverage/mesos-framework/lib/taskHelper.js.html index f6e6b10..fcbf929 100644 --- a/docs/coverage/mesos-framework/lib/taskHelper.js.html +++ b/docs/coverage/mesos-framework/lib/taskHelper.js.html @@ -502,7 +502,7 @@

diff --git a/docs/executor.js.html b/docs/executor.js.html index 4aea169..c21dc73 100644 --- a/docs/executor.js.html +++ b/docs/executor.js.html @@ -334,7 +334,7 @@

executor.js


- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/index.html b/docs/index.html index 432d27b..4d8c935 100644 --- a/docs/index.html +++ b/docs/index.html @@ -52,7 +52,9 @@

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 version is 1.5.0.

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.

+
npm i mesos-framework --save

Local test environment

docker-compose can be used for setting up a local test environment. Just run

+
$ docker-compose up -d

in the base directory of this project.

+

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.

It implements all existing Calls as methods for both the Scheduler and Executor classes, meaning that they can be used without having to write the HTTP communication yourself. Additionally, it exposes all Events for both classes, as definied in the Mesos docs. It also adds some custom events for the Scheduler class for better task handling.

There are some basic event handler methods provided for the Scheduler class, which for example take care of the checking and accepting the offers received from the Mesos master, as well as keeping track of tasks. Please have a look at the class documentation in the docs folder of this project.

For both the Scheduler and Executor classes, the belonging event handler methods can be overwritten with custom logic. To do that, you can supply a options.handlers property map object (where the property name is the uppercase Event name) when instantiating a class:

@@ -67,7 +69,7 @@

Installation

You can use mesos-framework in your own pro });

Basically this is the mechanism to create custom framework logic. Please have a look at the examples folder to see examples for command-based and Docker-based schedulers.

API docs

The API docs can be accessed via API docs hosted on GitHub pages.

Coverage reports

The Coverage Reports are hosted on GitHub pages as well.

-

Scheduler

The Scheduler is the "heart" of a Mesos framework. It is very well possible to create a Mesos framework only by implementing the Scheduler with the standard CommandInfo and ContainerInfo objects.

+

Scheduler

The Scheduler is the "heart" of a Mesos framework. It is very well possible to create a Mesos framework only by implementing the Scheduler with the standard CommandInfo and ContainerInfo objects.

The option properties you can specify to create a Scheduler are the following:

  • masterUrl: The URL of the leading Mesos master (mandatory).
  • @@ -78,7 +80,7 @@

    Scheduler

    The Scheduler is the "heart" of a Me

  • user: The system user name to use (must exist on the agents!). Default is root.
  • role: The Mesos role to use when subscribing to the master. Default is *.
  • frameworkName: The desired framework name (will choose a standard name if not specified). Default is mesos-framework. concatented with a unique UUID.
  • -
  • restartStates: An array of TaskState objects which should trigger a restart of a task. For example, regularly finished tasks (in state TASK_FINISHED) are not restarted by default.
  • +
  • restartStates: An array of TaskState objects which should trigger a restart of a task. For example, regularly finished tasks (in state TASK_FINISHED) are not restarted by default.
  • masterConnectionTimeout: The number of seconds to wait before a connection to the leading Mesos master is considered as timed out (default: 10).
  • 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).
  • exponentialBackoffFactor: The factor in which to increase (multiply) the backoff timer upon re-subscription (default 1.5).
  • @@ -94,13 +96,13 @@

    Scheduler

    The Scheduler is the "heart" of a Me

  • instances: The number of instances (tasks) you want to launch (will be 1 if you don't specify this property).
  • priority: The priority of which the different tasks shall be launched (lower is better). If none is specified, tasks will be launched based on the task naming.
  • allowScaling: A boolean value which indicates whether this task permits scaling operations (default: false).
  • -
  • commandInfo: A Mesos.CommandInfo definition (mandatory).
  • -
  • containerInfo: A Mesos.ContainerInfo definition.
  • -
  • executorInfo: A Mesos.ExecutorInfo definition.
  • -
  • 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).
  • +
  • commandInfo: A Mesos.CommandInfo definition (mandatory).
  • +
  • containerInfo: A Mesos.ContainerInfo definition.
  • +
  • executorInfo: A Mesos.ExecutorInfo definition.
  • +
  • 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.
  • +
  • healthChecks: A Mesos.HealthCheck definition.
  • +
  • labels: A Mesos.Labels definition.

High availability

Currently, mesos-framework doesn't support HA setups for the scheduler instances, meaning that you can only run one instance at once. If you run the scheduler application via Marathon, you should be able to make use of the health checks to let them restart the scheduler application once it fails.

You can use ZooKeeper though to be able to recover from scheduler restarts. This is done by setting useZk to true and specifying a zkUrl connection string (optionally, if you don't want to use the default master.mesos:2181, which should work inside clusters using Mesos DNS).

@@ -219,9 +221,9 @@

Example

Also, you can have a look at the examples folder

How can the custom executors be used? Taken from the Mesos framework development guide:

One way to distribute your framework executor is to let the Mesos fetcher download it on-demand when your scheduler launches tasks on that slave. -ExecutorInfo is a Protocol Buffer Message class, and it contains a field of type CommandInfo. -CommandInfo allows schedulers to specify, among other things, a number of resources as URIs. -These resources are fetched to a sandbox directory on the slave before attempting to execute the ExecutorInfo command. +ExecutorInfo is a Protocol Buffer Message class, and it contains a field of type CommandInfo. +CommandInfo allows schedulers to specify, among other things, a number of resources as URIs. +These resources are fetched to a sandbox directory on the slave before attempting to execute the ExecutorInfo command. Several URI schemes are supported, including HTTP, FTP, HDFS, and S3.

@@ -294,7 +296,7 @@

Mesos

Creating objects ("natively" via protobufjs)


- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/mesos.js.html b/docs/mesos.js.html index a841b04..4468cca 100644 --- a/docs/mesos.js.html +++ b/docs/mesos.js.html @@ -109,7 +109,7 @@

mesos.js


- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/scheduler.js.html b/docs/scheduler.js.html index 84632ab..1e0212a 100644 --- a/docs/scheduler.js.html +++ b/docs/scheduler.js.html @@ -606,8 +606,8 @@

scheduler.js

/** * Accept incoming offers to actually start the framework scheduler. * @param {array} offersIds - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be accepted. - * @param {array} operations - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1452|Operation} objects. - * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object. + * @param {array} operations - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1903|Operation} objects. + * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2488|Filters} object. */ Scheduler.prototype.accept = function (offersIds, operations, filters) { @@ -643,7 +643,7 @@

scheduler.js

/** * Decline incoming offers because they are not needed by the framework scheduler currently. * @param {array} offersIds - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be declined. - * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object. + * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2488|Filters} object. */ Scheduler.prototype.decline = function (offersIds, filters) { @@ -906,7 +906,7 @@

scheduler.js

/** * Request resources from the master/allocator. The built-in hierarchical allocator simply ignores this request but other allocators (modules) can interpret this in a customizable fashion. - * @param {array} requests The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1410|Request} objects which should be sent to the server. + * @param {array} requests The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1858|Request} objects which should be sent to the server. */ Scheduler.prototype.request = function (requests) { @@ -934,7 +934,7 @@

scheduler.js

/** * Suppress offers for the specified roles. If `roles` is empty, the `SUPPRESS` call will suppress offers for all of the roles the framework is currently subscribed to. - * @param {array} roles The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2696|Role} objects which should be sent to the server. + * @param {array} roles The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L3390|Role} objects which should be sent to the server. */ Scheduler.prototype.suppress = function (roles) { @@ -963,7 +963,7 @@

scheduler.js

/** * Accepts an inverse offer. Inverse offers should only be accepted if the resources in the offer can be safely evacuated before the provided unavailability. * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server. - * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server. + * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2488|Filters} object which should be sent to the server. */ Scheduler.prototype.acceptInverseOffers = function (inverseOffersIds, filters) { @@ -993,7 +993,7 @@

scheduler.js

/** * Declines an inverse offer. Inverse offers should be declined if the resources in the offer might not be safely evacuated before the provided unavailability. * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server. - * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server. + * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2488|Filters} object which should be sent to the server. */ Scheduler.prototype.declineInverseOffers = function (inverseOffersIds, filters) { @@ -1158,7 +1158,7 @@

scheduler.js


- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/taskHealthHelper.js.html b/docs/taskHealthHelper.js.html index db5f55d..27d5eca 100644 --- a/docs/taskHealthHelper.js.html +++ b/docs/taskHealthHelper.js.html @@ -216,7 +216,7 @@

taskHealthHelper.js


- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/docs/taskHelper.js.html b/docs/taskHelper.js.html index 1711fcc..c453eab 100644 --- a/docs/taskHelper.js.html +++ b/docs/taskHelper.js.html @@ -202,7 +202,7 @@

taskHelper.js


- Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:16:42 GMT+0100 (CET) using the Minami theme. + Generated by JSDoc 3.5.5 on Sun Mar 04 2018 17:37:29 GMT+0100 (CET) using the Minami theme.
diff --git a/lib/scheduler.js b/lib/scheduler.js index bc8fc8e..ef821aa 100644 --- a/lib/scheduler.js +++ b/lib/scheduler.js @@ -565,8 +565,8 @@ Scheduler.prototype.subscribe = function () { /** * Accept incoming offers to actually start the framework scheduler. * @param {array} offersIds - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be accepted. - * @param {array} operations - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1452|Operation} objects. - * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object. + * @param {array} operations - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1903|Operation} objects. + * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2488|Filters} object. */ Scheduler.prototype.accept = function (offersIds, operations, filters) { @@ -602,7 +602,7 @@ Scheduler.prototype.accept = function (offersIds, operations, filters) { /** * Decline incoming offers because they are not needed by the framework scheduler currently. * @param {array} offersIds - The array of {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID}s which should be declined. - * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object. + * @param {object} filters - The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2488|Filters} object. */ Scheduler.prototype.decline = function (offersIds, filters) { @@ -865,7 +865,7 @@ Scheduler.prototype.message = function (agentId, executorId, data) { /** * Request resources from the master/allocator. The built-in hierarchical allocator simply ignores this request but other allocators (modules) can interpret this in a customizable fashion. - * @param {array} requests The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1410|Request} objects which should be sent to the server. + * @param {array} requests The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1858|Request} objects which should be sent to the server. */ Scheduler.prototype.request = function (requests) { @@ -893,7 +893,7 @@ Scheduler.prototype.request = function (requests) { /** * Suppress offers for the specified roles. If `roles` is empty, the `SUPPRESS` call will suppress offers for all of the roles the framework is currently subscribed to. - * @param {array} roles The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2696|Role} objects which should be sent to the server. + * @param {array} roles The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L3390|Role} objects which should be sent to the server. */ Scheduler.prototype.suppress = function (roles) { @@ -922,7 +922,7 @@ Scheduler.prototype.suppress = function (roles) { /** * Accepts an inverse offer. Inverse offers should only be accepted if the resources in the offer can be safely evacuated before the provided unavailability. * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server. - * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server. + * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2488|Filters} object which should be sent to the server. */ Scheduler.prototype.acceptInverseOffers = function (inverseOffersIds, filters) { @@ -952,7 +952,7 @@ Scheduler.prototype.acceptInverseOffers = function (inverseOffersIds, filters) { /** * Declines an inverse offer. Inverse offers should be declined if the resources in the offer might not be safely evacuated before the provided unavailability. * @param {array} inverseOffersIds The {@Link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L49|OfferID} array which should be sent to the server. - * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L1911|Filters} object which should be sent to the server. + * @param {object} filters The {@link https://github.com/apache/mesos/blob/1.5.x/include/mesos/v1/mesos.proto#L2488|Filters} object which should be sent to the server. */ Scheduler.prototype.declineInverseOffers = function (inverseOffersIds, filters) {