summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--METADATA3
-rw-r--r--OWNERS5
-rw-r--r--PREUPLOAD.cfg9
-rw-r--r--__init__.py0
-rw-r--r--configs/global/Android.mk63
-rw-r--r--configs/infra/prod/androidtestcenter/bots.cfg17
-rw-r--r--configs/infra/prod/androidtestcenter/scripts/home_bot_config.py340
-rw-r--r--configs/infra/prod/androidtestcenter/settings.cfg27
-rw-r--r--configs/infra/prod/vtslab-config-prod/acl.cfg9
-rw-r--r--configs/infra/prod/vtslab-config-prod/import.cfg6
-rw-r--r--configs/infra/prod/vtslab-config-prod/projects.cfg19
-rw-r--r--configs/infra/prod/vtslab-config-prod/schemas.cfg79
-rw-r--r--configs/infra/prod/vtslab-config-prod/services.cfg60
-rw-r--r--configs/infra/test/androidtestcenter-test/bots.cfg17
-rw-r--r--configs/infra/test/androidtestcenter-test/scripts/home_bot_config.py340
-rw-r--r--configs/infra/test/androidtestcenter-test/settings.cfg27
-rw-r--r--configs/infra/test/vtslab-config-test/acl.cfg9
-rw-r--r--configs/infra/test/vtslab-config-test/import.cfg6
-rw-r--r--configs/infra/test/vtslab-config-test/projects.cfg19
-rw-r--r--configs/infra/test/vtslab-config-test/schemas.cfg79
-rw-r--r--configs/infra/test/vtslab-config-test/services.cfg60
-rw-r--r--gae/.gitignore1
-rw-r--r--gae/app.yaml57
-rw-r--r--gae/appengine_config.py5
-rw-r--r--gae/buildv1openapi.json194
-rw-r--r--gae/cron.yaml13
-rw-r--r--gae/favicon.icobin4286 -> 0 bytes
-rw-r--r--gae/frontend/.editorconfig13
-rw-r--r--gae/frontend/.gitignore39
-rw-r--r--gae/frontend/MODULE_LICENSE_MIT0
-rw-r--r--gae/frontend/NOTICE22
-rw-r--r--gae/frontend/angular.json127
-rw-r--r--gae/frontend/e2e/protractor.conf.js28
-rw-r--r--gae/frontend/e2e/src/app.e2e-spec.ts14
-rw-r--r--gae/frontend/e2e/src/app.po.ts11
-rw-r--r--gae/frontend/e2e/tsconfig.e2e.json13
-rw-r--r--gae/frontend/package-lock.json10746
-rw-r--r--gae/frontend/package.json53
-rw-r--r--gae/frontend/src/app/app.component.html35
-rw-r--r--gae/frontend/src/app/app.component.scss28
-rw-r--r--gae/frontend/src/app/app.component.spec.ts0
-rw-r--r--gae/frontend/src/app/app.component.ts63
-rw-r--r--gae/frontend/src/app/app.module.ts141
-rw-r--r--gae/frontend/src/app/appservice.ts37
-rw-r--r--gae/frontend/src/app/menu/build/build.component.html75
-rw-r--r--gae/frontend/src/app/menu/build/build.component.scss0
-rw-r--r--gae/frontend/src/app/menu/build/build.component.ts127
-rw-r--r--gae/frontend/src/app/menu/build/build.service.ts43
-rw-r--r--gae/frontend/src/app/menu/cdk-detail-row.directive.ts72
-rw-r--r--gae/frontend/src/app/menu/dashboard/dashboard.component.html30
-rw-r--r--gae/frontend/src/app/menu/dashboard/dashboard.component.scss17
-rw-r--r--gae/frontend/src/app/menu/dashboard/dashboard.component.ts74
-rw-r--r--gae/frontend/src/app/menu/device/device.component.html80
-rw-r--r--gae/frontend/src/app/menu/device/device.component.scss7
-rw-r--r--gae/frontend/src/app/menu/device/device.component.ts138
-rw-r--r--gae/frontend/src/app/menu/device/device.service.ts43
-rw-r--r--gae/frontend/src/app/menu/job/_job-theme.scss7
-rw-r--r--gae/frontend/src/app/menu/job/job.component.html192
-rw-r--r--gae/frontend/src/app/menu/job/job.component.scss24
-rw-r--r--gae/frontend/src/app/menu/job/job.component.ts221
-rw-r--r--gae/frontend/src/app/menu/job/job.service.ts44
-rw-r--r--gae/frontend/src/app/menu/lab/lab.component.html109
-rw-r--r--gae/frontend/src/app/menu/lab/lab.component.scss41
-rw-r--r--gae/frontend/src/app/menu/lab/lab.component.ts104
-rw-r--r--gae/frontend/src/app/menu/lab/lab.service.ts44
-rw-r--r--gae/frontend/src/app/menu/menu-items.ts23
-rw-r--r--gae/frontend/src/app/menu/menu_base.ts79
-rw-r--r--gae/frontend/src/app/menu/schedule/_schedule-theme.scss7
-rw-r--r--gae/frontend/src/app/menu/schedule/schedule.component.html121
-rw-r--r--gae/frontend/src/app/menu/schedule/schedule.component.scss24
-rw-r--r--gae/frontend/src/app/menu/schedule/schedule.component.ts160
-rw-r--r--gae/frontend/src/app/menu/schedule/schedule.service.ts51
-rw-r--r--gae/frontend/src/app/model/build.ts25
-rw-r--r--gae/frontend/src/app/model/build_wrapper.ts21
-rw-r--r--gae/frontend/src/app/model/device.ts24
-rw-r--r--gae/frontend/src/app/model/device_wrapper.ts21
-rw-r--r--gae/frontend/src/app/model/filter_condition.ts24
-rw-r--r--gae/frontend/src/app/model/filter_item.ts22
-rw-r--r--gae/frontend/src/app/model/host.ts25
-rw-r--r--gae/frontend/src/app/model/host_wrapper.ts23
-rw-r--r--gae/frontend/src/app/model/job.ts66
-rw-r--r--gae/frontend/src/app/model/job_wrapper.ts21
-rw-r--r--gae/frontend/src/app/model/lab.ts23
-rw-r--r--gae/frontend/src/app/model/schedule.ts75
-rw-r--r--gae/frontend/src/app/model/schedule_wrapper.ts21
-rw-r--r--gae/frontend/src/app/model/tslint.json9
-rw-r--r--gae/frontend/src/app/shared/dict.pipe.ts29
-rw-r--r--gae/frontend/src/app/shared/filter/filter.component.html66
-rw-r--r--gae/frontend/src/app/shared/filter/filter.component.scss35
-rw-r--r--gae/frontend/src/app/shared/filter/filter.component.ts107
-rw-r--r--gae/frontend/src/app/shared/navbar/_navbar-theme.scss13
-rw-r--r--gae/frontend/src/app/shared/navbar/navbar.component.html20
-rw-r--r--gae/frontend/src/app/shared/navbar/navbar.component.scss10
-rw-r--r--gae/frontend/src/app/shared/navbar/navbar.component.ts29
-rw-r--r--gae/frontend/src/app/shared/navbar/navbar.ts47
-rw-r--r--gae/frontend/src/app/shared/servicebase.ts41
-rw-r--r--gae/frontend/src/app/shared/vtslab_status.ts58
-rw-r--r--gae/frontend/src/browserslist5
-rw-r--r--gae/frontend/src/environments/environment.prod.ts4
-rw-r--r--gae/frontend/src/environments/environment.ts4
-rw-r--r--gae/frontend/src/favicon.icobin5430 -> 0 bytes
-rw-r--r--gae/frontend/src/index.html15
-rw-r--r--gae/frontend/src/karma.conf.js31
-rw-r--r--gae/frontend/src/main.ts12
-rw-r--r--gae/frontend/src/polyfills.ts5
-rw-r--r--gae/frontend/src/styles.scss54
-rw-r--r--gae/frontend/src/styles/_app-theme.scss14
-rw-r--r--gae/frontend/src/styles/_apply-theme.scss5
-rw-r--r--gae/frontend/src/styles/_blue-theme.scss34
-rw-r--r--gae/frontend/src/test.ts20
-rw-r--r--gae/frontend/src/tsconfig.app.json12
-rw-r--r--gae/frontend/src/tsconfig.spec.json19
-rw-r--r--gae/frontend/src/tslint.json17
-rw-r--r--gae/frontend/tsconfig.json20
-rw-r--r--gae/frontend/tslint.json130
-rw-r--r--gae/hostv1openapi.json243
-rw-r--r--gae/index.yaml112
-rw-r--r--gae/jobv1openapi.json718
-rw-r--r--gae/labv1openapi.json408
-rw-r--r--gae/queue.yaml18
-rw-r--r--gae/requirements.txt6
-rw-r--r--gae/schedulev1openapi.json545
-rwxr-xr-xgae/script/build.sh37
-rwxr-xr-xgae/script/create-datastore.sh17
-rwxr-xr-xgae/script/deploy-endpoint.sh36
-rwxr-xr-xgae/script/deploy-webapp.sh91
-rwxr-xr-xgae/script/install-pip.sh17
-rw-r--r--gae/testing/README.md16
-rw-r--r--gae/testing/e2e_test.py129
-rw-r--r--gae/testing/requirements-dev.txt1
-rwxr-xr-xgae/testing/test-endpoint.sh9
-rw-r--r--gae/testing/test_e2e.py32
-rw-r--r--gae/webapp/__init__.py0
-rw-r--r--gae/webapp/src/__init__.py0
-rw-r--r--gae/webapp/src/endpoint/__init__.py0
-rw-r--r--gae/webapp/src/endpoint/build_info.py95
-rw-r--r--gae/webapp/src/endpoint/build_info_test.py139
-rw-r--r--gae/webapp/src/endpoint/endpoint_base.py330
-rw-r--r--gae/webapp/src/endpoint/endpoint_base_test.py256
-rw-r--r--gae/webapp/src/endpoint/host_info.py134
-rw-r--r--gae/webapp/src/endpoint/host_info_test.py93
-rw-r--r--gae/webapp/src/endpoint/job_queue.py206
-rw-r--r--gae/webapp/src/endpoint/job_queue_test.py158
-rw-r--r--gae/webapp/src/endpoint/lab_info.py182
-rw-r--r--gae/webapp/src/endpoint/lab_info_test.py137
-rw-r--r--gae/webapp/src/endpoint/schedule_info.py218
-rw-r--r--gae/webapp/src/endpoint/schedule_info_test.py126
-rw-r--r--gae/webapp/src/endpoint_main.py32
-rw-r--r--gae/webapp/src/handlers/__init__.py0
-rw-r--r--gae/webapp/src/handlers/base.py215
-rw-r--r--gae/webapp/src/handlers/errors.py80
-rw-r--r--gae/webapp/src/proto/__init__.py0
-rw-r--r--gae/webapp/src/proto/model.py449
-rw-r--r--gae/webapp/src/scheduler/__init__.py0
-rw-r--r--gae/webapp/src/scheduler/device_heartbeat.py93
-rw-r--r--gae/webapp/src/scheduler/job_heartbeat.py95
-rw-r--r--gae/webapp/src/scheduler/job_heartbeat_test.py126
-rw-r--r--gae/webapp/src/scheduler/periodic.py54
-rw-r--r--gae/webapp/src/scheduler/schedule_worker.py549
-rw-r--r--gae/webapp/src/scheduler/schedule_worker_test.py581
-rw-r--r--gae/webapp/src/tasks/__init__.py0
-rw-r--r--gae/webapp/src/tasks/indexing.py185
-rw-r--r--gae/webapp/src/tasks/indexing_test.py191
-rw-r--r--gae/webapp/src/tasks/removing_outdated_devices.py37
-rw-r--r--gae/webapp/src/tasks/removing_outdated_devices_test.py111
-rw-r--r--gae/webapp/src/testing/__init__.py0
-rw-r--r--gae/webapp/src/testing/unittest_base.py347
-rw-r--r--gae/webapp/src/utils/__init__.py0
-rw-r--r--gae/webapp/src/utils/datetime_util.py39
-rw-r--r--gae/webapp/src/utils/email_util.py295
-rw-r--r--gae/webapp/src/utils/logger.py54
-rw-r--r--gae/webapp/src/utils/model_util.py56
-rw-r--r--gae/webapp/src/utils/model_util_test.py170
-rw-r--r--gae/webapp/src/vtslab_status.py137
-rw-r--r--gae/webapp/src/webapp_main.py65
-rw-r--r--gae/webapp/src/worker_main.py26
-rw-r--r--gae/worker.yaml22
-rw-r--r--proto/GreenBuildScheduleConfigMessage.proto81
-rw-r--r--proto/GreenBuildScheduleConfigMessage_pb2.py261
-rw-r--r--proto/TestLabConfigMessage.proto59
-rw-r--r--proto/TestLabConfigMessage_pb2.py226
-rw-r--r--proto/TestScheduleConfigMessage.proto131
-rw-r--r--proto/TestScheduleConfigMessage_pb2.py394
-rw-r--r--proto/__init__.py0
-rwxr-xr-xscript/build-python.sh27
-rwxr-xr-xscript/pack-gae.sh47
-rwxr-xr-xscript/run-unittest.sh26
187 files changed, 0 insertions, 25817 deletions
diff --git a/METADATA b/METADATA
deleted file mode 100644
index d97975c..0000000
--- a/METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-third_party {
- license_type: NOTICE
-}
diff --git a/OWNERS b/OWNERS
deleted file mode 100644
index 2132cd7..0000000
--- a/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-yim@google.com
-dchon@google.com
-hyunwooko@google.com
-jongmok@google.com
-younggyu@google.com
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
deleted file mode 100644
index 7049c8c..0000000
--- a/PREUPLOAD.cfg
+++ /dev/null
@@ -1,9 +0,0 @@
-[Builtin Hooks]
-clang_format = true
-
-[Builtin Hooks Options]
-clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp,java
-
-[Hook Scripts]
-test_serving_unittests = ${REPO_ROOT}/test/framework/script/run-unittest.sh
-
diff --git a/__init__.py b/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/__init__.py
+++ /dev/null
diff --git a/configs/global/Android.mk b/configs/global/Android.mk
deleted file mode 100644
index aba3244..0000000
--- a/configs/global/Android.mk
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-vti-global-config-prod-zip :=
-vti-global-config-test-zip :=
-
-dirs := $(strip \
- $(wildcard test/vti/test_serving/configs/global/prod) \
- $(wildcard vendor/google_vts/configs/global/prod))
-ifdef dirs
-vti-global-config-prod-zip := $(HOST_OUT)/vti-global-config/vti-global-config-prod.zip
-$(vti-global-config-prod-zip): $(SOONG_ZIP) $(call find-files-in-subdirs,.,"*.*_config", $(dirs))
- @echo "build vti config package: $@"
- $(hide) mkdir -p $(dir $@)
- $(hide) rm -f $@
- $(hide) find test/vti/test_serving/configs/global/prod/ -name '*.*_config' | sort > $@.list
- $(hide) find vendor/google_vts/configs/global/prod/ -name '*.*_config' | sort > $@.list.vendor
- $(hide) $(SOONG_ZIP) -d -o $@ -C test/vti/test_serving/configs/global -l $@.list \
- -C vendor/google_vts/configs/global -l $@.list.vendor
- $(hide) rm -f $@.list $@.list.vendor
-endif
-
-dirs := $(strip \
- $(wildcard test/vti/test_serving/configs/global/test) \
- $(wildcard vendor/google_vts/configs/global/test))
-ifdef dirs
-vti-global-config-test-zip := $(HOST_OUT)/vti-global-config/vti-global-config-test.zip
-$(vti-global-config-test-zip): $(SOONG_ZIP) $(call find-files-in-subdirs,.,"*.*_config", $(dirs))
- @echo "build vti config package: $@"
- $(hide) mkdir -p $(dir $@)
- $(hide) rm -f $@
- $(hide) find test/vti/test_serving/configs/global/test/ -name '*.*_config' | sort > $@.list
- $(hide) find vendor/google_vts/configs/global/test/ -name '*.*_config' | sort > $@.list.vendor
- $(hide) $(SOONG_ZIP) -d -o $@ -C test/vti/test_serving/configs/global -l $@.list \
- -C vendor/google_vts/configs/global -l $@.list.vendor
- $(hide) rm -f $@.list $@.list.vendor
-endif
-
-.PHONY: vti-global-config
-vti-global-config: $(vti-global-config-prod-zip) $(vti-global-config-test-zip)
-$(call dist-for-goals, vti-global-config, $(vti-global-config-prod-zip) $(vti-global-config-test-zip))
-
-.PHONY: vti-config
-vti-config: vti-global-config
-
-.PHONY: vti
-vti: vti-config
-
-.PHONY: vts
-vts: vti-config
diff --git a/configs/infra/prod/androidtestcenter/bots.cfg b/configs/infra/prod/androidtestcenter/bots.cfg
deleted file mode 100644
index d48675f..0000000
--- a/configs/infra/prod/androidtestcenter/bots.cfg
+++ /dev/null
@@ -1,17 +0,0 @@
-# Instance: androidtestcenter (swarming-prod)
-#
-# Schema: BotsCfg message in
-# https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/proto/bots.proto
-
-trusted_dimensions: "pool"
-bot_group {
- bot_id_prefix: "homedemo"
- owners: "yim@google.com"
- auth {
- require_luci_machine_token: false
- ip_whitelist: "vtslab-swarming-bots"
- }
- dimensions: "pool:home-demo"
- bot_config_script: "home_bot_config.py"
-}
-
diff --git a/configs/infra/prod/androidtestcenter/scripts/home_bot_config.py b/configs/infra/prod/androidtestcenter/scripts/home_bot_config.py
deleted file mode 100644
index fe078fa..0000000
--- a/configs/infra/prod/androidtestcenter/scripts/home_bot_config.py
+++ /dev/null
@@ -1,340 +0,0 @@
-# coding: utf-8
-# Copyright 2013 The LUCI Authors. All rights reserved.
-# Use of this source code is governed under the Apache License, Version 2.0
-# that can be found in the LICENSE file.
-"""bot_config for swarming bots running in Home CI.
-
-A copy of this file is downloaded to every swarming bot automatically.
-Updates to this file are propogated to bots within ~10 minutes.
-
-Prerequisites:
- - bot has eurtest_libs installed via: cipd install home_internal/eurtest_libs
- - eurtest_libs directory is in PYTHONPATH
-
-There's 3 types of functions in this file:
- - get_*() to return properties to describe this bot.
- - on_*() as hooks based on events happening on the bot.
- - setup_*() to setup global state on the host.
-"""
-
-import collections
-import json
-import logging
-import os
-import re
-import sys
-import time
-
-from api import os_utilities
-from api import platforms
-
-# Hack to de-prioritize sys.path variables that bot_code imports which are
-# incompatible with the libraries we're importing below.
-# see https://crbug.com/758609
-sys.path.sort(key=lambda x: 'swarm_env' not in x)
-# each bot must be run in a virtualenv that has eurtest_libs in PYTHONPATH
-try:
- from eurtest.device import device as device_lib
- from utilities import ssh_helper
-except ImportError as e:
- sys.stderr.write('Exception: %s\n' % e)
- sys.stderr.write('sys.path:\n%s' % str(sys.path))
- # Temporary while debugging issue
- import google
- print 'google.__path__: %s' % str(google.__path__)
- raise
-
-# Unused argument 'bot' - pylint: disable=W0613
-DeviceBot = collections.namedtuple('DeviceBot', 'dimensions state')
-
-
-def device(device_type, ip, groups=None, nic=None, serial=None, extra_state=None):
- if not hasattr(ip, '__iter__'):
- ip = [ip]
- dimensions = {
- u'device_ip': ip,
- u'device_type': [device_type],
- u'group': groups or ['COMMON'],
- u'nic': [nic or 'ethernet'],
- }
- # You can't advertise a key that cannot be selected,
- # so only set a dimension key if the value is not None
- if serial:
- dimensions[u'serial'] = [serial]
- if len(ip) > 1:
- dimensions[u'group'].append('multiconfig_box')
- return DeviceBot(dimensions, extra_state)
-
-_BOT_DEVICE_MAP = {
- ### home-demo pool ### - enforced via bot name prefix
- 'homedemo--1': device('assistantdefault', '1.2.3.4', ['abc_test']),
-}
-
-# global for caching device properties gathered dynamically during runtime
-_DEVICE = None
-
-### Helper Methods
-
-
-class SSHError(Exception):
- pass
-
-
-class Device(object):
- """Retrieves device property information for a device over SSH."""
- # amount of time (secs) until state is due for a refresh
- _STALE_STATE_DELTA = 60
-
- def __init__(self, device_ip, bot_id):
- self.device_ip = device_ip
- self.bot_id = bot_id
- self._device_client = device_lib.Device(
- ethernet_ip=self.device_ip)
- self._device_client.UseSsh()
- self._last_connect_succeeded = False
- self._properties = {}
- self._stale_state_ts = 0
-
- @property
- def build_fingerprint(self):
- return self.properties.get('ro.build.fingerprint', None)
-
- @property
- def hardware(self):
- return self.properties.get('ro.hardware', None)
-
- @property
- def is_reachable(self):
- """Checks if device is reachable over ssh."""
- if self._properties is None or time.time() > self._stale_state_ts:
- self._properties = self._fetch_properties()
- return self._last_connect_succeeded
-
- @property
- def product(self):
- return self.properties.get('ro.build.product', None)
-
- @property
- def properties(self):
- """Returns all of the last-known device properties as a dict."""
- if self._properties is None or time.time() > self._stale_state_ts:
- try:
- # Keep last-known properties when SSHError is raised
- self._properties = self._fetch_properties()
- except SSHError as e:
- logging.exception(e)
- return self._properties
-
- def _exec_ssh_cmd(self, cmd):
- """Executes the given cmd against the device over SSH.
- Arguments:
- - cmd: the command to be run on the device over ssh.
- Returns:
- stdout of cmd output
- Raises:
- SSHError: upon ssh cmd exec failure
- """
- # Temporary: fetch device properties from static local file when present.
- # This let's us demo what our swarm bots will look like, even though the
- # demo host ('voyager') is on a lab network in WAT that can't reach the
- # MTV devices over ssh. The real device properties are fetched over ssh
- # by a script on Corp and copied to the swarm host before starting bots.
- # TODO(jonesmi): remove this temporary workaround when bots run in MTV lab
- bot_common_dir = os.getenv('BOT_COMMON_DIR')
- if bot_common_dir:
- props_file = os.path.join(bot_common_dir, '%s.props' % self.bot_id)
- if os.path.isfile(props_file):
- with open(props_file, 'r') as f:
- # pretend that we read this from SSH connection
- self._last_connect_succeeded = True
- return f.read()
- try:
- if self._device_client.Cmd(cmd, timeout_secs=30):
- self._last_connect_succeeded = True
- return self._device_client.GetCmdOutput()
- else:
- self._last_connect_succeeded = False
- raise SSHError('failed to execute cmd over ssh: %s' % cmd)
- except ssh_helper.CommandThreadTimeoutError:
- self._last_connect_succeeded = False
- raise SSHError('timeout when waiting for ssh connect: %s' % cmd)
-
- def _fetch_properties(self):
- """Fetches device properties over ssh using getprop command."""
- self._stale_state_ts = time.time() + self._STALE_STATE_DELTA
- properties = {}
- stdout = self._exec_ssh_cmd('getprop')
- for line in stdout.strip().split('\n'):
- match = re.match(r'\[(.*)\]: \[(.*)\]', line)
- if match:
- properties[match.group(1)] = match.group(2)
- return properties
-
-
-### _get* Hooks
-def get_dimensions(bot):
- # pylint: disable=line-too-long
- """Returns dict with the bot's dimensions.
- The dimensions are what are used to select the bot that can run each task.
- The bot id will be automatically selected based on the hostname with
- os_utilities.get_dimensions(). If you want something more special, specify it
- in your bot_config.py and override the item 'id'.
- The dimensions returned here will be joined with server defined dimensions
- (extracted from bots.cfg config file based on the bot id). Server defined
- dimensions override the ones provided by the bot. See bot.Bot.dimensions for
- more information.
- See https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md.
- Arguments:
- - bot: bot.Bot instance or None. See ../api/bot.py.
- """
- dimensions = os_utilities.get_dimensions()
- # The bot base directory is formatted like <HOME>/bots/<Id>
- id = '%s--%s' % (
- os_utilities.get_hostname_short(),
- os.path.basename(bot.base_dir))
- dimensions[u'id'] = [id]
- if id in _BOT_DEVICE_MAP:
- dimensions.update(_BOT_DEVICE_MAP[id].dimensions)
- global _DEVICE
- if not _DEVICE:
- device_ip = dimensions[u'device_ip']
- # use first device_ip in list of device IPs for pulling device attributes
- if device_ip:
- assert isinstance(device_ip, (list, tuple)), repr(device_ip)
- _DEVICE = Device(device_ip[0], id)
- if _DEVICE:
- dimensions[u'build'] = _DEVICE.build_fingerprint,
- dimensions[u'hardware'] = _DEVICE.hardware,
- dimensions[u'product'] = _DEVICE.product,
- # TODO(jonesmi): don't strip these anymore after swarming fix goes in for limit on # dimensions
- del dimensions[u'cores']
- del dimensions[u'cpu']
- del dimensions[u'gpu']
- del dimensions[u'machine_type']
- return dimensions
-
-
-def get_state(bot):
- # pylint: disable=line-too-long
- """Returns dict with a state of the bot reported to the server with each poll.
- It is only for dynamic state that changes while bot is running for information
- for the sysadmins.
- The server can not use this state for immediate scheduling purposes (use
- 'dimensions' for that), but it can use it for maintenance and bookkeeping
- tasks.
- See https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md.
- Arguments:
- - bot: bot.Bot instance or None. See ../api/bot.py.
- """
- state = os_utilities.get_state()
- if _DEVICE:
- state[u'device'] = _DEVICE.properties
- if _DEVICE.bot_id in _BOT_DEVICE_MAP:
- extra_state = _BOT_DEVICE_MAP[_DEVICE.bot_id].state
- if extra_state:
- state[u'device'].update(extra_state)
- if not _DEVICE.is_reachable:
- state[u'quarantined'] = 'device is not reachable'
- return state
-
-
-def get_authentication_headers(bot):
- """Returns authentication headers and their expiration time.
- The returned headers will be passed with each HTTP request to the Swarming
- server (and only Swarming server). The bot will use the returned headers until
- they are close to expiration (usually 6 min, see AUTH_HEADERS_EXPIRATION_SEC
- in remote_client.py), and then it'll attempt to refresh them by calling
- get_authentication_headers again.
- Can be used to implement per-bot authentication. If no headers are returned,
- the server will use only IP whitelist for bot authentication.
- On GCE will use OAuth token of the default GCE service account. It should have
- "User info" API scope enabled (this can be set when starting an instance). The
- server should be configured (via bots.cfg) to trust this account (see
- 'require_service_account' in bots.proto).
- May be called by different threads, but never concurrently.
- Arguments:
- - bot: bot.Bot instance. See ../api/bot.py.
- Returns:
- Tuple (dict with headers or None, unix timestamp of when they expire).
- """
- if platforms.is_gce():
- tok = platforms.gce.oauth2_access_token()
- return {'Authorization': 'Bearer %s' % tok}, time.time() + 5*60
- return (None, None)
-
-
-### on_* Hooks
-def on_bot_shutdown(bot):
- """Hook function called when the bot shuts down, usually rebooting.
- It's a good time to do other kinds of cleanup.
- Arguments:
- - bot: bot.Bot instance. See ../api/bot.py.
- """
- pass
-
-
-def on_handshake(bot):
- """Hook function called when the bot starts, after handshake with the server.
- Here the bot already knows server enforced dimensions (defined in server side
- bots.cfg file).
- This is called right before starting to poll for tasks. It's a good time to
- do some final initialization or cleanup that may depend on server provided
- configuration.
- Arguments:
- - bot: bot.Bot instance. See ../api/bot.py.
- """
- pass
-
-
-def on_before_task(bot, bot_file):
- """Hook function called before running a task.
- It shouldn't do much, since it can't cancel the task so it shouldn't do
- anything too fancy.
- Arguments:
- - bot: bot.Bot instance. See ../api/bot.py.
- - bot_file: Path to file to write information about the state of the bot.
- This file can be used to pass certain info about the bot
- to tasks, such as which connected android devices to run on. See
- https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md#run_isolated
- """
- with open(bot_file, 'wb') as f:
- json.dump(bot.dimensions, f)
-
-
-def on_after_task(bot, failure, internal_failure, dimensions, summary):
- """Hook function called after running a task.
- It is an excellent place to do post-task cleanup of temporary files.
- The default implementation restarts after a task failure or an internal
- failure.
- Arguments:
- - bot: bot.Bot instance. See ../api/bot.py.
- - failure: bool, True if the task failed.
- - internal_failure: bool, True if an internal failure happened.
- - dimensions: dict, Dimensions requested as part of the task.
- - summary: dict, Summary of the task execution.
- """
- # Example code:
- #if failure:
- # bot.restart('Task failure')
- #elif internal_failure:
- # bot.restart('Internal failure')
-
-
-def on_bot_idle(bot, since_last_action):
- """Hook function called once when the bot has been idle; when it has no
- command to execute.
- This is an excellent place to put device in 'cool down' mode or any
- "pre-warming" kind of stuff that could take several seconds to do, that would
- not be appropriate to do in on_after_task(). It could be worth waiting for
- `since_last_action` to be several seconds before doing a more lengthy
- operation.
- This function is called repeatedly until an action is taken (a task, updating,
- etc).
- This is a good place to do "auto reboot" for hardware based bots that are
- rebooted periodically.
- Arguments:
- - bot: bot.Bot instance. See ../api/bot.py.
- - since_last_action: time in second since last action; e.g. amount of time the
- bot has been idle.
- """
- pass
diff --git a/configs/infra/prod/androidtestcenter/settings.cfg b/configs/infra/prod/androidtestcenter/settings.cfg
deleted file mode 100644
index 1f6777b..0000000
--- a/configs/infra/prod/androidtestcenter/settings.cfg
+++ /dev/null
@@ -1,27 +0,0 @@
-# Instance: androidtestcenter (swarming-prod)
-# Browse online: https://androidtestcenter.appspot.com/restricted/config
-#
-# Schema: SettingsCfg message in
-# https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/proto/config.proto
-
-google_analytics: "UA-107546859-1"
-reusable_task_age_secs: 604800
-bot_death_timeout_secs: 600
-enable_ts_monitoring: true
-ui_client_id: "849130811101-pk615h6979i256cb243t2cacjohamkq7.apps.googleusercontent.com"
-display_server_url_template: "https://androidtestcenter.appspot.com/swarming/task/%s"
-isolate {
- default_server: "https://vtslab-isolate-prod.appspot.com"
- default_namespace: "default-gzip"
-}
-mp {
- enabled: true
-}
-auth {
- admins_group: "vtslab-swarming-admins"
- bot_bootstrap_group: "vtslab-swarming-bot-bootstrap"
- privileged_users_group: "vtslab-swarming-privileged-users"
- users_group: "vtslab-swarming-users"
- view_all_bots_group: "vtslab-swarming-view-all-bots"
- view_all_tasks_group: "vtslab-swarming-view-all-tasks"
-}
diff --git a/configs/infra/prod/vtslab-config-prod/acl.cfg b/configs/infra/prod/vtslab-config-prod/acl.cfg
deleted file mode 100644
index 0da0ca1..0000000
--- a/configs/infra/prod/vtslab-config-prod/acl.cfg
+++ /dev/null
@@ -1,9 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-prod.appspot.com/schemas/services/vtslab-config-prod:acl.cfg
-# *** WARNING ***
-# This file is sensitive. project_access_group specifies a super group
-# that has access to all projects, including internal ones.
-# This file is cached in process memory of instances for 10min
-# because it ~never changes.
-admin_group: "vtslab-config-admins"
-project_access_group: "vtslab-config-project-access"
diff --git a/configs/infra/prod/vtslab-config-prod/import.cfg b/configs/infra/prod/vtslab-config-prod/import.cfg
deleted file mode 100644
index d956889..0000000
--- a/configs/infra/prod/vtslab-config-prod/import.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-prod.appspot.com/schemas/services/vtslab-config-prod:import.cfg
-gitiles {
- project_config_default_ref: "refs/heads/infra/config"
- ref_config_default_path: "infra/config"
-}
diff --git a/configs/infra/prod/vtslab-config-prod/projects.cfg b/configs/infra/prod/vtslab-config-prod/projects.cfg
deleted file mode 100644
index 3f00a7d..0000000
--- a/configs/infra/prod/vtslab-config-prod/projects.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-prod.appspot.com/schemas/services/vtslab-config-prod:projects.cfg
-#
-# Please keep the list sorted by project id!
-projects {
- id: "aosp-master-vts"
- config_location {
- url: "https://android.googlesource.com/platform/test/vts/"
- storage_type: GITILES
- }
-}
-
-projects {
- id: "aosp-master-goldfish"
- config_location {
- url: "https://android.googlesource.com/device/generic/goldfish/"
- storage_type: GITILES
- }
-}
diff --git a/configs/infra/prod/vtslab-config-prod/schemas.cfg b/configs/infra/prod/vtslab-config-prod/schemas.cfg
deleted file mode 100644
index 4ba2ae9..0000000
--- a/configs/infra/prod/vtslab-config-prod/schemas.cfg
+++ /dev/null
@@ -1,79 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-prod.appspot.com/schemas/services/vtslab-config-prod:schemas.cfg
-#
-# Please keep this list sorted by schema name.
-#
-################################################################################
-# WARNING: names and urls in this file will be exposed publicly. Do not put
-# internal stuff here!!!
-################################################################################
-################################################################################
-# ref configs
-schemas {
- name: "projects/refs:cq.cfg"
- url: "https://chromium.googlesource.com/chromium/tools/depot_tools/+/master/third_party/cq_client/cq.proto"
-}
-################################################################################
-# project configs
-schemas {
- name: "projects:buildbucket.cfg"
- url: "https://chromium.googlesource.com/infra/infra/+/master/appengine/cr-buildbucket/proto/project_config.proto"
-}
-schemas {
- name: "projects:refs.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/project_config.proto"
-}
-schemas {
- name: "projects:project.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/project_config.proto"
-}
-################################################################################
-# luci-config service schemas
-schemas {
- name: "services/luci-config:acl.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
- name: "services/luci-config:import.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
- name: "services/luci-config:projects.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
- name: "services/luci-config:services.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
- name: "services/luci-config:schemas.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-################################################################################
-# chrome-infra-auth service schemas.
-schemas {
- name: "services/chrome-infra-auth:delegation.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-schemas {
- name: "services/chrome-infra-auth:imports.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-schemas {
- name: "services/chrome-infra-auth:ip_whitelist.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-schemas {
- name: "services/chrome-infra-auth:oauth.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-################################################################################
-# LUCI LogDog service schemas.
-schemas {
- name: "services/luci-logdog:services.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-go/+/master/logdog/api/config/svcconfig/config.proto"
-}
-schemas {
- name: "services/luci-logdog:logdog.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-go/+/master/logdog/api/config/svcconfig/project.proto"
-}
diff --git a/configs/infra/prod/vtslab-config-prod/services.cfg b/configs/infra/prod/vtslab-config-prod/services.cfg
deleted file mode 100644
index a9b22d6..0000000
--- a/configs/infra/prod/vtslab-config-prod/services.cfg
+++ /dev/null
@@ -1,60 +0,0 @@
-# Schema for this file: ServicesCfg message in
-# https://vtslab-config-prod.appspot.com/schemas/services/vtslab-config-prod:services.cfg
-#
-# Please keep the list sorted by id.
-#
-# *** WARNING
-# This file is sensitive. These services may receive contents of any config
-# files for validation purposes, including configs of internal projects.
-# ***
-################################################################################
-# Swarming
-services {
- id: "androidtestcenter"
- owners: "yim@google.com"
- metadata_url: "https://androidtestcenter.appspot.com/_ah/api/config/v1/metadata"
- access: "androidtestcenter@appspot.gserviceaccount.com"
-}
-################################################################################
-# Auth
-services {
- id: "vtslab-auth-prod"
- owners: "yim@google.com"
- metadata_url: "https://vtslab-auth-prod.appspot.com/_ah/api/config/v1/metadata"
- access: "vtslab-auth-prod@appspot.gserviceaccount.com"
-}
-################################################################################
-# Commit Queue
-# services {
-# id: "commit-queue"
-# owners: "yim@google.com"
-# metadata_url: "https://vtslab-cq-prod.appspot.com/api/metadata"
-# }
-################################################################################
-# GCE Backend
-services {
- id: "vtslab-backend-prod"
- owners: "yim@google.com"
- access: "vtslab-backend-prod@appspot.gserviceaccount.com"
-}
-################################################################################
-# LUCI / Isolate Server
-services {
- id: "vtslab-isolate-prod"
- owners: "yim@google.com"
- metadata_url: "https://vtslab-isolate-prod.appspot.com/_ah/api/config/v1/metadata"
- access: "vtslab-isolate-prod@appspot.gserviceaccount.com"
-}
-################################################################################
-# Machine Provider
-services {
- id: "vtslab-machine-prod"
- owners: "yim@google.com"
- access: "vtslab-machine-prod@appspot.gserviceaccount.com"
-}
-################################################################################
-# Doc Indexer
-services {
- id: "vtslab-doc"
- owners: "yim@google.com"
-}
diff --git a/configs/infra/test/androidtestcenter-test/bots.cfg b/configs/infra/test/androidtestcenter-test/bots.cfg
deleted file mode 100644
index d48675f..0000000
--- a/configs/infra/test/androidtestcenter-test/bots.cfg
+++ /dev/null
@@ -1,17 +0,0 @@
-# Instance: androidtestcenter (swarming-prod)
-#
-# Schema: BotsCfg message in
-# https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/proto/bots.proto
-
-trusted_dimensions: "pool"
-bot_group {
- bot_id_prefix: "homedemo"
- owners: "yim@google.com"
- auth {
- require_luci_machine_token: false
- ip_whitelist: "vtslab-swarming-bots"
- }
- dimensions: "pool:home-demo"
- bot_config_script: "home_bot_config.py"
-}
-
diff --git a/configs/infra/test/androidtestcenter-test/scripts/home_bot_config.py b/configs/infra/test/androidtestcenter-test/scripts/home_bot_config.py
deleted file mode 100644
index fe078fa..0000000
--- a/configs/infra/test/androidtestcenter-test/scripts/home_bot_config.py
+++ /dev/null
@@ -1,340 +0,0 @@
-# coding: utf-8
-# Copyright 2013 The LUCI Authors. All rights reserved.
-# Use of this source code is governed under the Apache License, Version 2.0
-# that can be found in the LICENSE file.
-"""bot_config for swarming bots running in Home CI.
-
-A copy of this file is downloaded to every swarming bot automatically.
-Updates to this file are propogated to bots within ~10 minutes.
-
-Prerequisites:
- - bot has eurtest_libs installed via: cipd install home_internal/eurtest_libs
- - eurtest_libs directory is in PYTHONPATH
-
-There's 3 types of functions in this file:
- - get_*() to return properties to describe this bot.
- - on_*() as hooks based on events happening on the bot.
- - setup_*() to setup global state on the host.
-"""
-
-import collections
-import json
-import logging
-import os
-import re
-import sys
-import time
-
-from api import os_utilities
-from api import platforms
-
-# Hack to de-prioritize sys.path variables that bot_code imports which are
-# incompatible with the libraries we're importing below.
-# see https://crbug.com/758609
-sys.path.sort(key=lambda x: 'swarm_env' not in x)
-# each bot must be run in a virtualenv that has eurtest_libs in PYTHONPATH
-try:
- from eurtest.device import device as device_lib
- from utilities import ssh_helper
-except ImportError as e:
- sys.stderr.write('Exception: %s\n' % e)
- sys.stderr.write('sys.path:\n%s' % str(sys.path))
- # Temporary while debugging issue
- import google
- print 'google.__path__: %s' % str(google.__path__)
- raise
-
-# Unused argument 'bot' - pylint: disable=W0613
-DeviceBot = collections.namedtuple('DeviceBot', 'dimensions state')
-
-
-def device(device_type, ip, groups=None, nic=None, serial=None, extra_state=None):
- if not hasattr(ip, '__iter__'):
- ip = [ip]
- dimensions = {
- u'device_ip': ip,
- u'device_type': [device_type],
- u'group': groups or ['COMMON'],
- u'nic': [nic or 'ethernet'],
- }
- # You can't advertise a key that cannot be selected,
- # so only set a dimension key if the value is not None
- if serial:
- dimensions[u'serial'] = [serial]
- if len(ip) > 1:
- dimensions[u'group'].append('multiconfig_box')
- return DeviceBot(dimensions, extra_state)
-
-_BOT_DEVICE_MAP = {
- ### home-demo pool ### - enforced via bot name prefix
- 'homedemo--1': device('assistantdefault', '1.2.3.4', ['abc_test']),
-}
-
-# global for caching device properties gathered dynamically during runtime
-_DEVICE = None
-
-### Helper Methods
-
-
-class SSHError(Exception):
- pass
-
-
-class Device(object):
- """Retrieves device property information for a device over SSH."""
- # amount of time (secs) until state is due for a refresh
- _STALE_STATE_DELTA = 60
-
- def __init__(self, device_ip, bot_id):
- self.device_ip = device_ip
- self.bot_id = bot_id
- self._device_client = device_lib.Device(
- ethernet_ip=self.device_ip)
- self._device_client.UseSsh()
- self._last_connect_succeeded = False
- self._properties = {}
- self._stale_state_ts = 0
-
- @property
- def build_fingerprint(self):
- return self.properties.get('ro.build.fingerprint', None)
-
- @property
- def hardware(self):
- return self.properties.get('ro.hardware', None)
-
- @property
- def is_reachable(self):
- """Checks if device is reachable over ssh."""
- if self._properties is None or time.time() > self._stale_state_ts:
- self._properties = self._fetch_properties()
- return self._last_connect_succeeded
-
- @property
- def product(self):
- return self.properties.get('ro.build.product', None)
-
- @property
- def properties(self):
- """Returns all of the last-known device properties as a dict."""
- if self._properties is None or time.time() > self._stale_state_ts:
- try:
- # Keep last-known properties when SSHError is raised
- self._properties = self._fetch_properties()
- except SSHError as e:
- logging.exception(e)
- return self._properties
-
- def _exec_ssh_cmd(self, cmd):
- """Executes the given cmd against the device over SSH.
- Arguments:
- - cmd: the command to be run on the device over ssh.
- Returns:
- stdout of cmd output
- Raises:
- SSHError: upon ssh cmd exec failure
- """
- # Temporary: fetch device properties from static local file when present.
- # This let's us demo what our swarm bots will look like, even though the
- # demo host ('voyager') is on a lab network in WAT that can't reach the
- # MTV devices over ssh. The real device properties are fetched over ssh
- # by a script on Corp and copied to the swarm host before starting bots.
- # TODO(jonesmi): remove this temporary workaround when bots run in MTV lab
- bot_common_dir = os.getenv('BOT_COMMON_DIR')
- if bot_common_dir:
- props_file = os.path.join(bot_common_dir, '%s.props' % self.bot_id)
- if os.path.isfile(props_file):
- with open(props_file, 'r') as f:
- # pretend that we read this from SSH connection
- self._last_connect_succeeded = True
- return f.read()
- try:
- if self._device_client.Cmd(cmd, timeout_secs=30):
- self._last_connect_succeeded = True
- return self._device_client.GetCmdOutput()
- else:
- self._last_connect_succeeded = False
- raise SSHError('failed to execute cmd over ssh: %s' % cmd)
- except ssh_helper.CommandThreadTimeoutError:
- self._last_connect_succeeded = False
- raise SSHError('timeout when waiting for ssh connect: %s' % cmd)
-
- def _fetch_properties(self):
- """Fetches device properties over ssh using getprop command."""
- self._stale_state_ts = time.time() + self._STALE_STATE_DELTA
- properties = {}
- stdout = self._exec_ssh_cmd('getprop')
- for line in stdout.strip().split('\n'):
- match = re.match(r'\[(.*)\]: \[(.*)\]', line)
- if match:
- properties[match.group(1)] = match.group(2)
- return properties
-
-
-### _get* Hooks
-def get_dimensions(bot):
- # pylint: disable=line-too-long
- """Returns dict with the bot's dimensions.
- The dimensions are what are used to select the bot that can run each task.
- The bot id will be automatically selected based on the hostname with
- os_utilities.get_dimensions(). If you want something more special, specify it
- in your bot_config.py and override the item 'id'.
- The dimensions returned here will be joined with server defined dimensions
- (extracted from bots.cfg config file based on the bot id). Server defined
- dimensions override the ones provided by the bot. See bot.Bot.dimensions for
- more information.
- See https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md.
- Arguments:
- - bot: bot.Bot instance or None. See ../api/bot.py.
- """
- dimensions = os_utilities.get_dimensions()
- # The bot base directory is formatted like <HOME>/bots/<Id>
- id = '%s--%s' % (
- os_utilities.get_hostname_short(),
- os.path.basename(bot.base_dir))
- dimensions[u'id'] = [id]
- if id in _BOT_DEVICE_MAP:
- dimensions.update(_BOT_DEVICE_MAP[id].dimensions)
- global _DEVICE
- if not _DEVICE:
- device_ip = dimensions[u'device_ip']
- # use first device_ip in list of device IPs for pulling device attributes
- if device_ip:
- assert isinstance(device_ip, (list, tuple)), repr(device_ip)
- _DEVICE = Device(device_ip[0], id)
- if _DEVICE:
- dimensions[u'build'] = _DEVICE.build_fingerprint,
- dimensions[u'hardware'] = _DEVICE.hardware,
- dimensions[u'product'] = _DEVICE.product,
- # TODO(jonesmi): don't strip these anymore after swarming fix goes in for limit on # dimensions
- del dimensions[u'cores']
- del dimensions[u'cpu']
- del dimensions[u'gpu']
- del dimensions[u'machine_type']
- return dimensions
-
-
-def get_state(bot):
- # pylint: disable=line-too-long
- """Returns dict with a state of the bot reported to the server with each poll.
- It is only for dynamic state that changes while bot is running for information
- for the sysadmins.
- The server can not use this state for immediate scheduling purposes (use
- 'dimensions' for that), but it can use it for maintenance and bookkeeping
- tasks.
- See https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md.
- Arguments:
- - bot: bot.Bot instance or None. See ../api/bot.py.
- """
- state = os_utilities.get_state()
- if _DEVICE:
- state[u'device'] = _DEVICE.properties
- if _DEVICE.bot_id in _BOT_DEVICE_MAP:
- extra_state = _BOT_DEVICE_MAP[_DEVICE.bot_id].state
- if extra_state:
- state[u'device'].update(extra_state)
- if not _DEVICE.is_reachable:
- state[u'quarantined'] = 'device is not reachable'
- return state
-
-
-def get_authentication_headers(bot):
- """Returns authentication headers and their expiration time.
- The returned headers will be passed with each HTTP request to the Swarming
- server (and only Swarming server). The bot will use the returned headers until
- they are close to expiration (usually 6 min, see AUTH_HEADERS_EXPIRATION_SEC
- in remote_client.py), and then it'll attempt to refresh them by calling
- get_authentication_headers again.
- Can be used to implement per-bot authentication. If no headers are returned,
- the server will use only IP whitelist for bot authentication.
- On GCE will use OAuth token of the default GCE service account. It should have
- "User info" API scope enabled (this can be set when starting an instance). The
- server should be configured (via bots.cfg) to trust this account (see
- 'require_service_account' in bots.proto).
- May be called by different threads, but never concurrently.
- Arguments:
- - bot: bot.Bot instance. See ../api/bot.py.
- Returns:
- Tuple (dict with headers or None, unix timestamp of when they expire).
- """
- if platforms.is_gce():
- tok = platforms.gce.oauth2_access_token()
- return {'Authorization': 'Bearer %s' % tok}, time.time() + 5*60
- return (None, None)
-
-
-### on_* Hooks
-def on_bot_shutdown(bot):
- """Hook function called when the bot shuts down, usually rebooting.
- It's a good time to do other kinds of cleanup.
- Arguments:
- - bot: bot.Bot instance. See ../api/bot.py.
- """
- pass
-
-
-def on_handshake(bot):
- """Hook function called when the bot starts, after handshake with the server.
- Here the bot already knows server enforced dimensions (defined in server side
- bots.cfg file).
- This is called right before starting to poll for tasks. It's a good time to
- do some final initialization or cleanup that may depend on server provided
- configuration.
- Arguments:
- - bot: bot.Bot instance. See ../api/bot.py.
- """
- pass
-
-
-def on_before_task(bot, bot_file):
- """Hook function called before running a task.
- It shouldn't do much, since it can't cancel the task so it shouldn't do
- anything too fancy.
- Arguments:
- - bot: bot.Bot instance. See ../api/bot.py.
- - bot_file: Path to file to write information about the state of the bot.
- This file can be used to pass certain info about the bot
- to tasks, such as which connected android devices to run on. See
- https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md#run_isolated
- """
- with open(bot_file, 'wb') as f:
- json.dump(bot.dimensions, f)
-
-
-def on_after_task(bot, failure, internal_failure, dimensions, summary):
- """Hook function called after running a task.
- It is an excellent place to do post-task cleanup of temporary files.
- The default implementation restarts after a task failure or an internal
- failure.
- Arguments:
- - bot: bot.Bot instance. See ../api/bot.py.
- - failure: bool, True if the task failed.
- - internal_failure: bool, True if an internal failure happened.
- - dimensions: dict, Dimensions requested as part of the task.
- - summary: dict, Summary of the task execution.
- """
- # Example code:
- #if failure:
- # bot.restart('Task failure')
- #elif internal_failure:
- # bot.restart('Internal failure')
-
-
-def on_bot_idle(bot, since_last_action):
- """Hook function called once when the bot has been idle; when it has no
- command to execute.
- This is an excellent place to put device in 'cool down' mode or any
- "pre-warming" kind of stuff that could take several seconds to do, that would
- not be appropriate to do in on_after_task(). It could be worth waiting for
- `since_last_action` to be several seconds before doing a more lengthy
- operation.
- This function is called repeatedly until an action is taken (a task, updating,
- etc).
- This is a good place to do "auto reboot" for hardware based bots that are
- rebooted periodically.
- Arguments:
- - bot: bot.Bot instance. See ../api/bot.py.
- - since_last_action: time in second since last action; e.g. amount of time the
- bot has been idle.
- """
- pass
diff --git a/configs/infra/test/androidtestcenter-test/settings.cfg b/configs/infra/test/androidtestcenter-test/settings.cfg
deleted file mode 100644
index 412349f..0000000
--- a/configs/infra/test/androidtestcenter-test/settings.cfg
+++ /dev/null
@@ -1,27 +0,0 @@
-# Instance: androidtestcenter-test (swarming-test)
-# Browse online: https://androidtestcenter-test.appspot.com/restricted/config
-#
-# Schema: SettingsCfg message in
-# https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/proto/config.proto
-
-google_analytics: "UA-107546859-1"
-reusable_task_age_secs: 604800
-bot_death_timeout_secs: 600
-enable_ts_monitoring: true
-ui_client_id: "819908144382-mktl5tlg4cq9jkqfrqi0lat873itcfpi.apps.googleusercontent.com"
-display_server_url_template: "https://androidtestcenter-test.appspot.com/swarming/task/%s"
-isolate {
- default_server: "https://vtslab-isolate-test.appspot.com"
- default_namespace: "default-gzip"
-}
-mp {
- enabled: true
-}
-auth {
- admins_group: "vtslab-test-swarming-admins"
- bot_bootstrap_group: "vtslab-test-swarming-bot-bootstrap"
- privileged_users_group: "vtslab-test-swarming-privileged-users"
- users_group: "vtslab-test-swarming-users"
- view_all_bots_group: "vtslab-test-swarming-view-all-bots"
- view_all_tasks_group: "vtslab-test-swarming-view-all-tasks"
-}
diff --git a/configs/infra/test/vtslab-config-test/acl.cfg b/configs/infra/test/vtslab-config-test/acl.cfg
deleted file mode 100644
index 0da0ca1..0000000
--- a/configs/infra/test/vtslab-config-test/acl.cfg
+++ /dev/null
@@ -1,9 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-prod.appspot.com/schemas/services/vtslab-config-prod:acl.cfg
-# *** WARNING ***
-# This file is sensitive. project_access_group specifies a super group
-# that has access to all projects, including internal ones.
-# This file is cached in process memory of instances for 10min
-# because it ~never changes.
-admin_group: "vtslab-config-admins"
-project_access_group: "vtslab-config-project-access"
diff --git a/configs/infra/test/vtslab-config-test/import.cfg b/configs/infra/test/vtslab-config-test/import.cfg
deleted file mode 100644
index 6bc8bdc..0000000
--- a/configs/infra/test/vtslab-config-test/import.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-test.appspot.com/schemas/services/vtslab-config-test:import.cfg
-gitiles {
- project_config_default_ref: "refs/heads/infra/config"
- ref_config_default_path: "infra/config"
-}
diff --git a/configs/infra/test/vtslab-config-test/projects.cfg b/configs/infra/test/vtslab-config-test/projects.cfg
deleted file mode 100644
index b8043de..0000000
--- a/configs/infra/test/vtslab-config-test/projects.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-test.appspot.com/schemas/services/vtslab-config-test:projects.cfg
-#
-# Please keep the list sorted by project id!
-projects {
- id: "aosp-master-vts"
- config_location {
- url: "https://android.googlesource.com/platform/test/vts/"
- storage_type: GITILES
- }
-}
-
-projects {
- id: "aosp-master-goldfish"
- config_location {
- url: "https://android.googlesource.com/device/generic/goldfish/"
- storage_type: GITILES
- }
-}
diff --git a/configs/infra/test/vtslab-config-test/schemas.cfg b/configs/infra/test/vtslab-config-test/schemas.cfg
deleted file mode 100644
index 91d34c7..0000000
--- a/configs/infra/test/vtslab-config-test/schemas.cfg
+++ /dev/null
@@ -1,79 +0,0 @@
-# Schema for this file:
-# https://vtslab-config-test.appspot.com/schemas/services/vtslab-config-test:schemas.cfg
-#
-# Please keep this list sorted by schema name.
-#
-################################################################################
-# WARNING: names and urls in this file will be exposed publicly. Do not put
-# internal stuff here!!!
-################################################################################
-################################################################################
-# ref configs
-schemas {
- name: "projects/refs:cq.cfg"
- url: "https://chromium.googlesource.com/chromium/tools/depot_tools/+/master/third_party/cq_client/cq.proto"
-}
-################################################################################
-# project configs
-schemas {
- name: "projects:buildbucket.cfg"
- url: "https://chromium.googlesource.com/infra/infra/+/master/appengine/cr-buildbucket/proto/project_config.proto"
-}
-schemas {
- name: "projects:refs.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/project_config.proto"
-}
-schemas {
- name: "projects:project.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/project_config.proto"
-}
-################################################################################
-# luci-config service schemas
-schemas {
- name: "services/luci-config:acl.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
- name: "services/luci-config:import.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
- name: "services/luci-config:projects.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
- name: "services/luci-config:services.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-schemas {
- name: "services/luci-config:schemas.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/components/components/config/proto/service_config.proto"
-}
-################################################################################
-# chrome-infra-auth service schemas.
-schemas {
- name: "services/chrome-infra-auth:delegation.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-schemas {
- name: "services/chrome-infra-auth:imports.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-schemas {
- name: "services/chrome-infra-auth:ip_whitelist.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-schemas {
- name: "services/chrome-infra-auth:oauth.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/auth_service/proto/config.proto"
-}
-################################################################################
-# LUCI LogDog service schemas.
-schemas {
- name: "services/luci-logdog:services.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-go/+/master/logdog/api/config/svcconfig/config.proto"
-}
-schemas {
- name: "services/luci-logdog:logdog.cfg"
- url: "https://chromium.googlesource.com/infra/luci/luci-go/+/master/logdog/api/config/svcconfig/project.proto"
-}
diff --git a/configs/infra/test/vtslab-config-test/services.cfg b/configs/infra/test/vtslab-config-test/services.cfg
deleted file mode 100644
index 3377123..0000000
--- a/configs/infra/test/vtslab-config-test/services.cfg
+++ /dev/null
@@ -1,60 +0,0 @@
-# Schema for this file: ServicesCfg message in
-# https://vtslab-config-test.appspot.com/schemas/services/vtslab-config-test:services.cfg
-#
-# Please keep the list sorted by id.
-#
-# *** WARNING
-# This file is sensitive. These services may receive contents of any config
-# files for validation purposes, including configs of internal projects.
-# ***
-################################################################################
-# Swarming
-services {
- id: "androidtestcenter-test"
- owners: "yim@google.com"
- metadata_url: "https://androidtestcenter-test.appspot.com/_ah/api/config/v1/metadata"
- access: "androidtestcenter-test@appspot.gserviceaccount.com"
-}
-################################################################################
-# Auth
-services {
- id: "vtslab-auth-test"
- owners: "yim@google.com"
- metadata_url: "https://vtslab-auth-test.appspot.com/_ah/api/config/v1/metadata"
- access: "vtslab-auth-test@appspot.gserviceaccount.com"
-}
-################################################################################
-# Commit Queue
-# services {
-# id: "commit-queue"
-# owners: "yim@google.com"
-# metadata_url: "https://vtslab-cq-test.appspot.com/api/metadata"
-# }
-################################################################################
-# GCE Backend
-services {
- id: "vtslab-backend-test"
- owners: "yim@google.com"
- access: "vtslab-backend-test@appspot.gserviceaccount.com"
-}
-################################################################################
-# LUCI / Isolate Server
-services {
- id: "vtslab-isolate-test"
- owners: "yim@google.com"
- metadata_url: "https://vtslab-isolate-test.appspot.com/_ah/api/config/v1/metadata"
- access: "vtslab-isolate-test@appspot.gserviceaccount.com"
-}
-################################################################################
-# Machine Provider
-services {
- id: "vtslab-machine-test"
- owners: "yim@google.com"
- access: "vtslab-machine-test@appspot.gserviceaccount.com"
-}
-################################################################################
-# Doc Indexer
-services {
- id: "vtslab-doc"
- owners: "yim@google.com"
-}
diff --git a/gae/.gitignore b/gae/.gitignore
deleted file mode 100644
index 9d1699c..0000000
--- a/gae/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-webapp/static/**
diff --git a/gae/app.yaml b/gae/app.yaml
deleted file mode 100644
index 374c07c..0000000
--- a/gae/app.yaml
+++ /dev/null
@@ -1,57 +0,0 @@
-runtime: python27
-api_version: 1
-threadsafe: true
-
-# [START env_vars]
-env_variables:
- ENDPOINTS_SERVICE_NAME: vtslab-schedule-prod.appspot.com
- ENDPOINTS_SERVICE_VERSION: 2018-09-03r0
- SESSION_SECRET_KEY: ''
-# [END env_vars]
-
-# [START builtins]
-builtins:
-# [END builtins]
-
-# [START handlers]
-handlers:
-# The endpoints handler must be mapped to /_ah/api.
-- url: /_ah/api/.*
- script: webapp.src.endpoint_main.api
-
-- url: /(.*\.(html|js|css|txt|ico))
- static_files: webapp/static/\1
- upload: webapp/static/(.*\.(html|js|css|txt|ico))
-
-- url: /((build|device|job|lab|schedule)([?&/].*)?)?
- static_files: webapp/static/index.html
- upload: webapp/static/index.html
-
-- url: /.*
- script: webapp.src.webapp_main.app
-# [END handlers]
-
-# [START libraries]
-libraries:
-- name: webapp2
- version: latest
-- name: jinja2
- version: latest
-- name: pycrypto
- version: 2.6
-- name: ssl
- version: 2.7.11
-# [END libraries]
-
-# [START exclude]
-skip_files:
-- ^(.*/)?#.*#$
-- ^(.*/)?.*~$
-- ^(.*/)?.*\.py[co]$
-- ^(.*/)?.*/RCS/.*$
-- ^(.*/)?\..*$
-- ^script/*$
-- testrunner.py
-- .*_test.py$
-- ^(.*/)?frontend/(.*)
-# [END exclude]
diff --git a/gae/appengine_config.py b/gae/appengine_config.py
deleted file mode 100644
index 1003e5e..0000000
--- a/gae/appengine_config.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# appengine_config.py
-from google.appengine.ext import vendor
-
-# Add any libraries install in the "lib" folder.
-vendor.add('lib')
diff --git a/gae/buildv1openapi.json b/gae/buildv1openapi.json
deleted file mode 100644
index a59a137..0000000
--- a/gae/buildv1openapi.json
+++ /dev/null
@@ -1,194 +0,0 @@
-{
- "basePath": "/_ah/api",
- "consumes": [
- "application/json"
- ],
- "definitions": {
- "WebappSrcProtoModelBuildInfoMessage": {
- "properties": {
- "artifact_type": {
- "type": "string"
- },
- "artifacts": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "build_id": {
- "type": "string"
- },
- "build_target": {
- "type": "string"
- },
- "build_type": {
- "type": "string"
- },
- "manifest_branch": {
- "type": "string"
- },
- "signed": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelBuildResponseMessage": {
- "properties": {
- "builds": {
- "description": "A message for representing an individual build entry.",
- "items": {
- "$ref": "#/definitions/WebappSrcProtoModelBuildInfoMessage"
- },
- "type": "array"
- },
- "has_next": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelCountRequestMessage": {
- "properties": {
- "filter": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelCountResponseMessage": {
- "properties": {
- "count": {
- "format": "int64",
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDefaultResponse": {
- "properties": {
- "return_code": {
- "enum": [
- "SUCCESS",
- "FAIL"
- ],
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelGetRequestMessage": {
- "properties": {
- "direction": {
- "type": "string"
- },
- "filter": {
- "type": "string"
- },
- "offset": {
- "format": "int64",
- "type": "string"
- },
- "size": {
- "format": "int64",
- "type": "string"
- },
- "sort": {
- "type": "string"
- }
- },
- "type": "object"
- }
- },
- "host": "vtslab-schedule-prod.appspot.com",
- "info": {
- "description": "Endpoint API for build_info.",
- "title": "build",
- "version": "v1"
- },
- "paths": {
- "/build/v1/count": {
- "post": {
- "operationId": "BuildInfoApi_count",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelCountRequestMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelCountResponseMessage"
- }
- }
- }
- }
- },
- "/build/v1/get": {
- "post": {
- "operationId": "BuildInfoApi_get",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelGetRequestMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelBuildResponseMessage"
- }
- }
- }
- }
- },
- "/build/v1/set": {
- "post": {
- "operationId": "BuildInfoApi_set",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelBuildInfoMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
- }
- }
- }
- }
- }
- },
- "produces": [
- "application/json"
- ],
- "schemes": [
- "https"
- ],
- "securityDefinitions": {
- "google_id_token": {
- "authorizationUrl": "",
- "flow": "implicit",
- "type": "oauth2",
- "x-google-issuer": "https://accounts.google.com",
- "x-google-jwks_uri": "https://www.googleapis.com/oauth2/v3/certs"
- }
- },
- "swagger": "2.0",
- "x-google-api-name": "build"
-} \ No newline at end of file
diff --git a/gae/cron.yaml b/gae/cron.yaml
deleted file mode 100644
index e4d4a71..0000000
--- a/gae/cron.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-cron:
-- description: "test scheduler job"
- url: /tasks/schedule
- schedule: every 5 minutes
-- description: "device_heartbeat"
- url: /tasks/device_heartbeat
- schedule: every 1 minutes
-- description: "job_heartbeat"
- url: /tasks/job_heartbeat
- schedule: every 1 minutes
-- description: "remove_outdated_devices"
- url: /tasks/remove_outdated_devices
- schedule: every 1 hours
diff --git a/gae/favicon.ico b/gae/favicon.ico
deleted file mode 100644
index 42506c0..0000000
--- a/gae/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/gae/frontend/.editorconfig b/gae/frontend/.editorconfig
deleted file mode 100644
index 6e87a00..0000000
--- a/gae/frontend/.editorconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-# Editor configuration, see http://editorconfig.org
-root = true
-
-[*]
-charset = utf-8
-indent_style = space
-indent_size = 2
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*.md]
-max_line_length = off
-trim_trailing_whitespace = false
diff --git a/gae/frontend/.gitignore b/gae/frontend/.gitignore
deleted file mode 100644
index ee5c9d8..0000000
--- a/gae/frontend/.gitignore
+++ /dev/null
@@ -1,39 +0,0 @@
-# See http://help.github.com/ignore-files/ for more about ignoring files.
-
-# compiled output
-/dist
-/tmp
-/out-tsc
-
-# dependencies
-/node_modules
-
-# IDEs and editors
-/.idea
-.project
-.classpath
-.c9/
-*.launch
-.settings/
-*.sublime-workspace
-
-# IDE - VSCode
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
-
-# misc
-/.sass-cache
-/connect.lock
-/coverage
-/libpeerconnection.log
-npm-debug.log
-yarn-error.log
-testem.log
-/typings
-
-# System Files
-.DS_Store
-Thumbs.db
diff --git a/gae/frontend/MODULE_LICENSE_MIT b/gae/frontend/MODULE_LICENSE_MIT
deleted file mode 100644
index e69de29..0000000
--- a/gae/frontend/MODULE_LICENSE_MIT
+++ /dev/null
diff --git a/gae/frontend/NOTICE b/gae/frontend/NOTICE
deleted file mode 100644
index 40040b9..0000000
--- a/gae/frontend/NOTICE
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT License
-
-Copyright (c) 2014-2018 Google, Inc. http://angular.io
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
diff --git a/gae/frontend/angular.json b/gae/frontend/angular.json
deleted file mode 100644
index ca84a43..0000000
--- a/gae/frontend/angular.json
+++ /dev/null
@@ -1,127 +0,0 @@
-{
- "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
- "version": 1,
- "newProjectRoot": "projects",
- "projects": {
- "frontend": {
- "root": "",
- "sourceRoot": "src",
- "projectType": "application",
- "prefix": "app",
- "schematics": {},
- "architect": {
- "build": {
- "builder": "@angular-devkit/build-angular:browser",
- "options": {
- "outputPath": "dist",
- "index": "src/index.html",
- "main": "src/main.ts",
- "polyfills": "src/polyfills.ts",
- "tsConfig": "src/tsconfig.app.json",
- "assets": [
- "src/favicon.ico",
- "src/assets"
- ],
- "styles": [
- "src/styles.scss"
- ],
- "scripts": []
- },
- "configurations": {
- "production": {
- "fileReplacements": [
- {
- "replace": "src/environments/environment.ts",
- "with": "src/environments/environment.prod.ts"
- }
- ],
- "optimization": true,
- "outputHashing": "all",
- "sourceMap": false,
- "extractCss": true,
- "namedChunks": false,
- "aot": true,
- "extractLicenses": true,
- "vendorChunk": false,
- "buildOptimizer": true
- }
- }
- },
- "serve": {
- "builder": "@angular-devkit/build-angular:dev-server",
- "options": {
- "browserTarget": "frontend:build"
- },
- "configurations": {
- "production": {
- "browserTarget": "frontend:build:production"
- }
- }
- },
- "extract-i18n": {
- "builder": "@angular-devkit/build-angular:extract-i18n",
- "options": {
- "browserTarget": "frontend:build"
- }
- },
- "test": {
- "builder": "@angular-devkit/build-angular:karma",
- "options": {
- "main": "src/test.ts",
- "polyfills": "src/polyfills.ts",
- "tsConfig": "src/tsconfig.spec.json",
- "karmaConfig": "src/karma.conf.js",
- "styles": [
- "src/styles.scss"
- ],
- "scripts": [],
- "assets": [
- "src/favicon.ico",
- "src/assets"
- ]
- }
- },
- "lint": {
- "builder": "@angular-devkit/build-angular:tslint",
- "options": {
- "tsConfig": [
- "src/tsconfig.app.json",
- "src/tsconfig.spec.json"
- ],
- "exclude": [
- "**/node_modules/**"
- ]
- }
- }
- }
- },
- "frontend-e2e": {
- "root": "e2e/",
- "projectType": "application",
- "architect": {
- "e2e": {
- "builder": "@angular-devkit/build-angular:protractor",
- "options": {
- "protractorConfig": "e2e/protractor.conf.js",
- "devServerTarget": "frontend:serve"
- },
- "configurations": {
- "production": {
- "devServerTarget": "frontend:serve:production"
- }
- }
- },
- "lint": {
- "builder": "@angular-devkit/build-angular:tslint",
- "options": {
- "tsConfig": "e2e/tsconfig.e2e.json",
- "exclude": [
- "**/node_modules/**"
- ]
- }
- }
- }
- }
- },
- "defaultProject": "frontend"
-}
diff --git a/gae/frontend/e2e/protractor.conf.js b/gae/frontend/e2e/protractor.conf.js
deleted file mode 100644
index 86776a3..0000000
--- a/gae/frontend/e2e/protractor.conf.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Protractor configuration file, see link for more information
-// https://github.com/angular/protractor/blob/master/lib/config.ts
-
-const { SpecReporter } = require('jasmine-spec-reporter');
-
-exports.config = {
- allScriptsTimeout: 11000,
- specs: [
- './src/**/*.e2e-spec.ts'
- ],
- capabilities: {
- 'browserName': 'chrome'
- },
- directConnect: true,
- baseUrl: 'http://localhost:4200/',
- framework: 'jasmine',
- jasmineNodeOpts: {
- showColors: true,
- defaultTimeoutInterval: 30000,
- print: function() {}
- },
- onPrepare() {
- require('ts-node').register({
- project: require('path').join(__dirname, './tsconfig.e2e.json')
- });
- jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
- }
-}; \ No newline at end of file
diff --git a/gae/frontend/e2e/src/app.e2e-spec.ts b/gae/frontend/e2e/src/app.e2e-spec.ts
deleted file mode 100644
index 87525cf..0000000
--- a/gae/frontend/e2e/src/app.e2e-spec.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { AppPage } from './app.po';
-
-describe('workspace-project App', () => {
- let page: AppPage;
-
- beforeEach(() => {
- page = new AppPage();
- });
-
- it('should display welcome message', () => {
- page.navigateTo();
- expect(page.getParagraphText()).toEqual('Welcome to frontend!');
- });
-});
diff --git a/gae/frontend/e2e/src/app.po.ts b/gae/frontend/e2e/src/app.po.ts
deleted file mode 100644
index 82ea75b..0000000
--- a/gae/frontend/e2e/src/app.po.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { browser, by, element } from 'protractor';
-
-export class AppPage {
- navigateTo() {
- return browser.get('/');
- }
-
- getParagraphText() {
- return element(by.css('app-root h1')).getText();
- }
-}
diff --git a/gae/frontend/e2e/tsconfig.e2e.json b/gae/frontend/e2e/tsconfig.e2e.json
deleted file mode 100644
index a6dd622..0000000
--- a/gae/frontend/e2e/tsconfig.e2e.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "extends": "../tsconfig.json",
- "compilerOptions": {
- "outDir": "../out-tsc/app",
- "module": "commonjs",
- "target": "es5",
- "types": [
- "jasmine",
- "jasminewd2",
- "node"
- ]
- }
-} \ No newline at end of file
diff --git a/gae/frontend/package-lock.json b/gae/frontend/package-lock.json
deleted file mode 100644
index f697726..0000000
--- a/gae/frontend/package-lock.json
+++ /dev/null
@@ -1,10746 +0,0 @@
-{
- "name": "frontend",
- "version": "0.0.0",
- "lockfileVersion": 1,
- "requires": true,
- "dependencies": {
- "@angular-devkit/architect": {
- "version": "0.6.8",
- "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.6.8.tgz",
- "integrity": "sha512-ZKTm/zC61iY9IBHOEAKoMSzZpvhkmv+1O/HHzpHEuR551jCzu6vSyCmMY9Z7GBcccscCV+hjeSMwgFrFRcqlkw==",
- "dev": true,
- "requires": {
- "@angular-devkit/core": "0.6.8",
- "rxjs": "6.2.1"
- }
- },
- "@angular-devkit/build-angular": {
- "version": "0.6.8",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.6.8.tgz",
- "integrity": "sha512-VGqYAk8jpISraz2UHfsDre270NOUmV0CTSZw2p9sm5g/XIr5m+IHetFZz3gpoAr9+If2aFTs8Rt3sGdCRzwBqA==",
- "dev": true,
- "requires": {
- "@angular-devkit/architect": "0.6.8",
- "@angular-devkit/build-optimizer": "0.6.8",
- "@angular-devkit/core": "0.6.8",
- "@ngtools/webpack": "6.0.8",
- "ajv": "6.4.0",
- "autoprefixer": "8.6.2",
- "cache-loader": "1.2.2",
- "chalk": "2.2.2",
- "circular-dependency-plugin": "5.0.2",
- "clean-css": "4.1.11",
- "copy-webpack-plugin": "4.5.1",
- "file-loader": "1.1.11",
- "glob": "7.1.2",
- "html-webpack-plugin": "3.2.0",
- "istanbul": "0.4.5",
- "istanbul-instrumenter-loader": "3.0.1",
- "karma-source-map-support": "1.3.0",
- "less": "3.0.4",
- "less-loader": "4.1.0",
- "license-webpack-plugin": "1.3.1",
- "lodash": "4.17.10",
- "memory-fs": "0.4.1",
- "mini-css-extract-plugin": "0.4.0",
- "minimatch": "3.0.4",
- "node-sass": "4.9.0",
- "opn": "5.3.0",
- "parse5": "4.0.0",
- "portfinder": "1.0.13",
- "postcss": "6.0.22",
- "postcss-import": "11.1.0",
- "postcss-loader": "2.1.5",
- "postcss-url": "7.3.2",
- "raw-loader": "0.5.1",
- "resolve": "1.7.1",
- "rxjs": "6.2.1",
- "sass-loader": "7.0.3",
- "silent-error": "1.1.0",
- "source-map-support": "0.5.6",
- "stats-webpack-plugin": "0.6.2",
- "style-loader": "0.21.0",
- "stylus": "0.54.5",
- "stylus-loader": "3.0.2",
- "tree-kill": "1.2.0",
- "uglifyjs-webpack-plugin": "1.2.5",
- "url-loader": "1.0.1",
- "webpack": "4.8.3",
- "webpack-dev-middleware": "3.1.3",
- "webpack-dev-server": "3.1.4",
- "webpack-merge": "4.1.3",
- "webpack-sources": "1.1.0",
- "webpack-subresource-integrity": "1.1.0-rc.4"
- }
- },
- "@angular-devkit/build-optimizer": {
- "version": "0.6.8",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.6.8.tgz",
- "integrity": "sha512-of5syQbv3uNPp4AQkfRecfnp8AE8kvffbfYi+FFPZ6OGr7e59T1fGwk6+Zgb2qQFQg8HO2tzWI/uygtLIqmbmw==",
- "dev": true,
- "requires": {
- "loader-utils": "1.1.0",
- "source-map": "0.5.7",
- "typescript": "2.9.2",
- "webpack-sources": "1.1.0"
- },
- "dependencies": {
- "typescript": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
- "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==",
- "dev": true
- }
- }
- },
- "@angular-devkit/core": {
- "version": "0.6.8",
- "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-0.6.8.tgz",
- "integrity": "sha512-rkIa1OSVWTt4g9leLSK/PsqOj3HZbDKHbZjqlslyfVa3AyCeiumFoOgViOVXlYgPX3HHDbE5uH24nyUWSD8uww==",
- "dev": true,
- "requires": {
- "ajv": "6.4.0",
- "chokidar": "2.0.3",
- "rxjs": "6.2.1",
- "source-map": "0.5.7"
- }
- },
- "@angular-devkit/schematics": {
- "version": "0.6.8",
- "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-0.6.8.tgz",
- "integrity": "sha512-R4YqAUdo62wtrhX/5HSRGSKXNTWqfQb66ZE6m8jj6GEJNFKdNXMdxOchxr07LCiKTxfh1w6G3nGzxIsu/+D4KA==",
- "dev": true,
- "requires": {
- "@angular-devkit/core": "0.6.8",
- "rxjs": "6.2.1"
- }
- },
- "@angular/animations": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-6.0.6.tgz",
- "integrity": "sha512-mJvWn0GuYARJfV9/KNUn5qUc5iNJKMSSNm//pRtUB8n829KnJHLnGpNsr95dzARH5wI3Om/t6hG3M0XCLbIfNQ==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "@angular/cdk": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-6.2.1.tgz",
- "integrity": "sha512-uwW4eIGJKqOkR+ew6YcEAh1J4SP98jdyDpsZ4IEMkV9+jXcKfcwcxGFpZvs9wJsAvAr8EgNmZ8h+iuZLwJsvmA==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "@angular/cli": {
- "version": "6.0.8",
- "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-6.0.8.tgz",
- "integrity": "sha512-DhH1Zq5Yonthw6zh6W07fhf+9XrAZbD1fcQ0MrmbxlieCfLlTAdBqyK2LavFCKwSZkUMLF6UHM3+jiNRVZSSIg==",
- "dev": true,
- "requires": {
- "@angular-devkit/architect": "0.6.8",
- "@angular-devkit/core": "0.6.8",
- "@angular-devkit/schematics": "0.6.8",
- "@schematics/angular": "0.6.8",
- "@schematics/update": "0.6.8",
- "opn": "5.3.0",
- "resolve": "1.7.1",
- "rxjs": "6.2.1",
- "semver": "5.5.0",
- "silent-error": "1.1.0",
- "symbol-observable": "1.2.0",
- "yargs-parser": "10.0.0"
- },
- "dependencies": {
- "camelcase": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
- "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
- "dev": true
- },
- "yargs-parser": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.0.0.tgz",
- "integrity": "sha512-+DHejWujTVYeMHLff8U96rLc4uE4Emncoftvn5AjhB1Jw1pWxLzgBUT/WYbPrHmy6YPEBTZQx5myHhVcuuu64g==",
- "dev": true,
- "requires": {
- "camelcase": "4.1.0"
- }
- }
- }
- },
- "@angular/common": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/@angular/common/-/common-6.0.6.tgz",
- "integrity": "sha512-SjCrrGNJSeRMtNLv/ug5HpyRUexdNl11TrWCWMeu3ye3ss4k6EnuM9jGB196B0PIm0IbjO0KrpQ8bqBx0/2vqw==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "@angular/compiler": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-6.0.6.tgz",
- "integrity": "sha512-lcDNfkYLOWzOOqdD2Kspxwjk3xGs8kVLbq/8uk/aJ96ty8aA9j8Nbf3h53SCY9LuGoJMjOaaUpgwZCszFzqQyA==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "@angular/compiler-cli": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-6.0.6.tgz",
- "integrity": "sha512-vWJK+X6B63+kdAN2s7Az1NHF4gAbECf1fkB+zkO6pP706teW4VlN2xdXeHLXgvK39iDJbhbctTnDfhqIaPmyjw==",
- "dev": true,
- "requires": {
- "chokidar": "1.7.0",
- "minimist": "1.2.0",
- "reflect-metadata": "0.1.12",
- "tsickle": "0.29.0"
- },
- "dependencies": {
- "anymatch": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
- "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
- "dev": true,
- "requires": {
- "micromatch": "2.3.11",
- "normalize-path": "2.1.1"
- }
- },
- "arr-diff": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
- "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
- "dev": true,
- "requires": {
- "arr-flatten": "1.1.0"
- }
- },
- "array-unique": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
- "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
- "dev": true
- },
- "braces": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
- "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
- "dev": true,
- "requires": {
- "expand-range": "1.8.2",
- "preserve": "0.2.0",
- "repeat-element": "1.1.2"
- }
- },
- "chokidar": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
- "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
- "dev": true,
- "requires": {
- "anymatch": "1.3.2",
- "async-each": "1.0.1",
- "fsevents": "1.2.4",
- "glob-parent": "2.0.0",
- "inherits": "2.0.3",
- "is-binary-path": "1.0.1",
- "is-glob": "2.0.1",
- "path-is-absolute": "1.0.1",
- "readdirp": "2.1.0"
- }
- },
- "expand-brackets": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
- "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
- "dev": true,
- "requires": {
- "is-posix-bracket": "0.1.1"
- }
- },
- "extglob": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
- "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
- "dev": true,
- "requires": {
- "is-extglob": "1.0.0"
- }
- },
- "glob-parent": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
- "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
- "dev": true,
- "requires": {
- "is-glob": "2.0.1"
- }
- },
- "is-extglob": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
- "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
- "dev": true
- },
- "is-glob": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
- "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
- "dev": true,
- "requires": {
- "is-extglob": "1.0.0"
- }
- },
- "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"
- }
- },
- "micromatch": {
- "version": "2.3.11",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
- "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
- "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"
- }
- },
- "minimist": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
- "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
- "dev": true
- }
- }
- },
- "@angular/core": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/@angular/core/-/core-6.0.6.tgz",
- "integrity": "sha512-7J4wuQ5Bss2GmCptyXSfmgWk/IbCFK/MJwaXOpADLB9iWOkOIvKRSTntb4l6j3OVd9boCbs6Z/xW/HT964iMvw==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "@angular/flex-layout": {
- "version": "6.0.0-beta.16",
- "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-6.0.0-beta.16.tgz",
- "integrity": "sha512-0AYtIBGrEJshdFMc6TXGloCkD19YTCRKVJl6xZHX4H5dLnUn+daqXcbh4UsWhayevnLp85HEf2ViHLmTa6jv3g==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "@angular/forms": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-6.0.6.tgz",
- "integrity": "sha512-uVcvUz8JzO/R6HtxIUtefjK55nf4gJt9WjVdnjmA66pQe1+aQYscyQu9QFykGfGqta/0luhVSU7J+5g0rIRr/g==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "@angular/http": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/@angular/http/-/http-6.0.6.tgz",
- "integrity": "sha512-ZyY7JS3lQM0HnKfoCJl+S9ZHeQVdG+FefjYE2s7pBKUufaoMo9DTIfQe5ZgSQeXRAFKjuUyJDf1EZlPVVvQzIw==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "@angular/language-service": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-6.0.6.tgz",
- "integrity": "sha512-6zRuKreMPlLQkLGS7KaJ4xehwirPbst+S6tQZltcSHjgIKrZBu3acL7/tUo5G5jQW6OnPXWK9UYs2kCffPS3AQ==",
- "dev": true
- },
- "@angular/material": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@angular/material/-/material-6.2.1.tgz",
- "integrity": "sha512-SBoUXxHknkgwzp5pNDHW0jyrTM0d0Tk4lVyDbtEX8VEPtXqG5nL3BSgyjpJbTvqlmy2kOooUu3qgAmt87VH9lw==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "@angular/platform-browser": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-6.0.6.tgz",
- "integrity": "sha512-c+2c4Ba8IeIt9CnF1RmJVf/0xwljT9GSIJUC61SLrX01NMwRxDq/LC+tatcBGLzZ6rc1eYmsd1exTHOGfENOxw==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "@angular/platform-browser-dynamic": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-6.0.6.tgz",
- "integrity": "sha512-t5+dvfcwVaDa5H8qsVnPAvmNJa0rDwJMu1T6kfz8sAxzgiw6tOvIQShJX0Ka94+nPpd4mg7gv43VV705z6ryMA==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "@angular/router": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/@angular/router/-/router-6.0.6.tgz",
- "integrity": "sha512-R49Gh/ate//AloPGjtQ2Nl3HNMT21pumcUoWZEZtYw8UyTbxSKLMc40yzdsldGrKZ/G/CafFTaS1hpZD7MF5/w==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "@ngtools/webpack": {
- "version": "6.0.8",
- "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-6.0.8.tgz",
- "integrity": "sha512-jorGpTd82ILbyUwg4JQekovHFaYwSMlZan4f7x+sd3+2WgyL3Z1+ZbVSGKvXZWKS/mAVx7eLkRikzJkuC4FgHw==",
- "dev": true,
- "requires": {
- "@angular-devkit/core": "0.6.8",
- "tree-kill": "1.2.0",
- "webpack-sources": "1.1.0"
- }
- },
- "@schematics/angular": {
- "version": "0.6.8",
- "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-0.6.8.tgz",
- "integrity": "sha512-9kRphqTYG5Df/I8fvnT1zMsw0YNDPO9tl18tQZXj4am4raT7l9UCr+WkwJdlBoA5pwG6baWE9sL0iGWV/bzF/g==",
- "dev": true,
- "requires": {
- "@angular-devkit/core": "0.6.8",
- "@angular-devkit/schematics": "0.6.8",
- "typescript": "2.7.2"
- }
- },
- "@schematics/update": {
- "version": "0.6.8",
- "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.6.8.tgz",
- "integrity": "sha512-1Uq7LYnwL2wBwGVCgNz76QAR13ghAk+2vDDHOi+VX5+usHManxydrpoMGeX66OBPd+y5D3D2MFb+8mYHE7mygg==",
- "dev": true,
- "requires": {
- "@angular-devkit/core": "0.6.8",
- "@angular-devkit/schematics": "0.6.8",
- "npm-registry-client": "8.5.1",
- "rxjs": "6.2.1",
- "semver": "5.5.0",
- "semver-intersect": "1.3.1"
- }
- },
- "@types/jasmine": {
- "version": "2.8.8",
- "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.8.tgz",
- "integrity": "sha512-OJSUxLaxXsjjhob2DBzqzgrkLmukM3+JMpRp0r0E4HTdT1nwDCWhaswjYxazPij6uOdzHCJfNbDjmQ1/rnNbCg==",
- "dev": true
- },
- "@types/jasminewd2": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.3.tgz",
- "integrity": "sha512-hYDVmQZT5VA2kigd4H4bv7vl/OhlympwREUemqBdOqtrYTo5Ytm12a5W5/nGgGYdanGVxj0x/VhZ7J3hOg/YKg==",
- "dev": true,
- "requires": {
- "@types/jasmine": "2.8.8"
- }
- },
- "@types/node": {
- "version": "8.9.5",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-8.9.5.tgz",
- "integrity": "sha512-jRHfWsvyMtXdbhnz5CVHxaBgnV6duZnPlQuRSo/dm/GnmikNcmZhxIES4E9OZjUmQ8C+HCl4KJux+cXN/ErGDQ==",
- "dev": true
- },
- "@types/q": {
- "version": "0.0.32",
- "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz",
- "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=",
- "dev": true
- },
- "@types/selenium-webdriver": {
- "version": "2.53.43",
- "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-2.53.43.tgz",
- "integrity": "sha512-UBYHWph6P3tutkbXpW6XYg9ZPbTKjw/YC2hGG1/GEvWwTbvezBUv3h+mmUFw79T3RFPnmedpiXdOBbXX+4l0jg==",
- "dev": true
- },
- "@webassemblyjs/ast": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.4.3.tgz",
- "integrity": "sha512-S6npYhPcTHDYe9nlsKa9CyWByFi8Vj8HovcAgtmMAQZUOczOZbQ8CnwMYKYC5HEZzxEE+oY0jfQk4cVlI3J59Q==",
- "dev": true,
- "requires": {
- "@webassemblyjs/helper-wasm-bytecode": "1.4.3",
- "@webassemblyjs/wast-parser": "1.4.3",
- "debug": "3.1.0",
- "webassemblyjs": "1.4.3"
- },
- "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"
- }
- }
- }
- },
- "@webassemblyjs/floating-point-hex-parser": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.4.3.tgz",
- "integrity": "sha512-3zTkSFswwZOPNHnzkP9ONq4bjJSeKVMcuahGXubrlLmZP8fmTIJ58dW7h/zOVWiFSuG2em3/HH3BlCN7wyu9Rw==",
- "dev": true
- },
- "@webassemblyjs/helper-buffer": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.4.3.tgz",
- "integrity": "sha512-e8+KZHh+RV8MUvoSRtuT1sFXskFnWG9vbDy47Oa166xX+l0dD5sERJ21g5/tcH8Yo95e9IN3u7Jc3NbhnUcSkw==",
- "dev": true,
- "requires": {
- "debug": "3.1.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"
- }
- }
- }
- },
- "@webassemblyjs/helper-code-frame": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.4.3.tgz",
- "integrity": "sha512-9FgHEtNsZQYaKrGCtsjswBil48Qp1agrzRcPzCbQloCoaTbOXLJ9IRmqT+uEZbenpULLRNFugz3I4uw18hJM8w==",
- "dev": true,
- "requires": {
- "@webassemblyjs/wast-printer": "1.4.3"
- }
- },
- "@webassemblyjs/helper-fsm": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.4.3.tgz",
- "integrity": "sha512-JINY76U+702IRf7ePukOt037RwmtH59JHvcdWbTTyHi18ixmQ+uOuNhcdCcQHTquDAH35/QgFlp3Y9KqtyJsCQ==",
- "dev": true
- },
- "@webassemblyjs/helper-wasm-bytecode": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.4.3.tgz",
- "integrity": "sha512-I7bS+HaO0K07Io89qhJv+z1QipTpuramGwUSDkwEaficbSvCcL92CUZEtgykfNtk5wb0CoLQwWlmXTwGbNZUeQ==",
- "dev": true
- },
- "@webassemblyjs/helper-wasm-section": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.4.3.tgz",
- "integrity": "sha512-p0yeeO/h2r30PyjnJX9xXSR6EDcvJd/jC6xa/Pxg4lpfcNi7JUswOpqDToZQ55HMMVhXDih/yqkaywHWGLxqyQ==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.4.3",
- "@webassemblyjs/helper-buffer": "1.4.3",
- "@webassemblyjs/helper-wasm-bytecode": "1.4.3",
- "@webassemblyjs/wasm-gen": "1.4.3",
- "debug": "3.1.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"
- }
- }
- }
- },
- "@webassemblyjs/leb128": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.4.3.tgz",
- "integrity": "sha512-4u0LJLSPzuRDWHwdqsrThYn+WqMFVqbI2ltNrHvZZkzFPO8XOZ0HFQ5eVc4jY/TNHgXcnwrHjONhPGYuuf//KQ==",
- "dev": true,
- "requires": {
- "leb": "0.3.0"
- }
- },
- "@webassemblyjs/validation": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/validation/-/validation-1.4.3.tgz",
- "integrity": "sha512-R+rRMKfhd9mq0rj2mhU9A9NKI2l/Rw65vIYzz4lui7eTKPcCu1l7iZNi4b9Gen8D42Sqh/KGiaQNk/x5Tn/iBQ==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.4.3"
- }
- },
- "@webassemblyjs/wasm-edit": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.4.3.tgz",
- "integrity": "sha512-qzuwUn771PV6/LilqkXcS0ozJYAeY/OKbXIWU3a8gexuqb6De2p4ya/baBeH5JQ2WJdfhWhSvSbu86Vienttpw==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.4.3",
- "@webassemblyjs/helper-buffer": "1.4.3",
- "@webassemblyjs/helper-wasm-bytecode": "1.4.3",
- "@webassemblyjs/helper-wasm-section": "1.4.3",
- "@webassemblyjs/wasm-gen": "1.4.3",
- "@webassemblyjs/wasm-opt": "1.4.3",
- "@webassemblyjs/wasm-parser": "1.4.3",
- "@webassemblyjs/wast-printer": "1.4.3",
- "debug": "3.1.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"
- }
- }
- }
- },
- "@webassemblyjs/wasm-gen": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.4.3.tgz",
- "integrity": "sha512-eR394T8dHZfpLJ7U/Z5pFSvxl1L63JdREebpv9gYc55zLhzzdJPAuxjBYT4XqevUdW67qU2s0nNA3kBuNJHbaQ==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.4.3",
- "@webassemblyjs/helper-wasm-bytecode": "1.4.3",
- "@webassemblyjs/leb128": "1.4.3"
- }
- },
- "@webassemblyjs/wasm-opt": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.4.3.tgz",
- "integrity": "sha512-7Gp+nschuKiDuAL1xmp4Xz0rgEbxioFXw4nCFYEmy+ytynhBnTeGc9W9cB1XRu1w8pqRU2lbj2VBBA4cL5Z2Kw==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.4.3",
- "@webassemblyjs/helper-buffer": "1.4.3",
- "@webassemblyjs/wasm-gen": "1.4.3",
- "@webassemblyjs/wasm-parser": "1.4.3",
- "debug": "3.1.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"
- }
- }
- }
- },
- "@webassemblyjs/wasm-parser": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.4.3.tgz",
- "integrity": "sha512-KXBjtlwA3BVukR/yWHC9GF+SCzBcgj0a7lm92kTOaa4cbjaTaa47bCjXw6cX4SGQpkncB9PU2hHGYVyyI7wFRg==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.4.3",
- "@webassemblyjs/helper-wasm-bytecode": "1.4.3",
- "@webassemblyjs/leb128": "1.4.3",
- "@webassemblyjs/wasm-parser": "1.4.3",
- "webassemblyjs": "1.4.3"
- }
- },
- "@webassemblyjs/wast-parser": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.4.3.tgz",
- "integrity": "sha512-QhCsQzqV0CpsEkRYyTzQDilCNUZ+5j92f+g35bHHNqS22FppNTywNFfHPq8ZWZfYCgbectc+PoghD+xfzVFh1Q==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.4.3",
- "@webassemblyjs/floating-point-hex-parser": "1.4.3",
- "@webassemblyjs/helper-code-frame": "1.4.3",
- "@webassemblyjs/helper-fsm": "1.4.3",
- "long": "3.2.0",
- "webassemblyjs": "1.4.3"
- }
- },
- "@webassemblyjs/wast-printer": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.4.3.tgz",
- "integrity": "sha512-EgXk4anf8jKmuZJsqD8qy5bz2frEQhBvZruv+bqwNoLWUItjNSFygk8ywL3JTEz9KtxTlAmqTXNrdD1d9gNDtg==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.4.3",
- "@webassemblyjs/wast-parser": "1.4.3",
- "long": "3.2.0"
- }
- },
- "abbrev": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
- "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=",
- "dev": true
- },
- "accepts": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
- "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
- "dev": true,
- "requires": {
- "mime-types": "2.1.18",
- "negotiator": "0.6.1"
- }
- },
- "acorn": {
- "version": "5.6.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.6.2.tgz",
- "integrity": "sha512-zUzo1E5dI2Ey8+82egfnttyMlMZ2y0D8xOCO3PNPPlYXpl8NZvF6Qk9L9BEtJs+43FqEmfBViDqc5d1ckRDguw==",
- "dev": true
- },
- "acorn-dynamic-import": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz",
- "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==",
- "dev": true,
- "requires": {
- "acorn": "5.6.2"
- }
- },
- "adm-zip": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz",
- "integrity": "sha1-ph7VrmkFw66lizplfSUDMJEFJzY=",
- "dev": true
- },
- "after": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
- "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
- "dev": true
- },
- "agent-base": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz",
- "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==",
- "dev": true,
- "requires": {
- "es6-promisify": "5.0.0"
- }
- },
- "ajv": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.4.0.tgz",
- "integrity": "sha1-06/3jpJ3VJdx2vAWTP9ISCt1T8Y=",
- "dev": true,
- "requires": {
- "fast-deep-equal": "1.1.0",
- "fast-json-stable-stringify": "2.0.0",
- "json-schema-traverse": "0.3.1",
- "uri-js": "3.0.2"
- }
- },
- "ajv-keywords": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
- "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
- "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"
- }
- }
- }
- },
- "amdefine": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
- "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
- "dev": true
- },
- "ansi-html": {
- "version": "0.0.7",
- "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
- "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
- "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": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "requires": {
- "color-convert": "1.9.2"
- }
- },
- "anymatch": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
- "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
- "dev": true,
- "requires": {
- "micromatch": "3.1.10",
- "normalize-path": "2.1.1"
- }
- },
- "app-root-path": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz",
- "integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=",
- "dev": true
- },
- "append-transform": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
- "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==",
- "dev": true,
- "requires": {
- "default-require-extensions": "2.0.0"
- }
- },
- "aproba": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
- "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
- "dev": true
- },
- "are-we-there-yet": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
- "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
- "dev": true,
- "requires": {
- "delegates": "1.0.0",
- "readable-stream": "2.3.6"
- }
- },
- "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-find-index": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
- "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
- "dev": true
- },
- "array-flatten": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz",
- "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=",
- "dev": true
- },
- "array-includes": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
- "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
- "dev": true,
- "requires": {
- "define-properties": "1.1.2",
- "es-abstract": "1.12.0"
- }
- },
- "array-slice": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
- "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
- "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
- },
- "arraybuffer.slice": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz",
- "integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco=",
- "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,
- "optional": true
- },
- "asn1": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
- "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
- "dev": true
- },
- "asn1.js": {
- "version": "4.10.1",
- "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
- "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
- "dev": true,
- "requires": {
- "bn.js": "4.11.8",
- "inherits": "2.0.3",
- "minimalistic-assert": "1.0.1"
- }
- },
- "assert": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
- "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
- "dev": true,
- "requires": {
- "util": "0.10.3"
- },
- "dependencies": {
- "inherits": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
- "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
- "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"
- }
- }
- }
- },
- "assert-plus": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
- "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
- "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": "1.5.2",
- "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
- "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
- "dev": true
- },
- "async-each": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
- "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
- "dev": true
- },
- "async-foreach": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
- "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
- "dev": true,
- "optional": true
- },
- "asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
- "dev": true
- },
- "atob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz",
- "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=",
- "dev": true
- },
- "autoprefixer": {
- "version": "8.6.2",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.6.2.tgz",
- "integrity": "sha512-cv9v1mYYBcAnZq4MHseJ9AIdjQmNahnpCpPO46oTkQJS2GggsBp2azHjNpAuQ95Epvsg+AIsyjYhfI9YwFxGSA==",
- "dev": true,
- "requires": {
- "browserslist": "3.2.8",
- "caniuse-lite": "1.0.30000855",
- "normalize-range": "0.1.2",
- "num2fraction": "1.2.2",
- "postcss": "6.0.22",
- "postcss-value-parser": "3.3.0"
- }
- },
- "aws-sign2": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
- "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
- "dev": true
- },
- "aws4": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
- "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==",
- "dev": true
- },
- "babel-code-frame": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
- "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
- "dev": true,
- "requires": {
- "chalk": "1.1.3",
- "esutils": "2.0.2",
- "js-tokens": "3.0.2"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "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"
- }
- },
- "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
- }
- }
- },
- "babel-generator": {
- "version": "6.26.1",
- "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
- "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
- "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.10",
- "source-map": "0.5.7",
- "trim-right": "1.0.1"
- }
- },
- "babel-messages": {
- "version": "6.23.0",
- "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
- "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0"
- }
- },
- "babel-runtime": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
- "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
- "dev": true,
- "requires": {
- "core-js": "2.5.7",
- "regenerator-runtime": "0.11.1"
- }
- },
- "babel-template": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
- "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
- "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.10"
- }
- },
- "babel-traverse": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
- "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
- "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.4",
- "lodash": "4.17.10"
- }
- },
- "babel-types": {
- "version": "6.26.0",
- "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
- "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0",
- "esutils": "2.0.2",
- "lodash": "4.17.10",
- "to-fast-properties": "1.0.3"
- }
- },
- "babylon": {
- "version": "6.18.0",
- "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
- "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
- "dev": true
- },
- "backo2": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
- "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
- "dev": true
- },
- "balanced-match": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
- "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true
- },
- "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"
- }
- },
- "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-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"
- }
- }
- }
- },
- "base64-arraybuffer": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
- "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
- "dev": true
- },
- "base64-js": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
- "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==",
- "dev": true
- },
- "base64id": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
- "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=",
- "dev": true
- },
- "batch": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
- "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
- "dev": true
- },
- "bcrypt-pbkdf": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
- "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
- "dev": true,
- "optional": true,
- "requires": {
- "tweetnacl": "0.14.5"
- }
- },
- "better-assert": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
- "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
- "dev": true,
- "requires": {
- "callsite": "1.0.0"
- }
- },
- "big.js": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
- "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
- "dev": true
- },
- "binary-extensions": {
- "version": "1.11.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
- "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
- "dev": true
- },
- "blob": {
- "version": "0.0.4",
- "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
- "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=",
- "dev": true
- },
- "block-stream": {
- "version": "0.0.9",
- "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
- "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
- "dev": true,
- "optional": true,
- "requires": {
- "inherits": "2.0.3"
- }
- },
- "blocking-proxy": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz",
- "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==",
- "dev": true,
- "requires": {
- "minimist": "1.2.0"
- },
- "dependencies": {
- "minimist": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
- "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
- "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
- },
- "bn.js": {
- "version": "4.11.8",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
- "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
- "dev": true
- },
- "body-parser": {
- "version": "1.18.2",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
- "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
- "dev": true,
- "requires": {
- "bytes": "3.0.0",
- "content-type": "1.0.4",
- "debug": "2.6.9",
- "depd": "1.1.2",
- "http-errors": "1.6.3",
- "iconv-lite": "0.4.19",
- "on-finished": "2.3.0",
- "qs": "6.5.1",
- "raw-body": "2.3.2",
- "type-is": "1.6.16"
- },
- "dependencies": {
- "qs": {
- "version": "6.5.1",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
- "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
- "dev": true
- }
- }
- },
- "bonjour": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
- "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
- "dev": true,
- "requires": {
- "array-flatten": "2.1.1",
- "deep-equal": "1.0.1",
- "dns-equal": "1.0.0",
- "dns-txt": "2.0.2",
- "multicast-dns": "6.2.3",
- "multicast-dns-service-types": "1.1.0"
- }
- },
- "boolbase": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
- "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
- "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"
- }
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "requires": {
- "balanced-match": "1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "braces": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
- "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
- "dev": true,
- "requires": {
- "arr-flatten": "1.1.0",
- "array-unique": "0.3.2",
- "extend-shallow": "2.0.1",
- "fill-range": "4.0.0",
- "isobject": "3.0.1",
- "repeat-element": "1.1.2",
- "snapdragon": "0.8.2",
- "snapdragon-node": "2.1.1",
- "split-string": "3.1.0",
- "to-regex": "3.0.2"
- },
- "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"
- }
- }
- }
- },
- "brorand": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
- "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
- "dev": true
- },
- "browserify-aes": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
- "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
- "dev": true,
- "requires": {
- "buffer-xor": "1.0.3",
- "cipher-base": "1.0.4",
- "create-hash": "1.2.0",
- "evp_bytestokey": "1.0.3",
- "inherits": "2.0.3",
- "safe-buffer": "5.1.2"
- }
- },
- "browserify-cipher": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
- "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
- "dev": true,
- "requires": {
- "browserify-aes": "1.2.0",
- "browserify-des": "1.0.1",
- "evp_bytestokey": "1.0.3"
- }
- },
- "browserify-des": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz",
- "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==",
- "dev": true,
- "requires": {
- "cipher-base": "1.0.4",
- "des.js": "1.0.0",
- "inherits": "2.0.3"
- }
- },
- "browserify-rsa": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
- "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
- "dev": true,
- "requires": {
- "bn.js": "4.11.8",
- "randombytes": "2.0.6"
- }
- },
- "browserify-sign": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
- "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
- "dev": true,
- "requires": {
- "bn.js": "4.11.8",
- "browserify-rsa": "4.0.1",
- "create-hash": "1.2.0",
- "create-hmac": "1.1.7",
- "elliptic": "6.4.0",
- "inherits": "2.0.3",
- "parse-asn1": "5.1.1"
- }
- },
- "browserify-zlib": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
- "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
- "dev": true,
- "requires": {
- "pako": "1.0.6"
- }
- },
- "browserslist": {
- "version": "3.2.8",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz",
- "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==",
- "dev": true,
- "requires": {
- "caniuse-lite": "1.0.30000855",
- "electron-to-chromium": "1.3.48"
- }
- },
- "buffer": {
- "version": "4.9.1",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
- "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
- "dev": true,
- "requires": {
- "base64-js": "1.3.0",
- "ieee754": "1.1.12",
- "isarray": "1.0.0"
- }
- },
- "buffer-from": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz",
- "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==",
- "dev": true
- },
- "buffer-indexof": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
- "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
- "dev": true
- },
- "buffer-xor": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
- "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
- "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
- },
- "builtin-status-codes": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
- "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
- "dev": true
- },
- "builtins": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz",
- "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
- "dev": true
- },
- "bytes": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
- "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
- "dev": true
- },
- "cacache": {
- "version": "10.0.4",
- "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
- "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
- "dev": true,
- "requires": {
- "bluebird": "3.5.1",
- "chownr": "1.0.1",
- "glob": "7.1.2",
- "graceful-fs": "4.1.11",
- "lru-cache": "4.1.3",
- "mississippi": "2.0.0",
- "mkdirp": "0.5.1",
- "move-concurrently": "1.0.1",
- "promise-inflight": "1.0.1",
- "rimraf": "2.6.2",
- "ssri": "5.3.0",
- "unique-filename": "1.1.0",
- "y18n": "4.0.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"
- }
- },
- "cache-loader": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-1.2.2.tgz",
- "integrity": "sha512-rsGh4SIYyB9glU+d0OcHwiXHXBoUgDhHZaQ1KAbiXqfz1CDPxtTboh1gPbJ0q2qdO8a9lfcjgC5CJ2Ms32y5bw==",
- "dev": true,
- "requires": {
- "loader-utils": "1.1.0",
- "mkdirp": "0.5.1",
- "neo-async": "2.5.1",
- "schema-utils": "0.4.5"
- }
- },
- "callsite": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
- "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
- "dev": true
- },
- "camel-case": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
- "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
- "dev": true,
- "requires": {
- "no-case": "2.3.2",
- "upper-case": "1.1.3"
- }
- },
- "camelcase": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
- "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
- "dev": true,
- "optional": true
- },
- "camelcase-keys": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
- "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
- "dev": true,
- "requires": {
- "camelcase": "2.1.1",
- "map-obj": "1.0.1"
- },
- "dependencies": {
- "camelcase": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
- "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
- "dev": true
- }
- }
- },
- "caniuse-lite": {
- "version": "1.0.30000855",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000855.tgz",
- "integrity": "sha512-ajORrkXa5UYk62P5PK6ZmBraYOAOr9HWy+XxLwjDg8Ys/5KiSyarg8tIA32ZVqbFhtz67wyySXnU9imkh2ZT2w==",
- "dev": true
- },
- "caseless": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
- "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
- "dev": true
- },
- "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"
- }
- },
- "chalk": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.2.2.tgz",
- "integrity": "sha512-LvixLAQ4MYhbf7hgL4o5PeK32gJKvVzDRiSNIApDofQvyhl8adgG2lJVXn4+ekQoK7HL9RF8lqxwerpe0x2pCw==",
- "dev": true,
- "requires": {
- "ansi-styles": "3.2.1",
- "escape-string-regexp": "1.0.5",
- "supports-color": "4.5.0"
- },
- "dependencies": {
- "has-flag": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
- "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
- "dev": true
- },
- "supports-color": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
- "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
- "dev": true,
- "requires": {
- "has-flag": "2.0.0"
- }
- }
- }
- },
- "chokidar": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz",
- "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==",
- "dev": true,
- "requires": {
- "anymatch": "2.0.0",
- "async-each": "1.0.1",
- "braces": "2.3.2",
- "fsevents": "1.2.4",
- "glob-parent": "3.1.0",
- "inherits": "2.0.3",
- "is-binary-path": "1.0.1",
- "is-glob": "4.0.0",
- "normalize-path": "2.1.1",
- "path-is-absolute": "1.0.1",
- "readdirp": "2.1.0",
- "upath": "1.1.0"
- }
- },
- "chownr": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz",
- "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=",
- "dev": true
- },
- "chrome-trace-event": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-0.1.3.tgz",
- "integrity": "sha512-sjndyZHrrWiu4RY7AkHgjn80GfAM2ZSzUkZLV/Js59Ldmh6JDThf0SUmOHU53rFu2rVxxfCzJ30Ukcfch3Gb/A==",
- "dev": true
- },
- "cipher-base": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
- "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
- "dev": true,
- "requires": {
- "inherits": "2.0.3",
- "safe-buffer": "5.1.2"
- }
- },
- "circular-dependency-plugin": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.0.2.tgz",
- "integrity": "sha512-oC7/DVAyfcY3UWKm0sN/oVoDedQDQiw/vIiAnuTWTpE5s0zWf7l3WY417Xw/Fbi/QbAjctAkxgMiS9P0s3zkmA==",
- "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"
- }
- }
- }
- },
- "clean-css": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz",
- "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=",
- "dev": true,
- "requires": {
- "source-map": "0.5.7"
- }
- },
- "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"
- },
- "dependencies": {
- "wordwrap": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
- "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
- "dev": true,
- "optional": true
- }
- }
- },
- "clone": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz",
- "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=",
- "dev": true
- },
- "clone-deep": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz",
- "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==",
- "dev": true,
- "requires": {
- "for-own": "1.0.0",
- "is-plain-object": "2.0.4",
- "kind-of": "6.0.2",
- "shallow-clone": "1.0.0"
- }
- },
- "co": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
- "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
- "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=",
- "dev": true
- },
- "codelyzer": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-4.2.1.tgz",
- "integrity": "sha512-CKwfgpfkqi9dyzy4s6ELaxJ54QgJ6A8iTSsM4bzHbLuTpbKncvNc3DUlCvpnkHBhK47gEf4qFsWoYqLrJPhy6g==",
- "dev": true,
- "requires": {
- "app-root-path": "2.0.1",
- "css-selector-tokenizer": "0.7.0",
- "cssauron": "1.4.0",
- "semver-dsl": "1.0.1",
- "source-map": "0.5.7",
- "sprintf-js": "1.0.3"
- }
- },
- "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.2",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz",
- "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==",
- "dev": true,
- "requires": {
- "color-name": "1.1.1"
- }
- },
- "color-name": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz",
- "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=",
- "dev": true
- },
- "colors": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
- "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
- "dev": true
- },
- "combine-lists": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz",
- "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=",
- "dev": true,
- "requires": {
- "lodash": "4.17.10"
- }
- },
- "combined-stream": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
- "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
- "dev": true,
- "requires": {
- "delayed-stream": "1.0.0"
- }
- },
- "commander": {
- "version": "2.15.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
- "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
- "dev": true
- },
- "commondir": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
- "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
- "dev": true
- },
- "compare-versions": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.3.0.tgz",
- "integrity": "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ==",
- "dev": true
- },
- "component-bind": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
- "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=",
- "dev": true
- },
- "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
- },
- "component-inherit": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
- "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=",
- "dev": true
- },
- "compressible": {
- "version": "2.0.14",
- "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz",
- "integrity": "sha1-MmxfUH+7BV9UEWeCuWmoG2einac=",
- "dev": true,
- "requires": {
- "mime-db": "1.34.0"
- },
- "dependencies": {
- "mime-db": {
- "version": "1.34.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.34.0.tgz",
- "integrity": "sha1-RS0Oz/XDA0am3B5kseruDTcZ/5o=",
- "dev": true
- }
- }
- },
- "compression": {
- "version": "1.7.2",
- "resolved": "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz",
- "integrity": "sha1-qv+81qr4VLROuygDU9WtFlH1mmk=",
- "dev": true,
- "requires": {
- "accepts": "1.3.5",
- "bytes": "3.0.0",
- "compressible": "2.0.14",
- "debug": "2.6.9",
- "on-headers": "1.0.1",
- "safe-buffer": "5.1.1",
- "vary": "1.1.2"
- },
- "dependencies": {
- "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
- }
- }
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
- },
- "concat-stream": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
- "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
- "dev": true,
- "requires": {
- "buffer-from": "1.1.0",
- "inherits": "2.0.3",
- "readable-stream": "2.3.6",
- "typedarray": "0.0.6"
- }
- },
- "connect": {
- "version": "3.6.6",
- "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz",
- "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=",
- "dev": true,
- "requires": {
- "debug": "2.6.9",
- "finalhandler": "1.1.0",
- "parseurl": "1.3.2",
- "utils-merge": "1.0.1"
- },
- "dependencies": {
- "finalhandler": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
- "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=",
- "dev": true,
- "requires": {
- "debug": "2.6.9",
- "encodeurl": "1.0.2",
- "escape-html": "1.0.3",
- "on-finished": "2.3.0",
- "parseurl": "1.3.2",
- "statuses": "1.3.1",
- "unpipe": "1.0.0"
- }
- },
- "statuses": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
- "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=",
- "dev": true
- }
- }
- },
- "connect-history-api-fallback": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz",
- "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=",
- "dev": true
- },
- "console-browserify": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
- "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
- "dev": true,
- "requires": {
- "date-now": "0.1.4"
- }
- },
- "console-control-strings": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
- "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
- "dev": true
- },
- "constants-browserify": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
- "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
- "dev": true
- },
- "content-disposition": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
- "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=",
- "dev": true
- },
- "content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
- "dev": true
- },
- "convert-source-map": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz",
- "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=",
- "dev": true
- },
- "cookie": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
- "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
- "dev": true
- },
- "cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
- "dev": true
- },
- "copy-concurrently": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
- "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
- "dev": true,
- "requires": {
- "aproba": "1.2.0",
- "fs-write-stream-atomic": "1.0.10",
- "iferr": "0.1.5",
- "mkdirp": "0.5.1",
- "rimraf": "2.6.2",
- "run-queue": "1.0.3"
- }
- },
- "copy-descriptor": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
- "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
- "dev": true
- },
- "copy-webpack-plugin": {
- "version": "4.5.1",
- "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.1.tgz",
- "integrity": "sha512-OlTo6DYg0XfTKOF8eLf79wcHm4Ut10xU2cRBRPMW/NA5F9VMjZGTfRHWDIYC3s+1kObGYrBLshXWU1K0hILkNQ==",
- "dev": true,
- "requires": {
- "cacache": "10.0.4",
- "find-cache-dir": "1.0.0",
- "globby": "7.1.1",
- "is-glob": "4.0.0",
- "loader-utils": "1.1.0",
- "minimatch": "3.0.4",
- "p-limit": "1.3.0",
- "serialize-javascript": "1.5.0"
- }
- },
- "core-js": {
- "version": "2.5.7",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
- "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
- },
- "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
- },
- "cosmiconfig": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz",
- "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==",
- "dev": true,
- "requires": {
- "is-directory": "0.3.1",
- "js-yaml": "3.12.0",
- "minimist": "1.2.0",
- "object-assign": "4.1.1",
- "os-homedir": "1.0.2",
- "parse-json": "2.2.0",
- "require-from-string": "1.2.1"
- },
- "dependencies": {
- "minimist": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
- "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
- "dev": true
- }
- }
- },
- "create-ecdh": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
- "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
- "dev": true,
- "requires": {
- "bn.js": "4.11.8",
- "elliptic": "6.4.0"
- }
- },
- "create-hash": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
- "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
- "dev": true,
- "requires": {
- "cipher-base": "1.0.4",
- "inherits": "2.0.3",
- "md5.js": "1.3.4",
- "ripemd160": "2.0.2",
- "sha.js": "2.4.11"
- }
- },
- "create-hmac": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
- "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
- "dev": true,
- "requires": {
- "cipher-base": "1.0.4",
- "create-hash": "1.2.0",
- "inherits": "2.0.3",
- "ripemd160": "2.0.2",
- "safe-buffer": "5.1.2",
- "sha.js": "2.4.11"
- }
- },
- "cross-spawn": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
- "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
- "dev": true,
- "optional": true,
- "requires": {
- "lru-cache": "4.1.3",
- "which": "1.3.1"
- }
- },
- "cryptiles": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
- "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
- "dev": true,
- "requires": {
- "boom": "2.10.1"
- }
- },
- "crypto-browserify": {
- "version": "3.12.0",
- "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
- "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
- "dev": true,
- "requires": {
- "browserify-cipher": "1.0.1",
- "browserify-sign": "4.0.4",
- "create-ecdh": "4.0.3",
- "create-hash": "1.2.0",
- "create-hmac": "1.1.7",
- "diffie-hellman": "5.0.3",
- "inherits": "2.0.3",
- "pbkdf2": "3.0.16",
- "public-encrypt": "4.0.2",
- "randombytes": "2.0.6",
- "randomfill": "1.0.4"
- }
- },
- "css-parse": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz",
- "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=",
- "dev": true
- },
- "css-select": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
- "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
- "dev": true,
- "requires": {
- "boolbase": "1.0.0",
- "css-what": "2.1.0",
- "domutils": "1.5.1",
- "nth-check": "1.0.1"
- }
- },
- "css-selector-tokenizer": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz",
- "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=",
- "dev": true,
- "requires": {
- "cssesc": "0.1.0",
- "fastparse": "1.1.1",
- "regexpu-core": "1.0.0"
- }
- },
- "css-what": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz",
- "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=",
- "dev": true
- },
- "cssauron": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz",
- "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=",
- "dev": true,
- "requires": {
- "through": "2.3.8"
- }
- },
- "cssesc": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
- "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=",
- "dev": true
- },
- "cuint": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz",
- "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=",
- "dev": true
- },
- "currently-unhandled": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
- "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
- "dev": true,
- "requires": {
- "array-find-index": "1.0.2"
- }
- },
- "custom-event": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
- "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=",
- "dev": true
- },
- "cyclist": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
- "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
- "dev": true
- },
- "d": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
- "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
- "dev": true,
- "requires": {
- "es5-ext": "0.10.45"
- }
- },
- "dashdash": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
- "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
- "dev": true,
- "requires": {
- "assert-plus": "1.0.0"
- }
- },
- "date-now": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
- "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
- "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=",
- "dev": true
- },
- "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-equal": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
- "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
- "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
- },
- "default-require-extensions": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz",
- "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=",
- "dev": true,
- "requires": {
- "strip-bom": "3.0.0"
- },
- "dependencies": {
- "strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
- "dev": true
- }
- }
- },
- "define-properties": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
- "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
- "dev": true,
- "requires": {
- "foreach": "2.0.5",
- "object-keys": "1.0.11"
- }
- },
- "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"
- },
- "dependencies": {
- "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-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"
- }
- }
- }
- },
- "del": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz",
- "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=",
- "dev": true,
- "requires": {
- "globby": "6.1.0",
- "is-path-cwd": "1.0.0",
- "is-path-in-cwd": "1.0.1",
- "p-map": "1.2.0",
- "pify": "3.0.0",
- "rimraf": "2.6.2"
- },
- "dependencies": {
- "globby": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
- "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
- "dev": true,
- "requires": {
- "array-union": "1.0.2",
- "glob": "7.1.2",
- "object-assign": "4.1.1",
- "pify": "2.3.0",
- "pinkie-promise": "2.0.1"
- },
- "dependencies": {
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- }
- }
- }
- }
- },
- "delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
- "dev": true
- },
- "delegates": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
- "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
- "dev": true
- },
- "depd": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
- "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
- "dev": true
- },
- "des.js": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
- "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
- "dev": true,
- "requires": {
- "inherits": "2.0.3",
- "minimalistic-assert": "1.0.1"
- }
- },
- "destroy": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
- "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
- "dev": true
- },
- "detect-indent": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
- "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
- "dev": true,
- "requires": {
- "repeating": "2.0.1"
- }
- },
- "detect-node": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz",
- "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=",
- "dev": true
- },
- "di": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz",
- "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=",
- "dev": true
- },
- "diff": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
- "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
- "dev": true
- },
- "diffie-hellman": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
- "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
- "dev": true,
- "requires": {
- "bn.js": "4.11.8",
- "miller-rabin": "4.0.1",
- "randombytes": "2.0.6"
- }
- },
- "dir-glob": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz",
- "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==",
- "dev": true,
- "requires": {
- "arrify": "1.0.1",
- "path-type": "3.0.0"
- }
- },
- "dns-equal": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
- "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
- "dev": true
- },
- "dns-packet": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
- "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
- "dev": true,
- "requires": {
- "ip": "1.1.5",
- "safe-buffer": "5.1.2"
- }
- },
- "dns-txt": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
- "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
- "dev": true,
- "requires": {
- "buffer-indexof": "1.1.1"
- }
- },
- "dom-converter": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz",
- "integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=",
- "dev": true,
- "requires": {
- "utila": "0.3.3"
- },
- "dependencies": {
- "utila": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz",
- "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=",
- "dev": true
- }
- }
- },
- "dom-serialize": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz",
- "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=",
- "dev": true,
- "requires": {
- "custom-event": "1.0.1",
- "ent": "2.2.0",
- "extend": "3.0.1",
- "void-elements": "2.0.1"
- }
- },
- "dom-serializer": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
- "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
- "dev": true,
- "requires": {
- "domelementtype": "1.1.3",
- "entities": "1.1.1"
- },
- "dependencies": {
- "domelementtype": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
- "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
- "dev": true
- }
- }
- },
- "domain-browser": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
- "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
- "dev": true
- },
- "domelementtype": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
- "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
- "dev": true
- },
- "domhandler": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz",
- "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=",
- "dev": true,
- "requires": {
- "domelementtype": "1.3.0"
- }
- },
- "domutils": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
- "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
- "dev": true,
- "requires": {
- "dom-serializer": "0.1.0",
- "domelementtype": "1.3.0"
- }
- },
- "duplexify": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz",
- "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==",
- "dev": true,
- "requires": {
- "end-of-stream": "1.4.1",
- "inherits": "2.0.3",
- "readable-stream": "2.3.6",
- "stream-shift": "1.0.0"
- }
- },
- "ecc-jsbn": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
- "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
- "dev": true,
- "optional": true,
- "requires": {
- "jsbn": "0.1.1"
- }
- },
- "ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
- "dev": true
- },
- "ejs": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz",
- "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==",
- "dev": true
- },
- "electron-to-chromium": {
- "version": "1.3.48",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz",
- "integrity": "sha1-07DYWTgUBE4JLs4hCPw6ya6kuQA=",
- "dev": true
- },
- "elliptic": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
- "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
- "dev": true,
- "requires": {
- "bn.js": "4.11.8",
- "brorand": "1.1.0",
- "hash.js": "1.1.4",
- "hmac-drbg": "1.0.1",
- "inherits": "2.0.3",
- "minimalistic-assert": "1.0.1",
- "minimalistic-crypto-utils": "1.0.1"
- }
- },
- "emojis-list": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
- "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
- "dev": true
- },
- "encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
- "dev": true
- },
- "end-of-stream": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
- "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
- "dev": true,
- "requires": {
- "once": "1.4.0"
- }
- },
- "engine.io": {
- "version": "1.8.3",
- "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.3.tgz",
- "integrity": "sha1-jef5eJXSDTm4X4ju7nd7K9QrE9Q=",
- "dev": true,
- "requires": {
- "accepts": "1.3.3",
- "base64id": "1.0.0",
- "cookie": "0.3.1",
- "debug": "2.3.3",
- "engine.io-parser": "1.3.2",
- "ws": "1.1.2"
- },
- "dependencies": {
- "accepts": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz",
- "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=",
- "dev": true,
- "requires": {
- "mime-types": "2.1.18",
- "negotiator": "0.6.1"
- }
- },
- "debug": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
- "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
- "dev": true,
- "requires": {
- "ms": "0.7.2"
- }
- },
- "ms": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
- "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
- "dev": true
- }
- }
- },
- "engine.io-client": {
- "version": "1.8.3",
- "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.3.tgz",
- "integrity": "sha1-F5jtk0USRkU9TG9jXXogH+lA1as=",
- "dev": true,
- "requires": {
- "component-emitter": "1.2.1",
- "component-inherit": "0.0.3",
- "debug": "2.3.3",
- "engine.io-parser": "1.3.2",
- "has-cors": "1.1.0",
- "indexof": "0.0.1",
- "parsejson": "0.0.3",
- "parseqs": "0.0.5",
- "parseuri": "0.0.5",
- "ws": "1.1.2",
- "xmlhttprequest-ssl": "1.5.3",
- "yeast": "0.1.2"
- },
- "dependencies": {
- "debug": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
- "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
- "dev": true,
- "requires": {
- "ms": "0.7.2"
- }
- },
- "ms": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
- "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
- "dev": true
- }
- }
- },
- "engine.io-parser": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz",
- "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=",
- "dev": true,
- "requires": {
- "after": "0.8.2",
- "arraybuffer.slice": "0.0.6",
- "base64-arraybuffer": "0.1.5",
- "blob": "0.0.4",
- "has-binary": "0.1.7",
- "wtf-8": "1.0.0"
- }
- },
- "enhanced-resolve": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz",
- "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==",
- "dev": true,
- "requires": {
- "graceful-fs": "4.1.11",
- "memory-fs": "0.4.1",
- "tapable": "1.0.0"
- }
- },
- "ent": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz",
- "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=",
- "dev": true
- },
- "entities": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
- "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
- "dev": true
- },
- "errno": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
- "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
- "dev": true,
- "requires": {
- "prr": "1.0.1"
- }
- },
- "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"
- }
- },
- "es-abstract": {
- "version": "1.12.0",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
- "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
- "dev": true,
- "requires": {
- "es-to-primitive": "1.1.1",
- "function-bind": "1.1.1",
- "has": "1.0.3",
- "is-callable": "1.1.3",
- "is-regex": "1.0.4"
- }
- },
- "es-to-primitive": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
- "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
- "dev": true,
- "requires": {
- "is-callable": "1.1.3",
- "is-date-object": "1.0.1",
- "is-symbol": "1.0.1"
- }
- },
- "es5-ext": {
- "version": "0.10.45",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz",
- "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==",
- "dev": true,
- "requires": {
- "es6-iterator": "2.0.3",
- "es6-symbol": "3.1.1",
- "next-tick": "1.0.0"
- }
- },
- "es6-iterator": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
- "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
- "dev": true,
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.45",
- "es6-symbol": "3.1.1"
- }
- },
- "es6-promise": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz",
- "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==",
- "dev": true
- },
- "es6-promisify": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
- "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
- "dev": true,
- "requires": {
- "es6-promise": "4.2.4"
- }
- },
- "es6-symbol": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
- "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
- "dev": true,
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.45"
- }
- },
- "escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
- "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
- },
- "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"
- }
- }
- }
- },
- "eslint-scope": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
- "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
- "dev": true,
- "requires": {
- "esrecurse": "4.2.1",
- "estraverse": "4.2.0"
- },
- "dependencies": {
- "estraverse": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
- "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
- "dev": true
- }
- }
- },
- "esprima": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
- "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
- "dev": true
- },
- "esrecurse": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
- "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
- "dev": true,
- "requires": {
- "estraverse": "4.2.0"
- },
- "dependencies": {
- "estraverse": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
- "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
- "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
- },
- "etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
- "dev": true
- },
- "eventemitter3": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
- "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==",
- "dev": true
- },
- "events": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
- "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
- "dev": true
- },
- "eventsource": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz",
- "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=",
- "dev": true,
- "requires": {
- "original": "1.0.1"
- }
- },
- "evp_bytestokey": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
- "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
- "dev": true,
- "requires": {
- "md5.js": "1.3.4",
- "safe-buffer": "5.1.2"
- }
- },
- "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"
- },
- "dependencies": {
- "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.3",
- "shebang-command": "1.2.0",
- "which": "1.3.1"
- }
- }
- }
- },
- "exit": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
- "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
- "dev": true
- },
- "expand-braces": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz",
- "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=",
- "dev": true,
- "requires": {
- "array-slice": "0.2.3",
- "array-unique": "0.2.1",
- "braces": "0.1.5"
- },
- "dependencies": {
- "array-unique": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
- "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
- "dev": true
- },
- "braces": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz",
- "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=",
- "dev": true,
- "requires": {
- "expand-range": "0.1.1"
- }
- },
- "expand-range": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz",
- "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=",
- "dev": true,
- "requires": {
- "is-number": "0.1.1",
- "repeat-string": "0.2.2"
- }
- },
- "is-number": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz",
- "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=",
- "dev": true
- },
- "repeat-string": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz",
- "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=",
- "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.2",
- "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"
- }
- }
- }
- },
- "expand-range": {
- "version": "1.8.2",
- "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
- "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
- "dev": true,
- "requires": {
- "fill-range": "2.2.4"
- },
- "dependencies": {
- "fill-range": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz",
- "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==",
- "dev": true,
- "requires": {
- "is-number": "2.1.0",
- "isobject": "2.1.0",
- "randomatic": "3.0.0",
- "repeat-element": "1.1.2",
- "repeat-string": "1.6.1"
- }
- },
- "is-number": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
- "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
- "dev": true,
- "requires": {
- "kind-of": "3.2.2"
- }
- },
- "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"
- }
- },
- "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"
- }
- }
- }
- },
- "express": {
- "version": "4.16.3",
- "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz",
- "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
- "dev": true,
- "requires": {
- "accepts": "1.3.5",
- "array-flatten": "1.1.1",
- "body-parser": "1.18.2",
- "content-disposition": "0.5.2",
- "content-type": "1.0.4",
- "cookie": "0.3.1",
- "cookie-signature": "1.0.6",
- "debug": "2.6.9",
- "depd": "1.1.2",
- "encodeurl": "1.0.2",
- "escape-html": "1.0.3",
- "etag": "1.8.1",
- "finalhandler": "1.1.1",
- "fresh": "0.5.2",
- "merge-descriptors": "1.0.1",
- "methods": "1.1.2",
- "on-finished": "2.3.0",
- "parseurl": "1.3.2",
- "path-to-regexp": "0.1.7",
- "proxy-addr": "2.0.3",
- "qs": "6.5.1",
- "range-parser": "1.2.0",
- "safe-buffer": "5.1.1",
- "send": "0.16.2",
- "serve-static": "1.13.2",
- "setprototypeof": "1.1.0",
- "statuses": "1.4.0",
- "type-is": "1.6.16",
- "utils-merge": "1.0.1",
- "vary": "1.1.2"
- },
- "dependencies": {
- "array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
- "dev": true
- },
- "qs": {
- "version": "6.5.1",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
- "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
- "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
- }
- }
- },
- "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.2",
- "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"
- }
- },
- "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-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"
- }
- }
- }
- },
- "extsprintf": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
- "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
- "dev": true
- },
- "fast-deep-equal": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
- "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
- "dev": true
- },
- "fast-json-stable-stringify": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
- "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
- "dev": true
- },
- "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
- },
- "fastparse": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz",
- "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=",
- "dev": true
- },
- "faye-websocket": {
- "version": "0.10.0",
- "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
- "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
- "dev": true,
- "requires": {
- "websocket-driver": "0.7.0"
- }
- },
- "file-loader": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
- "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
- "dev": true,
- "requires": {
- "loader-utils": "1.1.0",
- "schema-utils": "0.4.5"
- }
- },
- "filename-regex": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
- "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
- "dev": true
- },
- "fileset": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz",
- "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=",
- "dev": true,
- "requires": {
- "glob": "7.1.2",
- "minimatch": "3.0.4"
- }
- },
- "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"
- }
- }
- }
- },
- "finalhandler": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
- "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
- "dev": true,
- "requires": {
- "debug": "2.6.9",
- "encodeurl": "1.0.2",
- "escape-html": "1.0.3",
- "on-finished": "2.3.0",
- "parseurl": "1.3.2",
- "statuses": "1.4.0",
- "unpipe": "1.0.0"
- }
- },
- "find-cache-dir": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
- "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
- "dev": true,
- "requires": {
- "commondir": "1.0.1",
- "make-dir": "1.3.0",
- "pkg-dir": "2.0.0"
- }
- },
- "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"
- }
- },
- "flush-write-stream": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz",
- "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==",
- "dev": true,
- "requires": {
- "inherits": "2.0.3",
- "readable-stream": "2.3.6"
- }
- },
- "follow-redirects": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.0.tgz",
- "integrity": "sha512-fdrt472/9qQ6Kgjvb935ig6vJCuofpBUD14f9Vb+SLlm7xIe4Qva5gey8EKtv8lp7ahE1wilg3xL1znpVGtZIA==",
- "dev": true,
- "requires": {
- "debug": "3.1.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"
- }
- }
- }
- },
- "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"
- }
- },
- "foreach": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
- "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
- "dev": true
- },
- "forever-agent": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
- "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
- "dev": true
- },
- "form-data": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
- "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
- "dev": true,
- "requires": {
- "asynckit": "0.4.0",
- "combined-stream": "1.0.6",
- "mime-types": "2.1.18"
- }
- },
- "forwarded": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
- "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
- "dev": true
- },
- "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"
- }
- },
- "fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
- "dev": true
- },
- "from2": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
- "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
- "dev": true,
- "requires": {
- "inherits": "2.0.3",
- "readable-stream": "2.3.6"
- }
- },
- "fs-access": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz",
- "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=",
- "dev": true,
- "requires": {
- "null-check": "1.0.0"
- }
- },
- "fs-write-stream-atomic": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
- "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
- "dev": true,
- "requires": {
- "graceful-fs": "4.1.11",
- "iferr": "0.1.5",
- "imurmurhash": "0.1.4",
- "readable-stream": "2.3.6"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
- "dev": true
- },
- "fsevents": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz",
- "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==",
- "dev": true,
- "optional": true,
- "requires": {
- "nan": "2.10.0",
- "node-pre-gyp": "0.10.0"
- },
- "dependencies": {
- "abbrev": {
- "version": "1.1.1",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "ansi-regex": {
- "version": "2.1.1",
- "bundled": true,
- "dev": true
- },
- "aproba": {
- "version": "1.2.0",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "are-we-there-yet": {
- "version": "1.1.4",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "delegates": "1.0.0",
- "readable-stream": "2.3.6"
- }
- },
- "balanced-match": {
- "version": "1.0.0",
- "bundled": true,
- "dev": true
- },
- "brace-expansion": {
- "version": "1.1.11",
- "bundled": true,
- "dev": true,
- "requires": {
- "balanced-match": "1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "chownr": {
- "version": "1.0.1",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "code-point-at": {
- "version": "1.1.0",
- "bundled": true,
- "dev": true
- },
- "concat-map": {
- "version": "0.0.1",
- "bundled": true,
- "dev": true
- },
- "console-control-strings": {
- "version": "1.1.0",
- "bundled": true,
- "dev": true
- },
- "core-util-is": {
- "version": "1.0.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "debug": {
- "version": "2.6.9",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "deep-extend": {
- "version": "0.5.1",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "delegates": {
- "version": "1.0.0",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "detect-libc": {
- "version": "1.0.3",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "fs-minipass": {
- "version": "1.2.5",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "minipass": "2.2.4"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "gauge": {
- "version": "2.7.4",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "aproba": "1.2.0",
- "console-control-strings": "1.1.0",
- "has-unicode": "2.0.1",
- "object-assign": "4.1.1",
- "signal-exit": "3.0.2",
- "string-width": "1.0.2",
- "strip-ansi": "3.0.1",
- "wide-align": "1.1.2"
- }
- },
- "glob": {
- "version": "7.1.2",
- "bundled": true,
- "dev": true,
- "optional": 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"
- }
- },
- "has-unicode": {
- "version": "2.0.1",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "iconv-lite": {
- "version": "0.4.21",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "safer-buffer": "2.1.2"
- }
- },
- "ignore-walk": {
- "version": "3.0.1",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "minimatch": "3.0.4"
- }
- },
- "inflight": {
- "version": "1.0.6",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "once": "1.4.0",
- "wrappy": "1.0.2"
- }
- },
- "inherits": {
- "version": "2.0.3",
- "bundled": true,
- "dev": true
- },
- "ini": {
- "version": "1.3.5",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "bundled": true,
- "dev": true,
- "requires": {
- "number-is-nan": "1.0.1"
- }
- },
- "isarray": {
- "version": "1.0.0",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "minimatch": {
- "version": "3.0.4",
- "bundled": true,
- "dev": true,
- "requires": {
- "brace-expansion": "1.1.11"
- }
- },
- "minimist": {
- "version": "0.0.8",
- "bundled": true,
- "dev": true
- },
- "minipass": {
- "version": "2.2.4",
- "bundled": true,
- "dev": true,
- "requires": {
- "safe-buffer": "5.1.1",
- "yallist": "3.0.2"
- }
- },
- "minizlib": {
- "version": "1.1.0",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "minipass": "2.2.4"
- }
- },
- "mkdirp": {
- "version": "0.5.1",
- "bundled": true,
- "dev": true,
- "requires": {
- "minimist": "0.0.8"
- }
- },
- "ms": {
- "version": "2.0.0",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "needle": {
- "version": "2.2.0",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "debug": "2.6.9",
- "iconv-lite": "0.4.21",
- "sax": "1.2.4"
- }
- },
- "node-pre-gyp": {
- "version": "0.10.0",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "detect-libc": "1.0.3",
- "mkdirp": "0.5.1",
- "needle": "2.2.0",
- "nopt": "4.0.1",
- "npm-packlist": "1.1.10",
- "npmlog": "4.1.2",
- "rc": "1.2.7",
- "rimraf": "2.6.2",
- "semver": "5.5.0",
- "tar": "4.4.1"
- }
- },
- "nopt": {
- "version": "4.0.1",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "abbrev": "1.1.1",
- "osenv": "0.1.5"
- }
- },
- "npm-bundled": {
- "version": "1.0.3",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "npm-packlist": {
- "version": "1.1.10",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "ignore-walk": "3.0.1",
- "npm-bundled": "1.0.3"
- }
- },
- "npmlog": {
- "version": "4.1.2",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "are-we-there-yet": "1.1.4",
- "console-control-strings": "1.1.0",
- "gauge": "2.7.4",
- "set-blocking": "2.0.0"
- }
- },
- "number-is-nan": {
- "version": "1.0.1",
- "bundled": true,
- "dev": true
- },
- "object-assign": {
- "version": "4.1.1",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "once": {
- "version": "1.4.0",
- "bundled": true,
- "dev": true,
- "requires": {
- "wrappy": "1.0.2"
- }
- },
- "os-homedir": {
- "version": "1.0.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "os-tmpdir": {
- "version": "1.0.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "osenv": {
- "version": "0.1.5",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "os-homedir": "1.0.2",
- "os-tmpdir": "1.0.2"
- }
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "process-nextick-args": {
- "version": "2.0.0",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "rc": {
- "version": "1.2.7",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "deep-extend": "0.5.1",
- "ini": "1.3.5",
- "minimist": "1.2.0",
- "strip-json-comments": "2.0.1"
- },
- "dependencies": {
- "minimist": {
- "version": "1.2.0",
- "bundled": true,
- "dev": true,
- "optional": true
- }
- }
- },
- "readable-stream": {
- "version": "2.3.6",
- "bundled": true,
- "dev": true,
- "optional": 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.1.1",
- "util-deprecate": "1.0.2"
- }
- },
- "rimraf": {
- "version": "2.6.2",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "glob": "7.1.2"
- }
- },
- "safe-buffer": {
- "version": "5.1.1",
- "bundled": true,
- "dev": true
- },
- "safer-buffer": {
- "version": "2.1.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "sax": {
- "version": "1.2.4",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "semver": {
- "version": "5.5.0",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "set-blocking": {
- "version": "2.0.0",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "signal-exit": {
- "version": "3.0.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "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"
- }
- },
- "string_decoder": {
- "version": "1.1.1",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "safe-buffer": "5.1.1"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "bundled": true,
- "dev": true,
- "requires": {
- "ansi-regex": "2.1.1"
- }
- },
- "strip-json-comments": {
- "version": "2.0.1",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "tar": {
- "version": "4.4.1",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "chownr": "1.0.1",
- "fs-minipass": "1.2.5",
- "minipass": "2.2.4",
- "minizlib": "1.1.0",
- "mkdirp": "0.5.1",
- "safe-buffer": "5.1.1",
- "yallist": "3.0.2"
- }
- },
- "util-deprecate": {
- "version": "1.0.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "wide-align": {
- "version": "1.1.2",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "string-width": "1.0.2"
- }
- },
- "wrappy": {
- "version": "1.0.2",
- "bundled": true,
- "dev": true
- },
- "yallist": {
- "version": "3.0.2",
- "bundled": true,
- "dev": true
- }
- }
- },
- "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"
- }
- },
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
- },
- "gauge": {
- "version": "2.7.4",
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
- "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
- "dev": true,
- "requires": {
- "aproba": "1.2.0",
- "console-control-strings": "1.1.0",
- "has-unicode": "2.0.1",
- "object-assign": "4.1.1",
- "signal-exit": "3.0.2",
- "string-width": "1.0.2",
- "strip-ansi": "3.0.1",
- "wide-align": "1.1.3"
- }
- },
- "gaze": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
- "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
- "dev": true,
- "optional": true,
- "requires": {
- "globule": "1.2.1"
- }
- },
- "generate-function": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
- "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=",
- "dev": true,
- "optional": true
- },
- "generate-object-property": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
- "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
- "dev": true,
- "optional": true,
- "requires": {
- "is-property": "1.0.2"
- }
- },
- "get-caller-file": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz",
- "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
- "dev": true
- },
- "get-stdin": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
- "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
- "dev": true
- },
- "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
- },
- "getpass": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
- "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
- "dev": true,
- "requires": {
- "assert-plus": "1.0.0"
- }
- },
- "glob": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
- "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
- "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",
- "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
- "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
- "dev": true,
- "requires": {
- "glob-parent": "2.0.0",
- "is-glob": "2.0.1"
- },
- "dependencies": {
- "glob-parent": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
- "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
- "dev": true,
- "requires": {
- "is-glob": "2.0.1"
- }
- },
- "is-extglob": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
- "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
- "dev": true
- },
- "is-glob": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
- "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
- "dev": true,
- "requires": {
- "is-extglob": "1.0.0"
- }
- }
- }
- },
- "glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
- "dev": true,
- "requires": {
- "is-glob": "3.1.0",
- "path-dirname": "1.0.2"
- },
- "dependencies": {
- "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"
- }
- }
- }
- },
- "globals": {
- "version": "9.18.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
- "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
- "dev": true
- },
- "globby": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
- "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
- "dev": true,
- "requires": {
- "array-union": "1.0.2",
- "dir-glob": "2.0.0",
- "glob": "7.1.2",
- "ignore": "3.3.8",
- "pify": "3.0.0",
- "slash": "1.0.0"
- }
- },
- "globule": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
- "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "glob": "7.1.2",
- "lodash": "4.17.10",
- "minimatch": "3.0.4"
- }
- },
- "graceful-fs": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
- "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
- "dev": true
- },
- "handle-thing": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
- "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=",
- "dev": true
- },
- "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": {
- "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"
- }
- },
- "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": {
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true,
- "optional": true
- }
- }
- }
- }
- },
- "har-schema": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
- "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
- "dev": true
- },
- "har-validator": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
- "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
- "dev": true,
- "requires": {
- "ajv": "5.5.2",
- "har-schema": "2.0.0"
- },
- "dependencies": {
- "ajv": {
- "version": "5.5.2",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
- "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
- "dev": true,
- "requires": {
- "co": "4.6.0",
- "fast-deep-equal": "1.1.0",
- "fast-json-stable-stringify": "2.0.0",
- "json-schema-traverse": "0.3.1"
- }
- }
- }
- },
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "requires": {
- "function-bind": "1.1.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-binary": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz",
- "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=",
- "dev": true,
- "requires": {
- "isarray": "0.0.1"
- },
- "dependencies": {
- "isarray": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
- "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
- "dev": true
- }
- }
- },
- "has-cors": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
- "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
- "dev": true
- },
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
- "dev": true
- },
- "has-symbols": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
- "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
- "dev": true
- },
- "has-unicode": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
- "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
- "dev": true
- },
- "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"
- }
- }
- }
- },
- "hash-base": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
- "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
- "dev": true,
- "requires": {
- "inherits": "2.0.3",
- "safe-buffer": "5.1.2"
- }
- },
- "hash.js": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.4.tgz",
- "integrity": "sha512-A6RlQvvZEtFS5fLU43IDu0QUmBy+fDO9VMdTXvufKwIkt/rFfvICAViCax5fbDO4zdNzaC3/27ZhKUok5bAJyw==",
- "dev": true,
- "requires": {
- "inherits": "2.0.3",
- "minimalistic-assert": "1.0.1"
- }
- },
- "hawk": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
- "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
- "dev": true,
- "requires": {
- "boom": "2.10.1",
- "cryptiles": "2.0.5",
- "hoek": "2.16.3",
- "sntp": "1.0.9"
- }
- },
- "he": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
- "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
- "dev": true
- },
- "hmac-drbg": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
- "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
- "dev": true,
- "requires": {
- "hash.js": "1.1.4",
- "minimalistic-assert": "1.0.1",
- "minimalistic-crypto-utils": "1.0.1"
- }
- },
- "hoek": {
- "version": "2.16.3",
- "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
- "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
- "dev": true
- },
- "hosted-git-info": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz",
- "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==",
- "dev": true
- },
- "hpack.js": {
- "version": "2.1.6",
- "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
- "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
- "dev": true,
- "requires": {
- "inherits": "2.0.3",
- "obuf": "1.1.2",
- "readable-stream": "2.3.6",
- "wbuf": "1.7.3"
- }
- },
- "html-entities": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
- "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
- "dev": true
- },
- "html-minifier": {
- "version": "3.5.16",
- "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.16.tgz",
- "integrity": "sha512-zP5EfLSpiLRp0aAgud4CQXPQZm9kXwWjR/cF0PfdOj+jjWnOaCgeZcll4kYXSvIBPeUMmyaSc7mM4IDtA+kboA==",
- "dev": true,
- "requires": {
- "camel-case": "3.0.0",
- "clean-css": "4.1.11",
- "commander": "2.15.1",
- "he": "1.1.1",
- "param-case": "2.1.1",
- "relateurl": "0.2.7",
- "uglify-js": "3.3.28"
- }
- },
- "html-webpack-plugin": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz",
- "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=",
- "dev": true,
- "requires": {
- "html-minifier": "3.5.16",
- "loader-utils": "0.2.17",
- "lodash": "4.17.10",
- "pretty-error": "2.1.1",
- "tapable": "1.0.0",
- "toposort": "1.0.7",
- "util.promisify": "1.0.0"
- },
- "dependencies": {
- "loader-utils": {
- "version": "0.2.17",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz",
- "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=",
- "dev": true,
- "requires": {
- "big.js": "3.2.0",
- "emojis-list": "2.1.0",
- "json5": "0.5.1",
- "object-assign": "4.1.1"
- }
- }
- }
- },
- "htmlparser2": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz",
- "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=",
- "dev": true,
- "requires": {
- "domelementtype": "1.3.0",
- "domhandler": "2.1.0",
- "domutils": "1.1.6",
- "readable-stream": "1.0.34"
- },
- "dependencies": {
- "domutils": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz",
- "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=",
- "dev": true,
- "requires": {
- "domelementtype": "1.3.0"
- }
- },
- "isarray": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
- "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
- "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"
- }
- },
- "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
- }
- }
- },
- "http-deceiver": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
- "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
- "dev": true
- },
- "http-errors": {
- "version": "1.6.3",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
- "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
- "dev": true,
- "requires": {
- "depd": "1.1.2",
- "inherits": "2.0.3",
- "setprototypeof": "1.1.0",
- "statuses": "1.4.0"
- }
- },
- "http-parser-js": {
- "version": "0.4.13",
- "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz",
- "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=",
- "dev": true
- },
- "http-proxy": {
- "version": "1.17.0",
- "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
- "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
- "dev": true,
- "requires": {
- "eventemitter3": "3.1.0",
- "follow-redirects": "1.5.0",
- "requires-port": "1.0.0"
- }
- },
- "http-proxy-middleware": {
- "version": "0.18.0",
- "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz",
- "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==",
- "dev": true,
- "requires": {
- "http-proxy": "1.17.0",
- "is-glob": "4.0.0",
- "lodash": "4.17.10",
- "micromatch": "3.1.10"
- }
- },
- "http-signature": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
- "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
- "dev": true,
- "requires": {
- "assert-plus": "1.0.0",
- "jsprim": "1.4.1",
- "sshpk": "1.14.2"
- }
- },
- "https-browserify": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
- "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
- "dev": true
- },
- "https-proxy-agent": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
- "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
- "dev": true,
- "requires": {
- "agent-base": "4.2.0",
- "debug": "3.1.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"
- }
- }
- }
- },
- "iconv-lite": {
- "version": "0.4.19",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
- "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
- "dev": true
- },
- "ieee754": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz",
- "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==",
- "dev": true
- },
- "iferr": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
- "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
- "dev": true
- },
- "ignore": {
- "version": "3.3.8",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz",
- "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==",
- "dev": true
- },
- "image-size": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
- "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
- "dev": true,
- "optional": true
- },
- "immediate": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
- "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=",
- "dev": true
- },
- "import-local": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz",
- "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==",
- "dev": true,
- "requires": {
- "pkg-dir": "2.0.0",
- "resolve-cwd": "2.0.0"
- }
- },
- "imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
- "dev": true
- },
- "in-publish": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
- "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=",
- "dev": true,
- "optional": true
- },
- "indent-string": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
- "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
- "dev": true,
- "requires": {
- "repeating": "2.0.1"
- }
- },
- "indexof": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
- "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
- "dev": true
- },
- "inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
- "dev": true,
- "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=",
- "dev": true
- },
- "ini": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
- "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
- "dev": true
- },
- "internal-ip": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz",
- "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=",
- "dev": true,
- "requires": {
- "meow": "3.7.0"
- }
- },
- "invariant": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
- "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
- "dev": true,
- "requires": {
- "loose-envify": "1.3.1"
- }
- },
- "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=",
- "dev": true
- },
- "ip": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
- "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
- "dev": true
- },
- "ipaddr.js": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz",
- "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=",
- "dev": true
- },
- "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-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
- "dev": true
- },
- "is-binary-path": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
- "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
- "dev": true,
- "requires": {
- "binary-extensions": "1.11.0"
- }
- },
- "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-callable": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
- "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
- "dev": true
- },
- "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-date-object": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
- "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
- "dev": true
- },
- "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
- }
- }
- },
- "is-directory": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
- "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
- "dev": true
- },
- "is-dotfile": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
- "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
- "dev": true
- },
- "is-equal-shallow": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
- "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
- "dev": true,
- "requires": {
- "is-primitive": "2.0.0"
- }
- },
- "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-finite": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
- "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
- "dev": true,
- "requires": {
- "number-is-nan": "1.0.1"
- }
- },
- "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=",
- "dev": true,
- "requires": {
- "number-is-nan": "1.0.1"
- }
- },
- "is-glob": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
- "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
- "dev": true,
- "requires": {
- "is-extglob": "2.1.1"
- }
- },
- "is-my-ip-valid": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz",
- "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==",
- "dev": true,
- "optional": true
- },
- "is-my-json-valid": {
- "version": "2.17.2",
- "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz",
- "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==",
- "dev": true,
- "optional": true,
- "requires": {
- "generate-function": "2.0.0",
- "generate-object-property": "1.2.0",
- "is-my-ip-valid": "1.0.0",
- "jsonpointer": "4.0.1",
- "xtend": "4.0.1"
- }
- },
- "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-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-cwd": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
- "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
- "dev": true
- },
- "is-path-in-cwd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
- "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
- "dev": true,
- "requires": {
- "is-path-inside": "1.0.1"
- }
- },
- "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-posix-bracket": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
- "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
- "dev": true
- },
- "is-primitive": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
- "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
- "dev": true
- },
- "is-property": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
- "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=",
- "dev": true,
- "optional": true
- },
- "is-regex": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
- "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
- "dev": true,
- "requires": {
- "has": "1.0.3"
- }
- },
- "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-symbol": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
- "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
- "dev": true
- },
- "is-typedarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
- "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
- "dev": true
- },
- "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
- },
- "is-wsl": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
- "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
- "dev": true
- },
- "isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
- "dev": true
- },
- "isbinaryfile": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz",
- "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=",
- "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=",
- "dev": true
- },
- "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.12.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.1",
- "wordwrap": "1.0.0"
- },
- "dependencies": {
- "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"
- }
- },
- "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
- },
- "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-api": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.1.tgz",
- "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==",
- "dev": true,
- "requires": {
- "async": "2.6.1",
- "compare-versions": "3.3.0",
- "fileset": "2.0.3",
- "istanbul-lib-coverage": "1.2.0",
- "istanbul-lib-hook": "1.2.1",
- "istanbul-lib-instrument": "1.10.1",
- "istanbul-lib-report": "1.1.4",
- "istanbul-lib-source-maps": "1.2.5",
- "istanbul-reports": "1.3.0",
- "js-yaml": "3.12.0",
- "mkdirp": "0.5.1",
- "once": "1.4.0"
- },
- "dependencies": {
- "async": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
- "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
- "dev": true,
- "requires": {
- "lodash": "4.17.10"
- }
- }
- }
- },
- "istanbul-instrumenter-loader": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz",
- "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==",
- "dev": true,
- "requires": {
- "convert-source-map": "1.5.1",
- "istanbul-lib-instrument": "1.10.1",
- "loader-utils": "1.1.0",
- "schema-utils": "0.3.0"
- },
- "dependencies": {
- "ajv": {
- "version": "5.5.2",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
- "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
- "dev": true,
- "requires": {
- "co": "4.6.0",
- "fast-deep-equal": "1.1.0",
- "fast-json-stable-stringify": "2.0.0",
- "json-schema-traverse": "0.3.1"
- }
- },
- "schema-utils": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
- "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=",
- "dev": true,
- "requires": {
- "ajv": "5.5.2"
- }
- }
- }
- },
- "istanbul-lib-coverage": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz",
- "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==",
- "dev": true
- },
- "istanbul-lib-hook": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz",
- "integrity": "sha512-eLAMkPG9FU0v5L02lIkcj/2/Zlz9OuluaXikdr5iStk8FDbSwAixTK9TkYxbF0eNnzAJTwM2fkV2A1tpsIp4Jg==",
- "dev": true,
- "requires": {
- "append-transform": "1.0.0"
- }
- },
- "istanbul-lib-instrument": {
- "version": "1.10.1",
- "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz",
- "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==",
- "dev": true,
- "requires": {
- "babel-generator": "6.26.1",
- "babel-template": "6.26.0",
- "babel-traverse": "6.26.0",
- "babel-types": "6.26.0",
- "babylon": "6.18.0",
- "istanbul-lib-coverage": "1.2.0",
- "semver": "5.5.0"
- }
- },
- "istanbul-lib-report": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz",
- "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==",
- "dev": true,
- "requires": {
- "istanbul-lib-coverage": "1.2.0",
- "mkdirp": "0.5.1",
- "path-parse": "1.0.5",
- "supports-color": "3.2.3"
- },
- "dependencies": {
- "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
- },
- "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-lib-source-maps": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz",
- "integrity": "sha512-8O2T/3VhrQHn0XcJbP1/GN7kXMiRAlPi+fj3uEHrjBD8Oz7Py0prSC25C09NuAZS6bgW1NNKAvCSHZXB0irSGA==",
- "dev": true,
- "requires": {
- "debug": "3.1.0",
- "istanbul-lib-coverage": "1.2.0",
- "mkdirp": "0.5.1",
- "rimraf": "2.6.2",
- "source-map": "0.5.7"
- },
- "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"
- }
- }
- }
- },
- "istanbul-reports": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.3.0.tgz",
- "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==",
- "dev": true,
- "requires": {
- "handlebars": "4.0.11"
- }
- },
- "jasmine": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz",
- "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=",
- "dev": true,
- "requires": {
- "exit": "0.1.2",
- "glob": "7.1.2",
- "jasmine-core": "2.8.0"
- },
- "dependencies": {
- "jasmine-core": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz",
- "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=",
- "dev": true
- }
- }
- },
- "jasmine-core": {
- "version": "2.99.1",
- "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
- "integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=",
- "dev": true
- },
- "jasmine-spec-reporter": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz",
- "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==",
- "dev": true,
- "requires": {
- "colors": "1.1.2"
- }
- },
- "jasminewd2": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz",
- "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=",
- "dev": true
- },
- "js-base64": {
- "version": "2.4.5",
- "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.5.tgz",
- "integrity": "sha512-aUnNwqMOXw3yvErjMPSQu6qIIzUmT1e5KcU1OZxRDU1g/am6mzBvcrmLAYwzmB59BHPrh5/tKaiF4OPhqRWESQ==",
- "dev": true,
- "optional": true
- },
- "js-tokens": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
- "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
- "dev": true
- },
- "js-yaml": {
- "version": "3.12.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
- "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
- "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
- }
- }
- },
- "jsbn": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
- "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
- "dev": true,
- "optional": true
- },
- "jsesc": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
- "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
- "dev": true
- },
- "json-schema": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
- "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
- "dev": true
- },
- "json-schema-traverse": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
- "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
- "dev": true
- },
- "json-stable-stringify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
- "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
- "dev": true,
- "optional": true,
- "requires": {
- "jsonify": "0.0.0"
- }
- },
- "json-stringify-safe": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
- "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
- "dev": true
- },
- "json3": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
- "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
- "dev": true
- },
- "json5": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
- "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
- "dev": true
- },
- "jsonify": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
- "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
- "dev": true,
- "optional": true
- },
- "jsonpointer": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
- "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=",
- "dev": true,
- "optional": true
- },
- "jsprim": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
- "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
- "dev": true,
- "requires": {
- "assert-plus": "1.0.0",
- "extsprintf": "1.3.0",
- "json-schema": "0.2.3",
- "verror": "1.10.0"
- }
- },
- "jszip": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz",
- "integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==",
- "dev": true,
- "requires": {
- "core-js": "2.3.0",
- "es6-promise": "3.0.2",
- "lie": "3.1.1",
- "pako": "1.0.6",
- "readable-stream": "2.0.6"
- },
- "dependencies": {
- "core-js": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz",
- "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=",
- "dev": true
- },
- "es6-promise": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz",
- "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=",
- "dev": true
- },
- "process-nextick-args": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
- "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
- "dev": true
- },
- "readable-stream": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
- "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
- "dev": true,
- "requires": {
- "core-util-is": "1.0.2",
- "inherits": "2.0.3",
- "isarray": "1.0.0",
- "process-nextick-args": "1.0.7",
- "string_decoder": "0.10.31",
- "util-deprecate": "1.0.2"
- }
- },
- "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
- }
- }
- },
- "karma": {
- "version": "1.7.1",
- "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz",
- "integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==",
- "dev": true,
- "requires": {
- "bluebird": "3.5.1",
- "body-parser": "1.18.2",
- "chokidar": "1.7.0",
- "colors": "1.1.2",
- "combine-lists": "1.0.1",
- "connect": "3.6.6",
- "core-js": "2.5.7",
- "di": "0.0.1",
- "dom-serialize": "2.2.1",
- "expand-braces": "0.1.2",
- "glob": "7.1.2",
- "graceful-fs": "4.1.11",
- "http-proxy": "1.17.0",
- "isbinaryfile": "3.0.2",
- "lodash": "3.10.1",
- "log4js": "0.6.38",
- "mime": "1.6.0",
- "minimatch": "3.0.4",
- "optimist": "0.6.1",
- "qjobs": "1.2.0",
- "range-parser": "1.2.0",
- "rimraf": "2.6.2",
- "safe-buffer": "5.1.2",
- "socket.io": "1.7.3",
- "source-map": "0.5.7",
- "tmp": "0.0.31",
- "useragent": "2.3.0"
- },
- "dependencies": {
- "anymatch": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
- "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
- "dev": true,
- "requires": {
- "micromatch": "2.3.11",
- "normalize-path": "2.1.1"
- }
- },
- "arr-diff": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
- "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
- "dev": true,
- "requires": {
- "arr-flatten": "1.1.0"
- }
- },
- "array-unique": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
- "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
- "dev": true
- },
- "braces": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
- "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
- "dev": true,
- "requires": {
- "expand-range": "1.8.2",
- "preserve": "0.2.0",
- "repeat-element": "1.1.2"
- }
- },
- "chokidar": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
- "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
- "dev": true,
- "requires": {
- "anymatch": "1.3.2",
- "async-each": "1.0.1",
- "fsevents": "1.2.4",
- "glob-parent": "2.0.0",
- "inherits": "2.0.3",
- "is-binary-path": "1.0.1",
- "is-glob": "2.0.1",
- "path-is-absolute": "1.0.1",
- "readdirp": "2.1.0"
- }
- },
- "expand-brackets": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
- "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
- "dev": true,
- "requires": {
- "is-posix-bracket": "0.1.1"
- }
- },
- "extglob": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
- "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
- "dev": true,
- "requires": {
- "is-extglob": "1.0.0"
- }
- },
- "glob-parent": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
- "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
- "dev": true,
- "requires": {
- "is-glob": "2.0.1"
- }
- },
- "is-extglob": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
- "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
- "dev": true
- },
- "is-glob": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
- "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
- "dev": true,
- "requires": {
- "is-extglob": "1.0.0"
- }
- },
- "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"
- }
- },
- "lodash": {
- "version": "3.10.1",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
- "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
- "dev": true
- },
- "micromatch": {
- "version": "2.3.11",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
- "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
- "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"
- }
- }
- }
- },
- "karma-chrome-launcher": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz",
- "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==",
- "dev": true,
- "requires": {
- "fs-access": "1.0.1",
- "which": "1.3.1"
- }
- },
- "karma-coverage-istanbul-reporter": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.0.1.tgz",
- "integrity": "sha512-UcgrHkFehI5+ivMouD8NH/UOHiX4oCAtwaANylzPFdcAuD52fnCUuelacq2gh8tZ4ydhU3+xiXofSq7j5Ehygw==",
- "dev": true,
- "requires": {
- "istanbul-api": "1.3.1",
- "minimatch": "3.0.4"
- }
- },
- "karma-jasmine": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.2.tgz",
- "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=",
- "dev": true
- },
- "karma-jasmine-html-reporter": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz",
- "integrity": "sha1-SKjl7xiAdhfuK14zwRlMNbQ5Ukw=",
- "dev": true,
- "requires": {
- "karma-jasmine": "1.1.2"
- }
- },
- "karma-source-map-support": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.3.0.tgz",
- "integrity": "sha512-HcPqdAusNez/ywa+biN4EphGz62MmQyPggUsDfsHqa7tSe4jdsxgvTKuDfIazjL+IOxpVWyT7Pr4dhAV+sxX5Q==",
- "dev": true,
- "requires": {
- "source-map-support": "0.5.6"
- }
- },
- "killable": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz",
- "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=",
- "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
- },
- "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
- },
- "lcid": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
- "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
- "dev": true,
- "requires": {
- "invert-kv": "1.0.0"
- }
- },
- "leb": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/leb/-/leb-0.3.0.tgz",
- "integrity": "sha1-Mr7p+tFoMo1q6oUi2DP0GA7tHaM=",
- "dev": true
- },
- "less": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/less/-/less-3.0.4.tgz",
- "integrity": "sha512-q3SyEnPKbk9zh4l36PGeW2fgynKu+FpbhiUNx/yaiBUQ3V0CbACCgb9FzYWcRgI2DJlP6eI4jc8XPrCTi55YcQ==",
- "dev": true,
- "requires": {
- "errno": "0.1.7",
- "graceful-fs": "4.1.11",
- "image-size": "0.5.5",
- "mime": "1.6.0",
- "mkdirp": "0.5.1",
- "promise": "7.3.1",
- "request": "2.87.0",
- "source-map": "0.6.1"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "optional": true
- }
- }
- },
- "less-loader": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.1.0.tgz",
- "integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==",
- "dev": true,
- "requires": {
- "clone": "2.1.1",
- "loader-utils": "1.1.0",
- "pify": "3.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"
- }
- },
- "license-webpack-plugin": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-1.3.1.tgz",
- "integrity": "sha512-NqAFodJdpBUuf1iD+Ij8hQvF0rCFKlO2KaieoQzAPhFgzLCtJnC7Z7x5gQbGNjoe++wOKAtAmwVEIBLqq2Yp1A==",
- "dev": true,
- "requires": {
- "ejs": "2.6.1"
- }
- },
- "lie": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
- "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
- "dev": true,
- "requires": {
- "immediate": "3.0.6"
- }
- },
- "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": {
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- }
- }
- },
- "loader-runner": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz",
- "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=",
- "dev": true
- },
- "loader-utils": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
- "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
- "dev": true,
- "requires": {
- "big.js": "3.2.0",
- "emojis-list": "2.1.0",
- "json5": "0.5.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.10",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
- "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
- "dev": true
- },
- "lodash.assign": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
- "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
- "dev": true,
- "optional": true
- },
- "lodash.clonedeep": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
- "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
- "dev": true
- },
- "lodash.mergewith": {
- "version": "4.6.1",
- "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
- "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==",
- "dev": true,
- "optional": true
- },
- "lodash.tail": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz",
- "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=",
- "dev": true
- },
- "log-symbols": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
- "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
- "dev": true,
- "requires": {
- "chalk": "2.2.2"
- }
- },
- "log4js": {
- "version": "0.6.38",
- "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz",
- "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=",
- "dev": true,
- "requires": {
- "readable-stream": "1.0.34",
- "semver": "4.3.6"
- },
- "dependencies": {
- "isarray": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
- "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
- "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"
- }
- },
- "semver": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
- "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=",
- "dev": true
- },
- "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
- }
- }
- },
- "loglevel": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz",
- "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=",
- "dev": true
- },
- "loglevelnext": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz",
- "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==",
- "dev": true,
- "requires": {
- "es6-symbol": "3.1.1",
- "object.assign": "4.1.0"
- }
- },
- "long": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
- "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=",
- "dev": true
- },
- "longest": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
- "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
- "dev": true
- },
- "loose-envify": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
- "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
- "dev": true,
- "requires": {
- "js-tokens": "3.0.2"
- }
- },
- "loud-rejection": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
- "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
- "dev": true,
- "requires": {
- "currently-unhandled": "0.4.1",
- "signal-exit": "3.0.2"
- }
- },
- "lower-case": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
- "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
- "dev": true
- },
- "lru-cache": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
- "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
- "dev": true,
- "requires": {
- "pseudomap": "1.0.2",
- "yallist": "2.1.2"
- }
- },
- "make-dir": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
- "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
- "dev": true,
- "requires": {
- "pify": "3.0.0"
- }
- },
- "make-error": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz",
- "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==",
- "dev": true
- },
- "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-obj": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
- "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
- "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"
- }
- },
- "math-random": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz",
- "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=",
- "dev": true
- },
- "md5.js": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
- "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
- "dev": true,
- "requires": {
- "hash-base": "3.0.4",
- "inherits": "2.0.3"
- }
- },
- "media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
- "dev": true
- },
- "mem": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
- "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
- "dev": true,
- "requires": {
- "mimic-fn": "1.2.0"
- }
- },
- "memory-fs": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
- "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
- "dev": true,
- "requires": {
- "errno": "0.1.7",
- "readable-stream": "2.3.6"
- }
- },
- "meow": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
- "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
- "dev": true,
- "requires": {
- "camelcase-keys": "2.1.0",
- "decamelize": "1.2.0",
- "loud-rejection": "1.6.0",
- "map-obj": "1.0.1",
- "minimist": "1.2.0",
- "normalize-package-data": "2.4.0",
- "object-assign": "4.1.1",
- "read-pkg-up": "1.0.1",
- "redent": "1.0.0",
- "trim-newlines": "1.0.0"
- },
- "dependencies": {
- "minimist": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
- "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
- "dev": true
- }
- }
- },
- "merge-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
- "dev": true
- },
- "methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
- "dev": true
- },
- "micromatch": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
- "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
- "dev": true,
- "requires": {
- "arr-diff": "4.0.0",
- "array-unique": "0.3.2",
- "braces": "2.3.2",
- "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.2",
- "to-regex": "3.0.2"
- }
- },
- "miller-rabin": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
- "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
- "dev": true,
- "requires": {
- "bn.js": "4.11.8",
- "brorand": "1.1.0"
- }
- },
- "mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "dev": true
- },
- "mime-db": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
- "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==",
- "dev": true
- },
- "mime-types": {
- "version": "2.1.18",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
- "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
- "dev": true,
- "requires": {
- "mime-db": "1.33.0"
- }
- },
- "mimic-fn": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
- "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
- "dev": true
- },
- "mini-css-extract-plugin": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.0.tgz",
- "integrity": "sha512-2Zik6PhUZ/MbiboG6SDS9UTPL4XXy4qnyGjSdCIWRrr8xb6PwLtHE+AYOjkXJWdF0OG8vo/yrJ8CgS5WbMpzIg==",
- "dev": true,
- "requires": {
- "loader-utils": "1.1.0",
- "webpack-sources": "1.1.0"
- }
- },
- "minimalistic-assert": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
- "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
- "dev": true
- },
- "minimalistic-crypto-utils": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
- "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
- "dev": true
- },
- "minimatch": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
- "dev": true,
- "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=",
- "dev": true
- },
- "mississippi": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz",
- "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==",
- "dev": true,
- "requires": {
- "concat-stream": "1.6.2",
- "duplexify": "3.6.0",
- "end-of-stream": "1.4.1",
- "flush-write-stream": "1.0.3",
- "from2": "2.3.0",
- "parallel-transform": "1.1.0",
- "pump": "2.0.1",
- "pumpify": "1.5.1",
- "stream-each": "1.2.2",
- "through2": "2.0.3"
- }
- },
- "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"
- }
- }
- }
- },
- "mixin-object": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz",
- "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=",
- "dev": true,
- "requires": {
- "for-in": "0.1.8",
- "is-extendable": "0.1.1"
- },
- "dependencies": {
- "for-in": {
- "version": "0.1.8",
- "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz",
- "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=",
- "dev": true
- }
- }
- },
- "mkdirp": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
- "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
- "dev": true,
- "requires": {
- "minimist": "0.0.8"
- }
- },
- "moment": {
- "version": "2.22.2",
- "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz",
- "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y="
- },
- "moment-timezone": {
- "version": "0.5.21",
- "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.21.tgz",
- "integrity": "sha512-j96bAh4otsgj3lKydm3K7kdtA3iKf2m6MY2iSYCzCm5a1zmHo1g+aK3068dDEeocLZQIS9kU8bsdQHLqEvgW0A==",
- "requires": {
- "moment": "2.22.2"
- }
- },
- "move-concurrently": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
- "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
- "dev": true,
- "requires": {
- "aproba": "1.2.0",
- "copy-concurrently": "1.0.5",
- "fs-write-stream-atomic": "1.0.10",
- "mkdirp": "0.5.1",
- "rimraf": "2.6.2",
- "run-queue": "1.0.3"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- },
- "multicast-dns": {
- "version": "6.2.3",
- "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
- "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
- "dev": true,
- "requires": {
- "dns-packet": "1.3.1",
- "thunky": "1.0.2"
- }
- },
- "multicast-dns-service-types": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
- "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
- "dev": true
- },
- "nan": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
- "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
- "dev": true,
- "optional": 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.2",
- "to-regex": "3.0.2"
- }
- },
- "negotiator": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
- "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
- "dev": true
- },
- "neo-async": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz",
- "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==",
- "dev": true
- },
- "next-tick": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
- "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
- "dev": true
- },
- "no-case": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
- "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
- "dev": true,
- "requires": {
- "lower-case": "1.1.4"
- }
- },
- "node-forge": {
- "version": "0.7.5",
- "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
- "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==",
- "dev": true
- },
- "node-gyp": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.7.0.tgz",
- "integrity": "sha512-qDQE/Ft9xXP6zphwx4sD0t+VhwV7yFaloMpfbL2QnnDZcyaiakWlLdtFGGQfTAwpFHdpbRhRxVhIHN1OKAjgbg==",
- "dev": true,
- "optional": true,
- "requires": {
- "fstream": "1.0.11",
- "glob": "7.1.2",
- "graceful-fs": "4.1.11",
- "mkdirp": "0.5.1",
- "nopt": "3.0.6",
- "npmlog": "4.1.2",
- "osenv": "0.1.5",
- "request": "2.81.0",
- "rimraf": "2.6.2",
- "semver": "5.3.0",
- "tar": "2.2.1",
- "which": "1.3.1"
- },
- "dependencies": {
- "ajv": {
- "version": "4.11.8",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
- "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
- "dev": true,
- "optional": true,
- "requires": {
- "co": "4.6.0",
- "json-stable-stringify": "1.0.1"
- }
- },
- "assert-plus": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
- "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
- "dev": true,
- "optional": true
- },
- "aws-sign2": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
- "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
- "dev": true,
- "optional": true
- },
- "form-data": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
- "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
- "dev": true,
- "optional": true,
- "requires": {
- "asynckit": "0.4.0",
- "combined-stream": "1.0.6",
- "mime-types": "2.1.18"
- }
- },
- "har-schema": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
- "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=",
- "dev": true,
- "optional": true
- },
- "har-validator": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
- "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
- "dev": true,
- "optional": true,
- "requires": {
- "ajv": "4.11.8",
- "har-schema": "1.0.5"
- }
- },
- "http-signature": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
- "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
- "dev": true,
- "optional": true,
- "requires": {
- "assert-plus": "0.2.0",
- "jsprim": "1.4.1",
- "sshpk": "1.14.2"
- }
- },
- "performance-now": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
- "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=",
- "dev": true,
- "optional": true
- },
- "qs": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
- "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=",
- "dev": true,
- "optional": true
- },
- "request": {
- "version": "2.81.0",
- "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
- "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
- "dev": true,
- "optional": true,
- "requires": {
- "aws-sign2": "0.6.0",
- "aws4": "1.7.0",
- "caseless": "0.12.0",
- "combined-stream": "1.0.6",
- "extend": "3.0.1",
- "forever-agent": "0.6.1",
- "form-data": "2.1.4",
- "har-validator": "4.2.1",
- "hawk": "3.1.3",
- "http-signature": "1.1.1",
- "is-typedarray": "1.0.0",
- "isstream": "0.1.2",
- "json-stringify-safe": "5.0.1",
- "mime-types": "2.1.18",
- "oauth-sign": "0.8.2",
- "performance-now": "0.2.0",
- "qs": "6.4.0",
- "safe-buffer": "5.1.2",
- "stringstream": "0.0.6",
- "tough-cookie": "2.3.4",
- "tunnel-agent": "0.6.0",
- "uuid": "3.2.1"
- }
- },
- "semver": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
- "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
- "dev": true,
- "optional": true
- }
- }
- },
- "node-libs-browser": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz",
- "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==",
- "dev": true,
- "requires": {
- "assert": "1.4.1",
- "browserify-zlib": "0.2.0",
- "buffer": "4.9.1",
- "console-browserify": "1.1.0",
- "constants-browserify": "1.0.0",
- "crypto-browserify": "3.12.0",
- "domain-browser": "1.2.0",
- "events": "1.1.1",
- "https-browserify": "1.0.0",
- "os-browserify": "0.3.0",
- "path-browserify": "0.0.0",
- "process": "0.11.10",
- "punycode": "1.4.1",
- "querystring-es3": "0.2.1",
- "readable-stream": "2.3.6",
- "stream-browserify": "2.0.1",
- "stream-http": "2.8.3",
- "string_decoder": "1.1.1",
- "timers-browserify": "2.0.10",
- "tty-browserify": "0.0.0",
- "url": "0.11.0",
- "util": "0.10.4",
- "vm-browserify": "0.0.4"
- },
- "dependencies": {
- "punycode": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
- "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
- "dev": true
- }
- }
- },
- "node-sass": {
- "version": "4.9.0",
- "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.0.tgz",
- "integrity": "sha512-QFHfrZl6lqRU3csypwviz2XLgGNOoWQbo2GOvtsfQqOfL4cy1BtWnhx/XUeAO9LT3ahBzSRXcEO6DdvAH9DzSg==",
- "dev": true,
- "optional": true,
- "requires": {
- "async-foreach": "0.1.3",
- "chalk": "1.1.3",
- "cross-spawn": "3.0.1",
- "gaze": "1.1.3",
- "get-stdin": "4.0.1",
- "glob": "7.1.2",
- "in-publish": "2.0.0",
- "lodash.assign": "4.2.0",
- "lodash.clonedeep": "4.5.0",
- "lodash.mergewith": "4.6.1",
- "meow": "3.7.0",
- "mkdirp": "0.5.1",
- "nan": "2.10.0",
- "node-gyp": "3.7.0",
- "npmlog": "4.1.2",
- "request": "2.79.0",
- "sass-graph": "2.2.4",
- "stdout-stream": "1.4.0",
- "true-case-path": "1.0.2"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
- "dev": true
- },
- "assert-plus": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
- "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
- "dev": true,
- "optional": true
- },
- "aws-sign2": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
- "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
- "dev": true,
- "optional": true
- },
- "caseless": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
- "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=",
- "dev": true,
- "optional": true
- },
- "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"
- }
- },
- "form-data": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
- "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
- "dev": true,
- "optional": true,
- "requires": {
- "asynckit": "0.4.0",
- "combined-stream": "1.0.6",
- "mime-types": "2.1.18"
- }
- },
- "har-validator": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
- "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=",
- "dev": true,
- "optional": true,
- "requires": {
- "chalk": "1.1.3",
- "commander": "2.15.1",
- "is-my-json-valid": "2.17.2",
- "pinkie-promise": "2.0.1"
- }
- },
- "http-signature": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
- "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
- "dev": true,
- "optional": true,
- "requires": {
- "assert-plus": "0.2.0",
- "jsprim": "1.4.1",
- "sshpk": "1.14.2"
- }
- },
- "qs": {
- "version": "6.3.2",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz",
- "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=",
- "dev": true,
- "optional": true
- },
- "request": {
- "version": "2.79.0",
- "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz",
- "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=",
- "dev": true,
- "optional": true,
- "requires": {
- "aws-sign2": "0.6.0",
- "aws4": "1.7.0",
- "caseless": "0.11.0",
- "combined-stream": "1.0.6",
- "extend": "3.0.1",
- "forever-agent": "0.6.1",
- "form-data": "2.1.4",
- "har-validator": "2.0.6",
- "hawk": "3.1.3",
- "http-signature": "1.1.1",
- "is-typedarray": "1.0.0",
- "isstream": "0.1.2",
- "json-stringify-safe": "5.0.1",
- "mime-types": "2.1.18",
- "oauth-sign": "0.8.2",
- "qs": "6.3.2",
- "stringstream": "0.0.6",
- "tough-cookie": "2.3.4",
- "tunnel-agent": "0.4.3",
- "uuid": "3.2.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
- },
- "tunnel-agent": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
- "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=",
- "dev": true,
- "optional": true
- }
- }
- },
- "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.6.0",
- "is-builtin-module": "1.0.0",
- "semver": "5.5.0",
- "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"
- }
- },
- "normalize-range": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
- "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
- "dev": true
- },
- "npm-package-arg": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.0.tgz",
- "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==",
- "dev": true,
- "requires": {
- "hosted-git-info": "2.6.0",
- "osenv": "0.1.5",
- "semver": "5.5.0",
- "validate-npm-package-name": "3.0.0"
- }
- },
- "npm-registry-client": {
- "version": "8.5.1",
- "resolved": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-8.5.1.tgz",
- "integrity": "sha512-7rjGF2eA7hKDidGyEWmHTiKfXkbrcQAsGL/Rh4Rt3x3YNRNHhwaTzVJfW3aNvvlhg4G62VCluif0sLCb/i51Hg==",
- "dev": true,
- "requires": {
- "concat-stream": "1.6.2",
- "graceful-fs": "4.1.11",
- "normalize-package-data": "2.4.0",
- "npm-package-arg": "6.1.0",
- "npmlog": "4.1.2",
- "once": "1.4.0",
- "request": "2.87.0",
- "retry": "0.10.1",
- "safe-buffer": "5.1.2",
- "semver": "5.5.0",
- "slide": "1.1.6",
- "ssri": "5.3.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"
- }
- },
- "npmlog": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
- "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
- "dev": true,
- "requires": {
- "are-we-there-yet": "1.1.5",
- "console-control-strings": "1.1.0",
- "gauge": "2.7.4",
- "set-blocking": "2.0.0"
- }
- },
- "nth-check": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz",
- "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=",
- "dev": true,
- "requires": {
- "boolbase": "1.0.0"
- }
- },
- "null-check": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz",
- "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=",
- "dev": true
- },
- "num2fraction": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
- "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
- "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=",
- "dev": true
- },
- "oauth-sign": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
- "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
- "dev": true
- },
- "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
- },
- "object-component": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
- "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
- "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"
- }
- },
- "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-keys": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
- "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=",
- "dev": true
- },
- "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.assign": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
- "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
- "dev": true,
- "requires": {
- "define-properties": "1.1.2",
- "function-bind": "1.1.1",
- "has-symbols": "1.0.0",
- "object-keys": "1.0.11"
- }
- },
- "object.getownpropertydescriptors": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
- "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
- "dev": true,
- "requires": {
- "define-properties": "1.1.2",
- "es-abstract": "1.12.0"
- }
- },
- "object.omit": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
- "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
- "dev": true,
- "requires": {
- "for-own": "0.1.5",
- "is-extendable": "0.1.1"
- },
- "dependencies": {
- "for-own": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
- "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
- "dev": true,
- "requires": {
- "for-in": "1.0.2"
- }
- }
- }
- },
- "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"
- }
- },
- "obuf": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
- "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
- "dev": true
- },
- "on-finished": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
- "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
- "dev": true,
- "requires": {
- "ee-first": "1.1.1"
- }
- },
- "on-headers": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
- "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=",
- "dev": true
- },
- "once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "dev": true,
- "requires": {
- "wrappy": "1.0.2"
- }
- },
- "opn": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
- "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==",
- "dev": true,
- "requires": {
- "is-wsl": "1.1.0"
- }
- },
- "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"
- }
- },
- "options": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz",
- "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=",
- "dev": true
- },
- "original": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/original/-/original-1.0.1.tgz",
- "integrity": "sha512-IEvtB5vM5ULvwnqMxWBLxkS13JIEXbakizMSo3yoPNPCIWzg8TG3Usn/UhXoZFM/m+FuEA20KdzPSFq/0rS+UA==",
- "dev": true,
- "requires": {
- "url-parse": "1.4.1"
- }
- },
- "os-browserify": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
- "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
- "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=",
- "dev": true,
- "optional": true,
- "requires": {
- "lcid": "1.0.0"
- }
- },
- "os-tmpdir": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
- "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
- "dev": true
- },
- "osenv": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
- "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
- "dev": true,
- "requires": {
- "os-homedir": "1.0.2",
- "os-tmpdir": "1.0.2"
- }
- },
- "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.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
- "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
- "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.3.0"
- }
- },
- "p-map": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
- "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
- "dev": true
- },
- "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
- },
- "pako": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
- "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==",
- "dev": true
- },
- "parallel-transform": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz",
- "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
- "dev": true,
- "requires": {
- "cyclist": "0.2.2",
- "inherits": "2.0.3",
- "readable-stream": "2.3.6"
- }
- },
- "param-case": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
- "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
- "dev": true,
- "requires": {
- "no-case": "2.3.2"
- }
- },
- "parse-asn1": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
- "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==",
- "dev": true,
- "requires": {
- "asn1.js": "4.10.1",
- "browserify-aes": "1.2.0",
- "create-hash": "1.2.0",
- "evp_bytestokey": "1.0.3",
- "pbkdf2": "3.0.16"
- }
- },
- "parse-glob": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
- "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
- "dev": true,
- "requires": {
- "glob-base": "0.3.0",
- "is-dotfile": "1.0.3",
- "is-extglob": "1.0.0",
- "is-glob": "2.0.1"
- },
- "dependencies": {
- "is-extglob": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
- "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
- "dev": true
- },
- "is-glob": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
- "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
- "dev": true,
- "requires": {
- "is-extglob": "1.0.0"
- }
- }
- }
- },
- "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"
- }
- },
- "parse5": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
- "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
- "dev": true
- },
- "parsejson": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz",
- "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=",
- "dev": true,
- "requires": {
- "better-assert": "1.0.2"
- }
- },
- "parseqs": {
- "version": "0.0.5",
- "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
- "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
- "dev": true,
- "requires": {
- "better-assert": "1.0.2"
- }
- },
- "parseuri": {
- "version": "0.0.5",
- "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
- "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
- "dev": true,
- "requires": {
- "better-assert": "1.0.2"
- }
- },
- "parseurl": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
- "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=",
- "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-browserify": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
- "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=",
- "dev": true
- },
- "path-dirname": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
- "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
- "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=",
- "dev": true
- },
- "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-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
- "dev": true
- },
- "path-type": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
- "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
- "dev": true,
- "requires": {
- "pify": "3.0.0"
- }
- },
- "pbkdf2": {
- "version": "3.0.16",
- "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz",
- "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==",
- "dev": true,
- "requires": {
- "create-hash": "1.2.0",
- "create-hmac": "1.1.7",
- "ripemd160": "2.0.2",
- "safe-buffer": "5.1.2",
- "sha.js": "2.4.11"
- }
- },
- "performance-now": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
- "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
- "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"
- }
- },
- "pkg-dir": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
- "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
- "dev": true,
- "requires": {
- "find-up": "2.1.0"
- }
- },
- "portfinder": {
- "version": "1.0.13",
- "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz",
- "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=",
- "dev": true,
- "requires": {
- "async": "1.5.2",
- "debug": "2.6.9",
- "mkdirp": "0.5.1"
- }
- },
- "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
- },
- "postcss": {
- "version": "6.0.22",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz",
- "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==",
- "dev": true,
- "requires": {
- "chalk": "2.4.1",
- "source-map": "0.6.1",
- "supports-color": "5.4.0"
- },
- "dependencies": {
- "chalk": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
- "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "3.2.1",
- "escape-string-regexp": "1.0.5",
- "supports-color": "5.4.0"
- }
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- }
- }
- },
- "postcss-import": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-11.1.0.tgz",
- "integrity": "sha512-5l327iI75POonjxkXgdRCUS+AlzAdBx4pOvMEhTKTCjb1p8IEeVR9yx3cPbmN7LIWJLbfnIXxAhoB4jpD0c/Cw==",
- "dev": true,
- "requires": {
- "postcss": "6.0.22",
- "postcss-value-parser": "3.3.0",
- "read-cache": "1.0.0",
- "resolve": "1.7.1"
- }
- },
- "postcss-load-config": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz",
- "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=",
- "dev": true,
- "requires": {
- "cosmiconfig": "2.2.2",
- "object-assign": "4.1.1",
- "postcss-load-options": "1.2.0",
- "postcss-load-plugins": "2.3.0"
- }
- },
- "postcss-load-options": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz",
- "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=",
- "dev": true,
- "requires": {
- "cosmiconfig": "2.2.2",
- "object-assign": "4.1.1"
- }
- },
- "postcss-load-plugins": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz",
- "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=",
- "dev": true,
- "requires": {
- "cosmiconfig": "2.2.2",
- "object-assign": "4.1.1"
- }
- },
- "postcss-loader": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.5.tgz",
- "integrity": "sha512-pV7kB5neJ0/1tZ8L1uGOBNTVBCSCXQoIsZMsrwvO8V2rKGa2tBl/f80GGVxow2jJnRJ2w1ocx693EKhZAb9Isg==",
- "dev": true,
- "requires": {
- "loader-utils": "1.1.0",
- "postcss": "6.0.22",
- "postcss-load-config": "1.2.0",
- "schema-utils": "0.4.5"
- }
- },
- "postcss-url": {
- "version": "7.3.2",
- "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-7.3.2.tgz",
- "integrity": "sha512-QMV5mA+pCYZQcUEPQkmor9vcPQ2MT+Ipuu8qdi1gVxbNiIiErEGft+eny1ak19qALoBkccS5AHaCaCDzh7b9MA==",
- "dev": true,
- "requires": {
- "mime": "1.6.0",
- "minimatch": "3.0.4",
- "mkdirp": "0.5.1",
- "postcss": "6.0.22",
- "xxhashjs": "0.2.2"
- }
- },
- "postcss-value-parser": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz",
- "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=",
- "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
- },
- "preserve": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
- "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
- "dev": true
- },
- "pretty-error": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz",
- "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=",
- "dev": true,
- "requires": {
- "renderkid": "2.0.1",
- "utila": "0.4.0"
- }
- },
- "process": {
- "version": "0.11.10",
- "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
- "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
- "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
- },
- "promise": {
- "version": "7.3.1",
- "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
- "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
- "dev": true,
- "optional": true,
- "requires": {
- "asap": "2.0.6"
- }
- },
- "promise-inflight": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
- "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
- "dev": true
- },
- "protractor": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.3.2.tgz",
- "integrity": "sha512-pw4uwwiy5lHZjIguxNpkEwJJa7hVz+bJsvaTI+IbXlfn2qXwzbF8eghW/RmrZwE2sGx82I8etb8lVjQ+JrjejA==",
- "dev": true,
- "requires": {
- "@types/node": "6.0.113",
- "@types/q": "0.0.32",
- "@types/selenium-webdriver": "2.53.43",
- "blocking-proxy": "1.0.1",
- "chalk": "1.1.3",
- "glob": "7.1.2",
- "jasmine": "2.8.0",
- "jasminewd2": "2.2.0",
- "optimist": "0.6.1",
- "q": "1.4.1",
- "saucelabs": "1.5.0",
- "selenium-webdriver": "3.6.0",
- "source-map-support": "0.4.18",
- "webdriver-js-extender": "1.0.0",
- "webdriver-manager": "12.0.6"
- },
- "dependencies": {
- "@types/node": {
- "version": "6.0.113",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.113.tgz",
- "integrity": "sha512-f9XXUWFqryzjkZA1EqFvJHSFyqyasV17fq8zCDIzbRV4ctL7RrJGKvG+lcex86Rjbzd1GrER9h9VmF5sSjV0BQ==",
- "dev": true
- },
- "adm-zip": {
- "version": "0.4.11",
- "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz",
- "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==",
- "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
- },
- "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"
- }
- },
- "del": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
- "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
- "dev": true,
- "requires": {
- "globby": "5.0.0",
- "is-path-cwd": "1.0.0",
- "is-path-in-cwd": "1.0.1",
- "object-assign": "4.1.1",
- "pify": "2.3.0",
- "pinkie-promise": "2.0.1",
- "rimraf": "2.6.2"
- }
- },
- "globby": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
- "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
- "dev": true,
- "requires": {
- "array-union": "1.0.2",
- "arrify": "1.0.1",
- "glob": "7.1.2",
- "object-assign": "4.1.1",
- "pify": "2.3.0",
- "pinkie-promise": "2.0.1"
- }
- },
- "minimist": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
- "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
- "dev": true
- },
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- },
- "source-map-support": {
- "version": "0.4.18",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
- "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
- "dev": true,
- "requires": {
- "source-map": "0.5.7"
- }
- },
- "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
- },
- "webdriver-manager": {
- "version": "12.0.6",
- "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.0.6.tgz",
- "integrity": "sha1-PfGkgZdwELTL+MnYXHpXeCjA5ws=",
- "dev": true,
- "requires": {
- "adm-zip": "0.4.11",
- "chalk": "1.1.3",
- "del": "2.2.2",
- "glob": "7.1.2",
- "ini": "1.3.5",
- "minimist": "1.2.0",
- "q": "1.4.1",
- "request": "2.87.0",
- "rimraf": "2.6.2",
- "semver": "5.5.0",
- "xml2js": "0.4.19"
- }
- }
- }
- },
- "proxy-addr": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz",
- "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==",
- "dev": true,
- "requires": {
- "forwarded": "0.1.2",
- "ipaddr.js": "1.6.0"
- }
- },
- "prr": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
- "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
- "dev": true
- },
- "pseudomap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
- "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
- "dev": true
- },
- "public-encrypt": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz",
- "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==",
- "dev": true,
- "requires": {
- "bn.js": "4.11.8",
- "browserify-rsa": "4.0.1",
- "create-hash": "1.2.0",
- "parse-asn1": "5.1.1",
- "randombytes": "2.0.6"
- }
- },
- "pump": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
- "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
- "dev": true,
- "requires": {
- "end-of-stream": "1.4.1",
- "once": "1.4.0"
- }
- },
- "pumpify": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
- "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
- "dev": true,
- "requires": {
- "duplexify": "3.6.0",
- "inherits": "2.0.3",
- "pump": "2.0.1"
- }
- },
- "punycode": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
- "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
- "dev": true
- },
- "q": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
- "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
- "dev": true
- },
- "qjobs": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz",
- "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==",
- "dev": true
- },
- "qs": {
- "version": "6.5.2",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
- "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
- "dev": true
- },
- "querystring": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
- "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
- "dev": true
- },
- "querystring-es3": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
- "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
- "dev": true
- },
- "querystringify": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz",
- "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==",
- "dev": true
- },
- "randomatic": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz",
- "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==",
- "dev": true,
- "requires": {
- "is-number": "4.0.0",
- "kind-of": "6.0.2",
- "math-random": "1.0.1"
- },
- "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
- }
- }
- },
- "randombytes": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz",
- "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==",
- "dev": true,
- "requires": {
- "safe-buffer": "5.1.2"
- }
- },
- "randomfill": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
- "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
- "dev": true,
- "requires": {
- "randombytes": "2.0.6",
- "safe-buffer": "5.1.2"
- }
- },
- "range-parser": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
- "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
- "dev": true
- },
- "raw-body": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
- "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=",
- "dev": true,
- "requires": {
- "bytes": "3.0.0",
- "http-errors": "1.6.2",
- "iconv-lite": "0.4.19",
- "unpipe": "1.0.0"
- },
- "dependencies": {
- "depd": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
- "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=",
- "dev": true
- },
- "http-errors": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
- "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
- "dev": true,
- "requires": {
- "depd": "1.1.1",
- "inherits": "2.0.3",
- "setprototypeof": "1.0.3",
- "statuses": "1.4.0"
- }
- },
- "setprototypeof": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
- "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=",
- "dev": true
- }
- }
- },
- "raw-loader": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz",
- "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=",
- "dev": true
- },
- "read-cache": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
- "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=",
- "dev": true,
- "requires": {
- "pify": "2.3.0"
- },
- "dependencies": {
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "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"
- },
- "dependencies": {
- "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"
- }
- },
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- }
- }
- },
- "read-pkg-up": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
- "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
- "dev": true,
- "requires": {
- "find-up": "1.1.2",
- "read-pkg": "1.1.0"
- },
- "dependencies": {
- "find-up": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
- "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
- "dev": true,
- "requires": {
- "path-exists": "2.1.0",
- "pinkie-promise": "2.0.1"
- }
- },
- "path-exists": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
- "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
- "dev": true,
- "requires": {
- "pinkie-promise": "2.0.1"
- }
- }
- }
- },
- "readable-stream": {
- "version": "2.3.6",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
- "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
- "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.2",
- "string_decoder": "1.1.1",
- "util-deprecate": "1.0.2"
- }
- },
- "readdirp": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
- "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
- "dev": true,
- "requires": {
- "graceful-fs": "4.1.11",
- "minimatch": "3.0.4",
- "readable-stream": "2.3.6",
- "set-immediate-shim": "1.0.1"
- }
- },
- "redent": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
- "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
- "dev": true,
- "requires": {
- "indent-string": "2.1.0",
- "strip-indent": "1.0.1"
- }
- },
- "reflect-metadata": {
- "version": "0.1.12",
- "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz",
- "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==",
- "dev": true
- },
- "regenerate": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
- "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
- "dev": true
- },
- "regenerator-runtime": {
- "version": "0.11.1",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
- "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
- "dev": true
- },
- "regex-cache": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
- "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
- "dev": true,
- "requires": {
- "is-equal-shallow": "0.1.3"
- }
- },
- "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"
- }
- },
- "regexpu-core": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
- "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
- "dev": true,
- "requires": {
- "regenerate": "1.4.0",
- "regjsgen": "0.2.0",
- "regjsparser": "0.1.5"
- }
- },
- "regjsgen": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
- "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
- "dev": true
- },
- "regjsparser": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
- "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
- "dev": true,
- "requires": {
- "jsesc": "0.5.0"
- },
- "dependencies": {
- "jsesc": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
- "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
- "dev": true
- }
- }
- },
- "relateurl": {
- "version": "0.2.7",
- "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
- "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
- "dev": true
- },
- "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
- },
- "renderkid": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz",
- "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=",
- "dev": true,
- "requires": {
- "css-select": "1.2.0",
- "dom-converter": "0.1.4",
- "htmlparser2": "3.3.0",
- "strip-ansi": "3.0.1",
- "utila": "0.3.3"
- },
- "dependencies": {
- "utila": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz",
- "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=",
- "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
- },
- "repeating": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
- "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
- "dev": true,
- "requires": {
- "is-finite": "1.0.2"
- }
- },
- "request": {
- "version": "2.87.0",
- "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
- "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
- "dev": true,
- "requires": {
- "aws-sign2": "0.7.0",
- "aws4": "1.7.0",
- "caseless": "0.12.0",
- "combined-stream": "1.0.6",
- "extend": "3.0.1",
- "forever-agent": "0.6.1",
- "form-data": "2.3.2",
- "har-validator": "5.0.3",
- "http-signature": "1.2.0",
- "is-typedarray": "1.0.0",
- "isstream": "0.1.2",
- "json-stringify-safe": "5.0.1",
- "mime-types": "2.1.18",
- "oauth-sign": "0.8.2",
- "performance-now": "2.1.0",
- "qs": "6.5.2",
- "safe-buffer": "5.1.2",
- "tough-cookie": "2.3.4",
- "tunnel-agent": "0.6.0",
- "uuid": "3.2.1"
- }
- },
- "require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
- "dev": true
- },
- "require-from-string": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz",
- "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=",
- "dev": true
- },
- "require-main-filename": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
- "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
- "dev": true
- },
- "requires-port": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
- "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
- "dev": true
- },
- "resolve": {
- "version": "1.7.1",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
- "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
- "dev": true,
- "requires": {
- "path-parse": "1.0.5"
- }
- },
- "resolve-cwd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
- "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
- "dev": true,
- "requires": {
- "resolve-from": "3.0.0"
- }
- },
- "resolve-from": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
- "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
- "dev": true
- },
- "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
- },
- "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
- },
- "retry": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz",
- "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=",
- "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"
- }
- },
- "ripemd160": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
- "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
- "dev": true,
- "requires": {
- "hash-base": "3.0.4",
- "inherits": "2.0.3"
- }
- },
- "run-queue": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
- "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
- "dev": true,
- "requires": {
- "aproba": "1.2.0"
- }
- },
- "rxjs": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.1.tgz",
- "integrity": "sha512-OwMxHxmnmHTUpgO+V7dZChf3Tixf4ih95cmXjzzadULziVl/FKhHScGLj4goEw9weePVOH2Q0+GcCBUhKCZc/g==",
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "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"
- }
- },
- "safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true
- },
- "sass-graph": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
- "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
- "dev": true,
- "optional": true,
- "requires": {
- "glob": "7.1.2",
- "lodash": "4.17.10",
- "scss-tokenizer": "0.2.3",
- "yargs": "7.1.0"
- },
- "dependencies": {
- "camelcase": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
- "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
- "dev": true,
- "optional": true
- },
- "cliui": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
- "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
- "dev": true,
- "optional": true,
- "requires": {
- "string-width": "1.0.2",
- "strip-ansi": "3.0.1",
- "wrap-ansi": "2.1.0"
- }
- },
- "y18n": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
- "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
- "dev": true,
- "optional": true
- },
- "yargs": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
- "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
- "dev": true,
- "optional": true,
- "requires": {
- "camelcase": "3.0.0",
- "cliui": "3.2.0",
- "decamelize": "1.2.0",
- "get-caller-file": "1.0.2",
- "os-locale": "1.4.0",
- "read-pkg-up": "1.0.1",
- "require-directory": "2.1.1",
- "require-main-filename": "1.0.1",
- "set-blocking": "2.0.0",
- "string-width": "1.0.2",
- "which-module": "1.0.0",
- "y18n": "3.2.1",
- "yargs-parser": "5.0.0"
- }
- }
- }
- },
- "sass-loader": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.0.3.tgz",
- "integrity": "sha512-iaSFtQcGo4SSgDw5Aes5p4VTrA5jCGSA7sGmhPIcOloBlgI1VktM2MUrk2IHHjbNagckXlPz+HWq1vAAPrcYxA==",
- "dev": true,
- "requires": {
- "clone-deep": "2.0.2",
- "loader-utils": "1.1.0",
- "lodash.tail": "4.1.1",
- "neo-async": "2.5.1",
- "pify": "3.0.0"
- }
- },
- "saucelabs": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz",
- "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==",
- "dev": true,
- "requires": {
- "https-proxy-agent": "2.2.1"
- }
- },
- "sax": {
- "version": "0.5.8",
- "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz",
- "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=",
- "dev": true
- },
- "schema-utils": {
- "version": "0.4.5",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz",
- "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==",
- "dev": true,
- "requires": {
- "ajv": "6.4.0",
- "ajv-keywords": "3.2.0"
- }
- },
- "scss-tokenizer": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
- "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
- "dev": true,
- "optional": true,
- "requires": {
- "js-base64": "2.4.5",
- "source-map": "0.4.4"
- },
- "dependencies": {
- "source-map": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
- "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
- "dev": true,
- "optional": true,
- "requires": {
- "amdefine": "1.0.1"
- }
- }
- }
- },
- "select-hose": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
- "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
- "dev": true
- },
- "selenium-webdriver": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz",
- "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==",
- "dev": true,
- "requires": {
- "jszip": "3.1.5",
- "rimraf": "2.6.2",
- "tmp": "0.0.30",
- "xml2js": "0.4.19"
- },
- "dependencies": {
- "tmp": {
- "version": "0.0.30",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz",
- "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=",
- "dev": true,
- "requires": {
- "os-tmpdir": "1.0.2"
- }
- }
- }
- },
- "selfsigned": {
- "version": "1.10.3",
- "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.3.tgz",
- "integrity": "sha512-vmZenZ+8Al3NLHkWnhBQ0x6BkML1eCP2xEi3JE+f3D9wW9fipD9NNJHYtE9XJM4TsPaHGZJIamrSI6MTg1dU2Q==",
- "dev": true,
- "requires": {
- "node-forge": "0.7.5"
- }
- },
- "semver": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
- "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
- "dev": true
- },
- "semver-dsl": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz",
- "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=",
- "dev": true,
- "requires": {
- "semver": "5.5.0"
- }
- },
- "semver-intersect": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.3.1.tgz",
- "integrity": "sha1-j6hKnhAovSOeRTDRo+GB5pjYhLo=",
- "dev": true,
- "requires": {
- "semver": "5.5.0"
- }
- },
- "send": {
- "version": "0.16.2",
- "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
- "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
- "dev": true,
- "requires": {
- "debug": "2.6.9",
- "depd": "1.1.2",
- "destroy": "1.0.4",
- "encodeurl": "1.0.2",
- "escape-html": "1.0.3",
- "etag": "1.8.1",
- "fresh": "0.5.2",
- "http-errors": "1.6.3",
- "mime": "1.4.1",
- "ms": "2.0.0",
- "on-finished": "2.3.0",
- "range-parser": "1.2.0",
- "statuses": "1.4.0"
- },
- "dependencies": {
- "mime": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
- "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
- "dev": true
- }
- }
- },
- "serialize-javascript": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz",
- "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==",
- "dev": true
- },
- "serve-index": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
- "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
- "dev": true,
- "requires": {
- "accepts": "1.3.5",
- "batch": "0.6.1",
- "debug": "2.6.9",
- "escape-html": "1.0.3",
- "http-errors": "1.6.3",
- "mime-types": "2.1.18",
- "parseurl": "1.3.2"
- }
- },
- "serve-static": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
- "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
- "dev": true,
- "requires": {
- "encodeurl": "1.0.2",
- "escape-html": "1.0.3",
- "parseurl": "1.3.2",
- "send": "0.16.2"
- }
- },
- "set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
- "dev": true
- },
- "set-immediate-shim": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
- "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
- "dev": true
- },
- "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"
- }
- }
- }
- },
- "setimmediate": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
- "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
- "dev": true
- },
- "setprototypeof": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
- "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
- "dev": true
- },
- "sha.js": {
- "version": "2.4.11",
- "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
- "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
- "dev": true,
- "requires": {
- "inherits": "2.0.3",
- "safe-buffer": "5.1.2"
- }
- },
- "shallow-clone": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz",
- "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==",
- "dev": true,
- "requires": {
- "is-extendable": "0.1.1",
- "kind-of": "5.1.0",
- "mixin-object": "2.0.1"
- },
- "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
- }
- }
- },
- "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
- },
- "signal-exit": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
- "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
- "dev": true
- },
- "silent-error": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/silent-error/-/silent-error-1.1.0.tgz",
- "integrity": "sha1-IglwbxyFCp8dENDYQJGLRvJuG8k=",
- "dev": true,
- "requires": {
- "debug": "2.6.9"
- }
- },
- "slash": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
- "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
- "dev": true
- },
- "slide": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
- "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=",
- "dev": true
- },
- "snapdragon": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
- "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
- "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.2",
- "use": "3.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"
- }
- },
- "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"
- }
- }
- }
- },
- "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"
- }
- },
- "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-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"
- }
- }
- }
- },
- "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"
- }
- }
- }
- },
- "sntp": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
- "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
- "dev": true,
- "requires": {
- "hoek": "2.16.3"
- }
- },
- "socket.io": {
- "version": "1.7.3",
- "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.7.3.tgz",
- "integrity": "sha1-uK+cq6AJSeVo42nxMn6pvp6iRhs=",
- "dev": true,
- "requires": {
- "debug": "2.3.3",
- "engine.io": "1.8.3",
- "has-binary": "0.1.7",
- "object-assign": "4.1.0",
- "socket.io-adapter": "0.5.0",
- "socket.io-client": "1.7.3",
- "socket.io-parser": "2.3.1"
- },
- "dependencies": {
- "debug": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
- "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
- "dev": true,
- "requires": {
- "ms": "0.7.2"
- }
- },
- "ms": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
- "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
- "dev": true
- },
- "object-assign": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
- "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=",
- "dev": true
- }
- }
- },
- "socket.io-adapter": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz",
- "integrity": "sha1-y21LuL7IHhB4uZZ3+c7QBGBmu4s=",
- "dev": true,
- "requires": {
- "debug": "2.3.3",
- "socket.io-parser": "2.3.1"
- },
- "dependencies": {
- "debug": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
- "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
- "dev": true,
- "requires": {
- "ms": "0.7.2"
- }
- },
- "ms": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
- "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
- "dev": true
- }
- }
- },
- "socket.io-client": {
- "version": "1.7.3",
- "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.3.tgz",
- "integrity": "sha1-sw6GqhDV7zVGYBwJzeR2Xjgdo3c=",
- "dev": true,
- "requires": {
- "backo2": "1.0.2",
- "component-bind": "1.0.0",
- "component-emitter": "1.2.1",
- "debug": "2.3.3",
- "engine.io-client": "1.8.3",
- "has-binary": "0.1.7",
- "indexof": "0.0.1",
- "object-component": "0.0.3",
- "parseuri": "0.0.5",
- "socket.io-parser": "2.3.1",
- "to-array": "0.1.4"
- },
- "dependencies": {
- "debug": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
- "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
- "dev": true,
- "requires": {
- "ms": "0.7.2"
- }
- },
- "ms": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
- "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
- "dev": true
- }
- }
- },
- "socket.io-parser": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz",
- "integrity": "sha1-3VMgJRA85Clpcya+/WQAX8/ltKA=",
- "dev": true,
- "requires": {
- "component-emitter": "1.1.2",
- "debug": "2.2.0",
- "isarray": "0.0.1",
- "json3": "3.3.2"
- },
- "dependencies": {
- "component-emitter": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz",
- "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=",
- "dev": true
- },
- "debug": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
- "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
- "dev": true,
- "requires": {
- "ms": "0.7.1"
- }
- },
- "isarray": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
- "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
- "dev": true
- },
- "ms": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
- "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
- "dev": true
- }
- }
- },
- "sockjs": {
- "version": "0.3.19",
- "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz",
- "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==",
- "dev": true,
- "requires": {
- "faye-websocket": "0.10.0",
- "uuid": "3.2.1"
- }
- },
- "sockjs-client": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz",
- "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=",
- "dev": true,
- "requires": {
- "debug": "2.6.9",
- "eventsource": "0.1.6",
- "faye-websocket": "0.11.1",
- "inherits": "2.0.3",
- "json3": "3.3.2",
- "url-parse": "1.4.1"
- },
- "dependencies": {
- "faye-websocket": {
- "version": "0.11.1",
- "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz",
- "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=",
- "dev": true,
- "requires": {
- "websocket-driver": "0.7.0"
- }
- }
- }
- },
- "source-list-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz",
- "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==",
- "dev": true
- },
- "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.2",
- "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
- "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
- "dev": true,
- "requires": {
- "atob": "2.1.1",
- "decode-uri-component": "0.2.0",
- "resolve-url": "0.2.1",
- "source-map-url": "0.4.0",
- "urix": "0.1.0"
- }
- },
- "source-map-support": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz",
- "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==",
- "dev": true,
- "requires": {
- "buffer-from": "1.1.0",
- "source-map": "0.6.1"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- }
- }
- },
- "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
- },
- "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
- },
- "spdy": {
- "version": "3.4.7",
- "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz",
- "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=",
- "dev": true,
- "requires": {
- "debug": "2.6.9",
- "handle-thing": "1.2.5",
- "http-deceiver": "1.2.7",
- "safe-buffer": "5.1.2",
- "select-hose": "2.0.0",
- "spdy-transport": "2.1.0"
- }
- },
- "spdy-transport": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.0.tgz",
- "integrity": "sha512-bpUeGpZcmZ692rrTiqf9/2EUakI6/kXX1Rpe0ib/DyOzbiexVfXkw6GnvI9hVGvIwVaUhkaBojjCZwLNRGQg1g==",
- "dev": true,
- "requires": {
- "debug": "2.6.9",
- "detect-node": "2.0.3",
- "hpack.js": "2.1.6",
- "obuf": "1.1.2",
- "readable-stream": "2.3.6",
- "safe-buffer": "5.1.2",
- "wbuf": "1.7.3"
- }
- },
- "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
- },
- "sshpk": {
- "version": "1.14.2",
- "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
- "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
- "dev": true,
- "requires": {
- "asn1": "0.2.3",
- "assert-plus": "1.0.0",
- "bcrypt-pbkdf": "1.0.1",
- "dashdash": "1.14.1",
- "ecc-jsbn": "0.1.1",
- "getpass": "0.1.7",
- "jsbn": "0.1.1",
- "safer-buffer": "2.1.2",
- "tweetnacl": "0.14.5"
- }
- },
- "ssri": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz",
- "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==",
- "dev": true,
- "requires": {
- "safe-buffer": "5.1.2"
- }
- },
- "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"
- }
- }
- }
- },
- "stats-webpack-plugin": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/stats-webpack-plugin/-/stats-webpack-plugin-0.6.2.tgz",
- "integrity": "sha1-LFlJtTHgf4eojm6k3PrFOqjHWis=",
- "dev": true,
- "requires": {
- "lodash": "4.17.10"
- }
- },
- "statuses": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
- "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
- "dev": true
- },
- "stdout-stream": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz",
- "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=",
- "dev": true,
- "optional": true,
- "requires": {
- "readable-stream": "2.3.6"
- }
- },
- "stream-browserify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
- "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
- "dev": true,
- "requires": {
- "inherits": "2.0.3",
- "readable-stream": "2.3.6"
- }
- },
- "stream-each": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz",
- "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==",
- "dev": true,
- "requires": {
- "end-of-stream": "1.4.1",
- "stream-shift": "1.0.0"
- }
- },
- "stream-http": {
- "version": "2.8.3",
- "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
- "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
- "dev": true,
- "requires": {
- "builtin-status-codes": "3.0.0",
- "inherits": "2.0.3",
- "readable-stream": "2.3.6",
- "to-arraybuffer": "1.0.1",
- "xtend": "4.0.1"
- }
- },
- "stream-shift": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
- "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
- "dev": true
- },
- "string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
- "dev": true,
- "requires": {
- "code-point-at": "1.1.0",
- "is-fullwidth-code-point": "1.0.0",
- "strip-ansi": "3.0.1"
- }
- },
- "string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "dev": true,
- "requires": {
- "safe-buffer": "5.1.2"
- }
- },
- "stringstream": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz",
- "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==",
- "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-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"
- }
- },
- "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-indent": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
- "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
- "dev": true,
- "requires": {
- "get-stdin": "4.0.1"
- }
- },
- "style-loader": {
- "version": "0.21.0",
- "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.21.0.tgz",
- "integrity": "sha512-T+UNsAcl3Yg+BsPKs1vd22Fr8sVT+CJMtzqc6LEw9bbJZb43lm9GoeIfUcDEefBSWC0BhYbcdupV1GtI4DGzxg==",
- "dev": true,
- "requires": {
- "loader-utils": "1.1.0",
- "schema-utils": "0.4.5"
- }
- },
- "stylus": {
- "version": "0.54.5",
- "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz",
- "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=",
- "dev": true,
- "requires": {
- "css-parse": "1.7.0",
- "debug": "2.6.9",
- "glob": "7.0.6",
- "mkdirp": "0.5.1",
- "sax": "0.5.8",
- "source-map": "0.1.43"
- },
- "dependencies": {
- "glob": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
- "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
- "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"
- }
- },
- "source-map": {
- "version": "0.1.43",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
- "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
- "dev": true,
- "requires": {
- "amdefine": "1.0.1"
- }
- }
- }
- },
- "stylus-loader": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz",
- "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==",
- "dev": true,
- "requires": {
- "loader-utils": "1.1.0",
- "lodash.clonedeep": "4.5.0",
- "when": "3.6.4"
- }
- },
- "supports-color": {
- "version": "5.4.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
- "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
- "dev": true,
- "requires": {
- "has-flag": "3.0.0"
- }
- },
- "symbol-observable": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
- "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
- "dev": true
- },
- "tapable": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz",
- "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==",
- "dev": true
- },
- "tar": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
- "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
- "dev": true,
- "optional": true,
- "requires": {
- "block-stream": "0.0.9",
- "fstream": "1.0.11",
- "inherits": "2.0.3"
- }
- },
- "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.6",
- "xtend": "4.0.1"
- }
- },
- "thunky": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz",
- "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=",
- "dev": true
- },
- "timers-browserify": {
- "version": "2.0.10",
- "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz",
- "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==",
- "dev": true,
- "requires": {
- "setimmediate": "1.0.5"
- }
- },
- "tmp": {
- "version": "0.0.31",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz",
- "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=",
- "dev": true,
- "requires": {
- "os-tmpdir": "1.0.2"
- }
- },
- "to-array": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
- "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=",
- "dev": true
- },
- "to-arraybuffer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
- "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
- "dev": true
- },
- "to-fast-properties": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
- "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
- "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"
- }
- },
- "toposort": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz",
- "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=",
- "dev": true
- },
- "tough-cookie": {
- "version": "2.3.4",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
- "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
- "dev": true,
- "requires": {
- "punycode": "1.4.1"
- },
- "dependencies": {
- "punycode": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
- "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
- "dev": true
- }
- }
- },
- "tree-kill": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz",
- "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==",
- "dev": true
- },
- "trim-newlines": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
- "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
- "dev": true
- },
- "trim-right": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
- "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
- "dev": true
- },
- "true-case-path": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz",
- "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=",
- "dev": true,
- "optional": true,
- "requires": {
- "glob": "6.0.4"
- },
- "dependencies": {
- "glob": {
- "version": "6.0.4",
- "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
- "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
- "dev": true,
- "optional": true,
- "requires": {
- "inflight": "1.0.6",
- "inherits": "2.0.3",
- "minimatch": "3.0.4",
- "once": "1.4.0",
- "path-is-absolute": "1.0.1"
- }
- }
- }
- },
- "ts-node": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-5.0.1.tgz",
- "integrity": "sha512-XK7QmDcNHVmZkVtkiwNDWiERRHPyU8nBqZB1+iv2UhOG0q3RQ9HsZ2CMqISlFbxjrYFGfG2mX7bW4dAyxBVzUw==",
- "dev": true,
- "requires": {
- "arrify": "1.0.1",
- "chalk": "2.4.1",
- "diff": "3.5.0",
- "make-error": "1.3.4",
- "minimist": "1.2.0",
- "mkdirp": "0.5.1",
- "source-map-support": "0.5.6",
- "yn": "2.0.0"
- },
- "dependencies": {
- "chalk": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
- "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "3.2.1",
- "escape-string-regexp": "1.0.5",
- "supports-color": "5.4.0"
- }
- },
- "minimist": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
- "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
- "dev": true
- }
- }
- },
- "tsickle": {
- "version": "0.29.0",
- "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.29.0.tgz",
- "integrity": "sha512-JpID0Lv8/irRtPmqJJxb5fCwfZhjZeKmav9Zna7UjqVuJoSbI49Wue/c2PPybX1SbRrjl7bbI/JsCl0dSUJygA==",
- "dev": true,
- "requires": {
- "minimist": "1.2.0",
- "mkdirp": "0.5.1",
- "source-map": "0.6.1",
- "source-map-support": "0.5.6"
- },
- "dependencies": {
- "minimist": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
- "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
- "dev": true
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- }
- }
- },
- "tslib": {
- "version": "1.9.2",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.2.tgz",
- "integrity": "sha512-AVP5Xol3WivEr7hnssHDsaM+lVrVXWUvd1cfXTRkTj80b//6g2wIFEH6hZG0muGZRnHGrfttpdzRk3YlBkWjKw=="
- },
- "tslint": {
- "version": "5.9.1",
- "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.9.1.tgz",
- "integrity": "sha1-ElX4ej/1frCw4fDmEKi0dIBGya4=",
- "dev": true,
- "requires": {
- "babel-code-frame": "6.26.0",
- "builtin-modules": "1.1.1",
- "chalk": "2.4.1",
- "commander": "2.15.1",
- "diff": "3.5.0",
- "glob": "7.1.2",
- "js-yaml": "3.12.0",
- "minimatch": "3.0.4",
- "resolve": "1.7.1",
- "semver": "5.5.0",
- "tslib": "1.9.2",
- "tsutils": "2.29.0"
- },
- "dependencies": {
- "chalk": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
- "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "3.2.1",
- "escape-string-regexp": "1.0.5",
- "supports-color": "5.4.0"
- }
- }
- }
- },
- "tsutils": {
- "version": "2.29.0",
- "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
- "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
- "dev": true,
- "requires": {
- "tslib": "1.9.2"
- }
- },
- "tty-browserify": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
- "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
- "dev": true
- },
- "tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
- "dev": true,
- "requires": {
- "safe-buffer": "5.1.2"
- }
- },
- "tweetnacl": {
- "version": "0.14.5",
- "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
- "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
- "dev": true,
- "optional": true
- },
- "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-is": {
- "version": "1.6.16",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
- "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
- "dev": true,
- "requires": {
- "media-typer": "0.3.0",
- "mime-types": "2.1.18"
- }
- },
- "typedarray": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
- "dev": true
- },
- "typescript": {
- "version": "2.7.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.7.2.tgz",
- "integrity": "sha512-p5TCYZDAO0m4G344hD+wx/LATebLWZNkkh2asWUFqSsD2OrDNhbAHuSjobrmsUmdzjJjEeZVU9g1h3O6vpstnw==",
- "dev": true
- },
- "uglify-js": {
- "version": "3.3.28",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.28.tgz",
- "integrity": "sha512-68Rc/aA6cswiaQ5SrE979UJcXX+ADA1z33/ZsPd+fbAiVdjZ16OXdbtGO+rJUUBgK6qdf3SOPhQf3K/ybF5Miw==",
- "dev": true,
- "requires": {
- "commander": "2.15.1",
- "source-map": "0.6.1"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- }
- }
- },
- "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
- },
- "uglifyjs-webpack-plugin": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.5.tgz",
- "integrity": "sha512-hIQJ1yxAPhEA2yW/i7Fr+SXZVMp+VEI3d42RTHBgQd2yhp/1UdBcR3QEWPV5ahBxlqQDMEMTuTEvDHSFINfwSw==",
- "dev": true,
- "requires": {
- "cacache": "10.0.4",
- "find-cache-dir": "1.0.0",
- "schema-utils": "0.4.5",
- "serialize-javascript": "1.5.0",
- "source-map": "0.6.1",
- "uglify-es": "3.3.9",
- "webpack-sources": "1.1.0",
- "worker-farm": "1.6.0"
- },
- "dependencies": {
- "commander": {
- "version": "2.13.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
- "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==",
- "dev": true
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- },
- "uglify-es": {
- "version": "3.3.9",
- "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",
- "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==",
- "dev": true,
- "requires": {
- "commander": "2.13.0",
- "source-map": "0.6.1"
- }
- }
- }
- },
- "ultron": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
- "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=",
- "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-filename": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz",
- "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=",
- "dev": true,
- "requires": {
- "unique-slug": "2.0.0"
- }
- },
- "unique-slug": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz",
- "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=",
- "dev": true,
- "requires": {
- "imurmurhash": "0.1.4"
- }
- },
- "unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
- "dev": true
- },
- "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
- }
- }
- },
- "upath": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz",
- "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==",
- "dev": true
- },
- "upper-case": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
- "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=",
- "dev": true
- },
- "uri-js": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-3.0.2.tgz",
- "integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=",
- "dev": true,
- "requires": {
- "punycode": "2.1.1"
- }
- },
- "urix": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
- "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
- "dev": true
- },
- "url": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
- "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
- "dev": true,
- "requires": {
- "punycode": "1.3.2",
- "querystring": "0.2.0"
- },
- "dependencies": {
- "punycode": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
- "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
- "dev": true
- }
- }
- },
- "url-join": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz",
- "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=",
- "dev": true
- },
- "url-loader": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.0.1.tgz",
- "integrity": "sha512-rAonpHy7231fmweBKUFe0bYnlGDty77E+fm53NZdij7j/YOpyGzc7ttqG1nAXl3aRs0k41o0PC3TvGXQiw2Zvw==",
- "dev": true,
- "requires": {
- "loader-utils": "1.1.0",
- "mime": "2.3.1",
- "schema-utils": "0.4.5"
- },
- "dependencies": {
- "mime": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz",
- "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==",
- "dev": true
- }
- }
- },
- "url-parse": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.1.tgz",
- "integrity": "sha512-x95Td74QcvICAA0+qERaVkRpTGKyBHHYdwL2LXZm5t/gBtCB9KQSO/0zQgSTYEV1p0WcvSg79TLNPSvd5IDJMQ==",
- "dev": true,
- "requires": {
- "querystringify": "2.0.0",
- "requires-port": "1.0.0"
- }
- },
- "use": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz",
- "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==",
- "dev": true,
- "requires": {
- "kind-of": "6.0.2"
- }
- },
- "useragent": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz",
- "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==",
- "dev": true,
- "requires": {
- "lru-cache": "4.1.3",
- "tmp": "0.0.31"
- }
- },
- "util": {
- "version": "0.10.4",
- "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
- "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
- "dev": true,
- "requires": {
- "inherits": "2.0.3"
- }
- },
- "util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
- "dev": true
- },
- "util.promisify": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
- "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
- "dev": true,
- "requires": {
- "define-properties": "1.1.2",
- "object.getownpropertydescriptors": "2.0.3"
- }
- },
- "utila": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
- "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
- "dev": true
- },
- "utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
- "dev": true
- },
- "uuid": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
- "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==",
- "dev": true
- },
- "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"
- }
- },
- "validate-npm-package-name": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
- "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=",
- "dev": true,
- "requires": {
- "builtins": "1.0.3"
- }
- },
- "vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
- "dev": true
- },
- "verror": {
- "version": "1.10.0",
- "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
- "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
- "dev": true,
- "requires": {
- "assert-plus": "1.0.0",
- "core-util-is": "1.0.2",
- "extsprintf": "1.3.0"
- }
- },
- "vm-browserify": {
- "version": "0.0.4",
- "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
- "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
- "dev": true,
- "requires": {
- "indexof": "0.0.1"
- }
- },
- "void-elements": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
- "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
- "dev": true
- },
- "watchpack": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
- "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==",
- "dev": true,
- "requires": {
- "chokidar": "2.0.3",
- "graceful-fs": "4.1.11",
- "neo-async": "2.5.1"
- }
- },
- "wbuf": {
- "version": "1.7.3",
- "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
- "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
- "dev": true,
- "requires": {
- "minimalistic-assert": "1.0.1"
- }
- },
- "webassemblyjs": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/webassemblyjs/-/webassemblyjs-1.4.3.tgz",
- "integrity": "sha512-4lOV1Lv6olz0PJkDGQEp82HempAn147e6BXijWDzz9g7/2nSebVP9GVg62Fz5ZAs55mxq13GA0XLyvY8XkyDjg==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.4.3",
- "@webassemblyjs/validation": "1.4.3",
- "@webassemblyjs/wasm-parser": "1.4.3",
- "@webassemblyjs/wast-parser": "1.4.3",
- "long": "3.2.0"
- }
- },
- "webdriver-js-extender": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-1.0.0.tgz",
- "integrity": "sha1-gcUzqeM9W/tZe05j4s2yW1R3dRU=",
- "dev": true,
- "requires": {
- "@types/selenium-webdriver": "2.53.43",
- "selenium-webdriver": "2.53.3"
- },
- "dependencies": {
- "sax": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz",
- "integrity": "sha1-VjsZx8HeiS4Jv8Ty/DDjwn8JUrk=",
- "dev": true
- },
- "selenium-webdriver": {
- "version": "2.53.3",
- "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz",
- "integrity": "sha1-0p/1qVff8aG0ncRXdW5OS/vc4IU=",
- "dev": true,
- "requires": {
- "adm-zip": "0.4.4",
- "rimraf": "2.6.2",
- "tmp": "0.0.24",
- "ws": "1.1.2",
- "xml2js": "0.4.4"
- }
- },
- "tmp": {
- "version": "0.0.24",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.24.tgz",
- "integrity": "sha1-1qXhmNFKmDXMby18PZ4wJCjIzxI=",
- "dev": true
- },
- "xml2js": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz",
- "integrity": "sha1-MREBAAMAiuGSQOuhdJe1fHKcVV0=",
- "dev": true,
- "requires": {
- "sax": "0.6.1",
- "xmlbuilder": "9.0.7"
- }
- }
- }
- },
- "webpack": {
- "version": "4.8.3",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.8.3.tgz",
- "integrity": "sha512-/hfAjBISycdK597lxONjKEFX7dSIU1PsYwC3XlXUXoykWBlv9QV5HnO+ql3HvrrgfBJ7WXdnjO9iGPR2aAc5sw==",
- "dev": true,
- "requires": {
- "@webassemblyjs/ast": "1.4.3",
- "@webassemblyjs/wasm-edit": "1.4.3",
- "@webassemblyjs/wasm-parser": "1.4.3",
- "acorn": "5.6.2",
- "acorn-dynamic-import": "3.0.0",
- "ajv": "6.4.0",
- "ajv-keywords": "3.2.0",
- "chrome-trace-event": "0.1.3",
- "enhanced-resolve": "4.0.0",
- "eslint-scope": "3.7.1",
- "loader-runner": "2.3.0",
- "loader-utils": "1.1.0",
- "memory-fs": "0.4.1",
- "micromatch": "3.1.10",
- "mkdirp": "0.5.1",
- "neo-async": "2.5.1",
- "node-libs-browser": "2.1.0",
- "schema-utils": "0.4.5",
- "tapable": "1.0.0",
- "uglifyjs-webpack-plugin": "1.2.5",
- "watchpack": "1.6.0",
- "webpack-sources": "1.1.0"
- }
- },
- "webpack-core": {
- "version": "0.6.9",
- "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz",
- "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=",
- "dev": true,
- "requires": {
- "source-list-map": "0.1.8",
- "source-map": "0.4.4"
- },
- "dependencies": {
- "source-list-map": {
- "version": "0.1.8",
- "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz",
- "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=",
- "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"
- }
- }
- }
- },
- "webpack-dev-middleware": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.1.3.tgz",
- "integrity": "sha512-I6Mmy/QjWU/kXwCSFGaiOoL5YEQIVmbb0o45xMoCyQAg/mClqZVTcsX327sPfekDyJWpCxb+04whNyLOIxpJdQ==",
- "dev": true,
- "requires": {
- "loud-rejection": "1.6.0",
- "memory-fs": "0.4.1",
- "mime": "2.3.1",
- "path-is-absolute": "1.0.1",
- "range-parser": "1.2.0",
- "url-join": "4.0.0",
- "webpack-log": "1.2.0"
- },
- "dependencies": {
- "mime": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz",
- "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==",
- "dev": true
- }
- }
- },
- "webpack-dev-server": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.4.tgz",
- "integrity": "sha512-itcIUDFkHuj1/QQxzUFOEXXmxOj5bku2ScLEsOFPapnq2JRTm58gPdtnBphBJOKL2+M3p6+xygL64bI+3eyzzw==",
- "dev": true,
- "requires": {
- "ansi-html": "0.0.7",
- "array-includes": "3.0.3",
- "bonjour": "3.5.0",
- "chokidar": "2.0.3",
- "compression": "1.7.2",
- "connect-history-api-fallback": "1.5.0",
- "debug": "3.1.0",
- "del": "3.0.0",
- "express": "4.16.3",
- "html-entities": "1.2.1",
- "http-proxy-middleware": "0.18.0",
- "import-local": "1.0.0",
- "internal-ip": "1.2.0",
- "ip": "1.1.5",
- "killable": "1.0.0",
- "loglevel": "1.6.1",
- "opn": "5.3.0",
- "portfinder": "1.0.13",
- "selfsigned": "1.10.3",
- "serve-index": "1.9.1",
- "sockjs": "0.3.19",
- "sockjs-client": "1.1.4",
- "spdy": "3.4.7",
- "strip-ansi": "3.0.1",
- "supports-color": "5.4.0",
- "webpack-dev-middleware": "3.1.3",
- "webpack-log": "1.2.0",
- "yargs": "11.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
- },
- "camelcase": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
- "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
- "dev": true
- },
- "cliui": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
- "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
- "dev": true,
- "requires": {
- "string-width": "2.1.1",
- "strip-ansi": "4.0.0",
- "wrap-ansi": "2.1.0"
- },
- "dependencies": {
- "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"
- }
- }
- }
- },
- "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"
- }
- },
- "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
- },
- "os-locale": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
- "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
- "dev": true,
- "requires": {
- "execa": "0.7.0",
- "lcid": "1.0.0",
- "mem": "1.1.0"
- }
- },
- "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"
- },
- "dependencies": {
- "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"
- }
- }
- }
- },
- "which-module": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
- "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
- "dev": true
- },
- "y18n": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
- "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
- "dev": true
- },
- "yargs": {
- "version": "11.0.0",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz",
- "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==",
- "dev": true,
- "requires": {
- "cliui": "4.1.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": "9.0.2"
- }
- },
- "yargs-parser": {
- "version": "9.0.2",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz",
- "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=",
- "dev": true,
- "requires": {
- "camelcase": "4.1.0"
- }
- }
- }
- },
- "webpack-log": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz",
- "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==",
- "dev": true,
- "requires": {
- "chalk": "2.2.2",
- "log-symbols": "2.2.0",
- "loglevelnext": "1.0.5",
- "uuid": "3.2.1"
- }
- },
- "webpack-merge": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.3.tgz",
- "integrity": "sha512-zxwAIGK7nKdu5CIZL0BjTQoq3elV0t0MfB7rUC1zj668geid52abs6hN/ACwZdK6LeMS8dC9B6WmtF978zH5mg==",
- "dev": true,
- "requires": {
- "lodash": "4.17.10"
- }
- },
- "webpack-sources": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz",
- "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==",
- "dev": true,
- "requires": {
- "source-list-map": "2.0.0",
- "source-map": "0.6.1"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- }
- }
- },
- "webpack-subresource-integrity": {
- "version": "1.1.0-rc.4",
- "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.1.0-rc.4.tgz",
- "integrity": "sha1-xcTj1pD50vZKlVDgeodn+Xlqpdg=",
- "dev": true,
- "requires": {
- "webpack-core": "0.6.9"
- }
- },
- "websocket-driver": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz",
- "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=",
- "dev": true,
- "requires": {
- "http-parser-js": "0.4.13",
- "websocket-extensions": "0.1.3"
- }
- },
- "websocket-extensions": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
- "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
- "dev": true
- },
- "when": {
- "version": "3.6.4",
- "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz",
- "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=",
- "dev": true
- },
- "which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "dev": true,
- "requires": {
- "isexe": "2.0.0"
- }
- },
- "which-module": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
- "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
- "dev": true,
- "optional": true
- },
- "wide-align": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
- "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
- "dev": true,
- "requires": {
- "string-width": "1.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": "1.0.0",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
- "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
- "dev": true
- },
- "worker-farm": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz",
- "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==",
- "dev": true,
- "requires": {
- "errno": "0.1.7"
- }
- },
- "wrap-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
- "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
- "dev": true,
- "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=",
- "dev": true
- },
- "ws": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.2.tgz",
- "integrity": "sha1-iiRPoFJAHgjJiGz0SoUYnh/UBn8=",
- "dev": true,
- "requires": {
- "options": "0.0.6",
- "ultron": "1.0.2"
- }
- },
- "wtf-8": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz",
- "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=",
- "dev": true
- },
- "xml2js": {
- "version": "0.4.19",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
- "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
- "dev": true,
- "requires": {
- "sax": "1.2.4",
- "xmlbuilder": "9.0.7"
- },
- "dependencies": {
- "sax": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
- "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
- "dev": true
- }
- }
- },
- "xmlbuilder": {
- "version": "9.0.7",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
- "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
- "dev": true
- },
- "xmlhttprequest-ssl": {
- "version": "1.5.3",
- "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz",
- "integrity": "sha1-GFqIjATspGw+QHDZn3tJ3jUomS0=",
- "dev": true
- },
- "xtend": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
- "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
- "dev": true
- },
- "xxhashjs": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz",
- "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==",
- "dev": true,
- "requires": {
- "cuint": "0.2.2"
- }
- },
- "y18n": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
- "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
- "dev": true
- },
- "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.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"
- }
- },
- "yargs-parser": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz",
- "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
- "dev": true,
- "optional": true,
- "requires": {
- "camelcase": "3.0.0"
- },
- "dependencies": {
- "camelcase": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
- "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
- "dev": true,
- "optional": true
- }
- }
- },
- "yeast": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
- "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
- "dev": true
- },
- "yn": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz",
- "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=",
- "dev": true
- },
- "zone.js": {
- "version": "0.8.26",
- "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.26.tgz",
- "integrity": "sha512-W9Nj+UmBJG251wkCacIkETgra4QgBo/vgoEkb4a2uoLzpQG7qF9nzwoLXWU5xj3Fg2mxGvEDh47mg24vXccYjA=="
- }
- }
-}
diff --git a/gae/frontend/package.json b/gae/frontend/package.json
deleted file mode 100644
index 1511ee3..0000000
--- a/gae/frontend/package.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
- "name": "frontend",
- "version": "0.0.0",
- "scripts": {
- "ng": "ng",
- "start": "ng serve",
- "build": "ng build",
- "test": "ng test",
- "lint": "ng lint",
- "e2e": "ng e2e"
- },
- "private": true,
- "dependencies": {
- "@angular/animations": "^6.0.6",
- "@angular/cdk": "^6.2.1",
- "@angular/common": "^6.0.6",
- "@angular/compiler": "^6.0.6",
- "@angular/core": "^6.0.6",
- "@angular/flex-layout": "^6.0.0-beta.16",
- "@angular/forms": "^6.0.6",
- "@angular/http": "^6.0.6",
- "@angular/material": "^6.2.1",
- "@angular/platform-browser": "^6.0.6",
- "@angular/platform-browser-dynamic": "^6.0.6",
- "@angular/router": "^6.0.6",
- "core-js": "^2.5.4",
- "moment": "^2.22.2",
- "moment-timezone": "^0.5.21",
- "rxjs": "^6.0.0",
- "zone.js": "^0.8.26"
- },
- "devDependencies": {
- "@angular-devkit/build-angular": "~0.6.8",
- "@angular/cli": "~6.0.8",
- "@angular/compiler-cli": "^6.0.6",
- "@angular/language-service": "^6.0.6",
- "@types/jasmine": "~2.8.6",
- "@types/jasminewd2": "~2.0.3",
- "@types/node": "~8.9.4",
- "codelyzer": "~4.2.1",
- "jasmine-core": "~2.99.1",
- "jasmine-spec-reporter": "~4.2.1",
- "karma": "~1.7.1",
- "karma-chrome-launcher": "~2.2.0",
- "karma-coverage-istanbul-reporter": "~2.0.0",
- "karma-jasmine": "~1.1.1",
- "karma-jasmine-html-reporter": "^0.2.2",
- "protractor": "~5.3.0",
- "ts-node": "~5.0.1",
- "tslint": "^5.9.1",
- "typescript": "^2.7.2"
- }
-}
diff --git a/gae/frontend/src/app/app.component.html b/gae/frontend/src/app/app.component.html
deleted file mode 100644
index 8f21391..0000000
--- a/gae/frontend/src/app/app.component.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<header>
- <div>
- <app-nav-bar id="nav-bar"></app-nav-bar>
- </div>
-</header>
-<mat-sidenav-container>
- <mat-sidenav-content>
- <router-outlet id="router-outlet"></router-outlet>
- </mat-sidenav-content>
- <mat-sidenav #sidenav mode="over" position="end" [(opened)]="sideNavOpened">
- <button mat-button (click)="sidenav.toggle()">
- <mat-icon>clear</mat-icon>
- </button>
- <mat-list>
- <mat-list-item *ngFor="let property of selectedEntity">
- <h4 id="property-name" mat-line>{{property.name}}</h4>
- <p id="property-value" mat-line *ngFor="let each of property.value">{{each}}</p>
- </mat-list-item>
- </mat-list>
- </mat-sidenav>
-</mat-sidenav-container>
diff --git a/gae/frontend/src/app/app.component.scss b/gae/frontend/src/app/app.component.scss
deleted file mode 100644
index d818d0e..0000000
--- a/gae/frontend/src/app/app.component.scss
+++ /dev/null
@@ -1,28 +0,0 @@
-mat-sidenav {
- width: 400px;
- padding: 30px 10px;
-}
-
-#property-name {
- color: rgba(0, 0, 0, 0.66);
- font-size: 12px;
- margin-bottom: 2px;
-}
-
-#property-value {
- font-size: 12px;
-}
-
-.mat-button {
- position: absolute;
- top: 10px;
- right: 10px;
- min-width: 28px;
- width: 28px;
- height: 28px;
- padding: 0;
- .mat-icon {
- width: 24px;
- height: 24px;
- }
-}
diff --git a/gae/frontend/src/app/app.component.spec.ts b/gae/frontend/src/app/app.component.spec.ts
deleted file mode 100644
index e69de29..0000000
--- a/gae/frontend/src/app/app.component.spec.ts
+++ /dev/null
diff --git a/gae/frontend/src/app/app.component.ts b/gae/frontend/src/app/app.component.ts
deleted file mode 100644
index 1a2ef06..0000000
--- a/gae/frontend/src/app/app.component.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { Component } from '@angular/core';
-
-import { AppService } from "./appservice";
-
-
-@Component({
- selector: 'app-root',
- templateUrl: './app.component.html',
- styleUrls: ['./app.component.scss']
-})
-export class AppComponent {
- _sideNavOpened = false;
- get sideNavOpened(): boolean {
- return this._sideNavOpened;
- }
- set sideNavOpened(value: boolean) {
- this._sideNavOpened = value;
- if (!value) {
- this.selectedEntity = this.selectedEntity.slice();
- }
- }
- selectedEntity: {name: string; value: any[]}[] = [];
-
- constructor(private appService: AppService) {
- appService.closeSideNavEmitter.subscribe(() => {this.sideNavOpened = false});
- appService.showDetailsEmitter.subscribe(
- (entity) => {
- this.selectedEntity.length = 0;
- if (entity) {
- let self = this;
- Object.keys(entity).forEach(function(value){
- if (value !== 'urlsafe_key') {
- self.selectedEntity.push({
- name: value,
- value: (entity[value] instanceof Array) ? entity[value] : [entity[value]]
- });
- }
- });
- }
- this.sideNavOpened = !this.sideNavOpened;
- },
- (error) => {
- console.log(error);
- }
- )
- }
-}
diff --git a/gae/frontend/src/app/app.module.ts b/gae/frontend/src/app/app.module.ts
deleted file mode 100644
index ec940db..0000000
--- a/gae/frontend/src/app/app.module.ts
+++ /dev/null
@@ -1,141 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// Angular modules.
-import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-import { BrowserModule } from '@angular/platform-browser';
-import { FormsModule } from '@angular/forms';
-import { HttpClientModule } from '@angular/common/http';
-import { NgModule } from '@angular/core';
-import { RouterModule, Routes } from '@angular/router';
-
-// Angular Material modules
-import { MatButtonModule } from '@angular/material/button';
-import { MatCardModule } from '@angular/material/card';
-import { MatChipsModule } from '@angular/material/chips';
-import { MatExpansionModule } from '@angular/material/expansion';
-import { MatFormFieldModule } from '@angular/material/form-field';
-import { MatIconModule } from '@angular/material';
-import { MatInputModule } from '@angular/material/input';
-import { MatListModule } from '@angular/material/list';
-import { MatPaginatorModule } from '@angular/material/paginator';
-import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
-import { MatSnackBarModule } from '@angular/material/snack-bar';
-import { MatSelectModule } from '@angular/material/select';
-import { MatSidenavModule } from '@angular/material/sidenav';
-import { MatSortModule } from '@angular/material/sort';
-import { MatTableModule } from '@angular/material/table';
-import { MatTabsModule } from '@angular/material/tabs';
-
-// User components.
-import { AppComponent } from './app.component';
-import { BuildComponent } from './menu/build/build.component';
-import { DashboardComponent } from './menu/dashboard/dashboard.component';
-import { DeviceComponent } from './menu/device/device.component';
-import { FilterComponent } from './shared/filter/filter.component';
-import { JobComponent } from './menu/job/job.component';
-import { LabComponent } from './menu/lab/lab.component';
-import { ScheduleComponent } from './menu/schedule/schedule.component';
-
-// User modules.
-import { NavModule } from './shared/navbar/navbar';
-
-// Other dependencies.
-import { FlexLayoutModule } from '@angular/flex-layout';
-
-// User directives for CDK (Component Development Kit).
-import { CdkDetailRowDirective } from './menu/cdk-detail-row.directive';
-
-
-const appRoutes: Routes = [
- { path: 'device', component: DeviceComponent },
- { path: 'build', component: BuildComponent },
- { path: 'job', component: JobComponent },
- { path: 'lab', component: LabComponent },
- { path: 'schedule', component: ScheduleComponent },
- { path: '', component: DashboardComponent },
- { path: '**', redirectTo: '/', pathMatch: 'full' }
-];
-
-
-@NgModule({
- imports: [
- MatButtonModule,
- MatCardModule,
- MatChipsModule,
- MatExpansionModule,
- MatFormFieldModule,
- MatIconModule,
- MatInputModule,
- MatListModule,
- MatPaginatorModule,
- MatProgressSpinnerModule,
- MatSnackBarModule,
- MatSelectModule,
- MatSidenavModule,
- MatSortModule,
- MatTableModule,
- MatTabsModule,
- ],
- exports: [
- MatButtonModule,
- MatCardModule,
- MatChipsModule,
- MatExpansionModule,
- MatFormFieldModule,
- MatIconModule,
- MatInputModule,
- MatListModule,
- MatPaginatorModule,
- MatProgressSpinnerModule,
- MatSnackBarModule,
- MatSelectModule,
- MatSidenavModule,
- MatSortModule,
- MatTableModule,
- MatTabsModule,
- ]
-})
-export class MaterialModule {}
-
-
-@NgModule({
- declarations: [
- AppComponent,
- BuildComponent,
- CdkDetailRowDirective,
- DashboardComponent,
- DeviceComponent,
- FilterComponent,
- JobComponent,
- LabComponent,
- ScheduleComponent,
- ],
- imports: [
- BrowserAnimationsModule,
- BrowserModule,
- FlexLayoutModule,
- FormsModule,
- HttpClientModule,
- MaterialModule,
- NavModule,
- RouterModule.forRoot(
- appRoutes
- ),
- ],
- providers: [],
- bootstrap: [AppComponent]
-})
-export class AppModule { }
diff --git a/gae/frontend/src/app/appservice.ts b/gae/frontend/src/app/appservice.ts
deleted file mode 100644
index 6b303f0..0000000
--- a/gae/frontend/src/app/appservice.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {EventEmitter, Injectable, Output} from '@angular/core';
-
-
-@Injectable({
- providedIn: 'root',
-})
-export class AppService {
- @Output() closeSideNavEmitter = new EventEmitter();
- @Output() showDetailsEmitter = new EventEmitter();
- constructor() {
- }
-
- /** Emits an EventEmitter to display entity in the side nav window. */
- showDetails(entity) {
- this.showDetailsEmitter.emit(entity);
- }
-
- /** Emits an EventEmitter to close the side nav window. */
- closeSideNav() {
- this.closeSideNavEmitter.emit();
- }
-}
diff --git a/gae/frontend/src/app/menu/build/build.component.html b/gae/frontend/src/app/menu/build/build.component.html
deleted file mode 100644
index d8ae525..0000000
--- a/gae/frontend/src/app/menu/build/build.component.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<div class="entity-filter">
- <app-filter (applyFilters)="applyFilters($event)" [disabled]="loading"></app-filter>
-</div>
-<div class="mat-elevation-z2 entity-table" [ngStyle]="{'opacity': (loading) ? 0.2 : 1 }">
- <mat-table #table [dataSource]="dataSource">
- <!-- Index Column -->
- <ng-container matColumnDef="_index">
- <mat-header-cell *matHeaderCellDef>No.</mat-header-cell>
- <mat-cell *matCellDef="let i = index"> {{i+1+pageSize*pageIndex}} </mat-cell>
- </ng-container>
-
- <!-- Manifest Branch Column -->
- <ng-container matColumnDef="artifact_type">
- <mat-header-cell *matHeaderCellDef>Artifact Type</mat-header-cell>
- <mat-cell *matCellDef="let build"> {{build.artifact_type}} </mat-cell>
- </ng-container>
-
- <!-- Manifest Branch Column -->
- <ng-container matColumnDef="manifest_branch">
- <mat-header-cell *matHeaderCellDef>Manifest Branch</mat-header-cell>
- <mat-cell *matCellDef="let build"> {{build.manifest_branch}} </mat-cell>
- </ng-container>
-
- <!-- Build ID Column -->
- <ng-container matColumnDef="build_id">
- <mat-header-cell *matHeaderCellDef>Build ID</mat-header-cell>
- <mat-cell *matCellDef="let build"> {{build.build_id}} </mat-cell>
- </ng-container>
-
- <!-- Build Target Column -->
- <ng-container matColumnDef="build_target">
- <mat-header-cell *matHeaderCellDef>Build Target</mat-header-cell>
- <mat-cell *matCellDef="let build"> {{build.build_target}} </mat-cell>
- </ng-container>
-
- <!-- Build Type Column -->
- <ng-container matColumnDef="build_type">
- <mat-header-cell *matHeaderCellDef>Build Type</mat-header-cell>
- <mat-cell *matCellDef="let build"> {{build.build_type}} </mat-cell>
- </ng-container>
-
- <!-- Signed Column -->
- <ng-container matColumnDef="signed">
- <mat-header-cell *matHeaderCellDef>Signed</mat-header-cell>
- <mat-cell *matCellDef="let build"> {{build.signed}} </mat-cell>
- </ng-container>
-
- <mat-header-row *matHeaderRowDef="columnTitles"></mat-header-row>
- <mat-row *matRowDef="let row; columns: columnTitles;"></mat-row>
- </mat-table>
-
- <mat-paginator [length]="count"
- [pageSize]="pageSize"
- [pageSizeOptions]="pageSizeOptions"
- [pageIndex]="pageIndex"
- (page)="pageEvent = onPageEvent($event)">
- </mat-paginator>
-</div>
-<div class="loading-spinner" *ngIf="loading">
- <mat-spinner color="primary"></mat-spinner>
-</div>
diff --git a/gae/frontend/src/app/menu/build/build.component.scss b/gae/frontend/src/app/menu/build/build.component.scss
deleted file mode 100644
index e69de29..0000000
--- a/gae/frontend/src/app/menu/build/build.component.scss
+++ /dev/null
diff --git a/gae/frontend/src/app/menu/build/build.component.ts b/gae/frontend/src/app/menu/build/build.component.ts
deleted file mode 100644
index e4c7325..0000000
--- a/gae/frontend/src/app/menu/build/build.component.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { MatSnackBar, MatTableDataSource, PageEvent } from '@angular/material';
-
-import { AppService } from '../../appservice';
-import { Build } from '../../model/build';
-import { BuildService } from './build.service';
-import { FilterComponent } from '../../shared/filter/filter.component';
-import { FilterItem } from '../../model/filter_item';
-import { MenuBaseClass } from '../menu_base';
-
-
-/** Component that handles build menu. */
-@Component({
- selector: 'app-build',
- templateUrl: './build.component.html',
- providers: [ BuildService ],
- styleUrls: ['./build.component.scss'],
-})
-export class BuildComponent extends MenuBaseClass implements OnInit {
- columnTitles = [
- '_index',
- 'artifact_type',
- 'manifest_branch',
- 'build_id',
- 'build_target',
- 'build_type',
- 'signed'];
- dataSource = new MatTableDataSource<Build>();
- pageEvent: PageEvent;
- appliedFilters: FilterItem[];
-
- @ViewChild(FilterComponent) filterComponent: FilterComponent;
-
- constructor(private buildService: BuildService,
- appService: AppService,
- snackBar: MatSnackBar) {
- super(appService, snackBar);
- }
-
- ngOnInit(): void {
- this.filterComponent.setSelectorList(Build);
- this.getCount();
- this.getBuilds(this.pageSize, this.pageSize * this.pageIndex);
- }
-
- /** Gets a total count of builds. */
- getCount(observer = this.getDefaultCountObservable()) {
- const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
- this.buildService.getCount(filterJSON).subscribe(observer);
- }
-
- /** Gets builds.
- * @param size A number, at most this many results will be returned.
- * @param offset A Number of results to skip.
- */
- getBuilds(size = 0, offset = 0) {
- this.loading = true;
- const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
- this.buildService.getBuilds(size, offset, filterJSON, '', '')
- .subscribe(
- (response) => {
- this.loading = false;
- if (this.count >= 0) {
- let length = 0;
- if (response.builds) {
- length = response.builds.length;
- }
- const total = length + offset;
- if (response.has_next) {
- if (length !== this.pageSize) {
- this.showSnackbar('Received unexpected number of entities.');
- } else if (this.count <= total) {
- this.getCount();
- }
- } else {
- if (this.count !== total) {
- if (length !== this.count) {
- this.getCount();
- } else if (this.count > total) {
- const countObservable = this.getDefaultCountObservable([
- () => {
- this.pageIndex = Math.floor(this.count / this.pageSize);
- this.getBuilds(this.pageSize, this.pageSize * this.pageIndex);
- }
- ]);
- this.getCount(countObservable);
- }
- }
- }
- }
- this.dataSource.data = response.builds;
- },
- (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
- );
- }
-
- /** Hooks a page event and handles properly. */
- onPageEvent(event: PageEvent) {
- this.pageSize = event.pageSize;
- this.pageIndex = event.pageIndex;
- this.getBuilds(this.pageSize, this.pageSize * this.pageIndex);
- return event;
- }
-
- /** Applies a filter and get entities with it. */
- applyFilters(filters) {
- this.pageIndex = 0;
- this.appliedFilters = filters;
- this.getCount();
- this.getBuilds(this.pageSize, this.pageSize * this.pageIndex);
- }
-}
diff --git a/gae/frontend/src/app/menu/build/build.service.ts b/gae/frontend/src/app/menu/build/build.service.ts
deleted file mode 100644
index d60f790..0000000
--- a/gae/frontend/src/app/menu/build/build.service.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-
-import { catchError } from 'rxjs/operators';
-import { Observable } from 'rxjs';
-
-import { BuildWrapper } from '../../model/build_wrapper';
-import { environment } from '../../../environments/environment';
-import { ServiceBase } from '../../shared/servicebase';
-
-
-@Injectable()
-export class BuildService extends ServiceBase {
- constructor(public httpClient: HttpClient) {
- super(httpClient);
- this.url = environment['baseURL'] + '/build/v1/';
- }
-
- getBuilds(size: number,
- offset: number,
- filterInfo: string,
- sort: string,
- direction: string): Observable<BuildWrapper> {
- const url = this.url + 'get';
- return this.httpClient.post<BuildWrapper>(url, {size: size, offset: offset, filter: filterInfo, sort: sort, direction: direction})
- .pipe(catchError(this.handleError));
- }
-}
diff --git a/gae/frontend/src/app/menu/cdk-detail-row.directive.ts b/gae/frontend/src/app/menu/cdk-detail-row.directive.ts
deleted file mode 100644
index 60b490a..0000000
--- a/gae/frontend/src/app/menu/cdk-detail-row.directive.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Directive, EventEmitter, HostBinding, HostListener, Input, Output, TemplateRef, ViewContainerRef} from '@angular/core';
-
-
-@Directive({
- selector: '[appCdkDetailRow]'
-})
-export class CdkDetailRowDirective {
- private row: any;
- private tRef: TemplateRef<any>;
- private opened: boolean;
-
- @HostBinding('class.expanded')
- get expended(): boolean {
- return this.opened;
- }
-
- @Input()
- set appCdkDetailRow(value: any) {
- if (value !== this.row) {
- this.row = value;
- // this.render();
- }
- }
-
- @Input('appCdkDetailRowTpl')
- set template(value: TemplateRef<any>) {
- if (value !== this.tRef) {
- this.tRef = value;
- }
- }
-
- @Output() toggleChange = new EventEmitter<CdkDetailRowDirective>();
-
- constructor(public vcRef: ViewContainerRef) { }
-
- @HostListener('click')
- onClick(): void {
- this.toggle();
- }
-
- toggle(): void {
- if (this.opened) {
- this.vcRef.clear();
- } else {
- this.render();
- }
- this.opened = this.vcRef.length > 0;
- this.toggleChange.emit(this);
- }
-
- private render(): void {
- this.vcRef.clear();
- if (this.tRef && this.row) {
- this.vcRef.createEmbeddedView(this.tRef, { $implicit: this.row });
- }
- }
-}
diff --git a/gae/frontend/src/app/menu/dashboard/dashboard.component.html b/gae/frontend/src/app/menu/dashboard/dashboard.component.html
deleted file mode 100644
index b91e80c..0000000
--- a/gae/frontend/src/app/menu/dashboard/dashboard.component.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<div fxLayout="row">
- <mat-card>
- <mat-card-title>Build</mat-card-title>
- <mat-card-subtitle>Last updated: {{getRelativeTime(lastBuildUpdateTime)}}</mat-card-subtitle>
- <button mat-raised-button (click)="getLatestBuild()">
- <mat-icon>refresh</mat-icon>
- </button>
- </mat-card>
- <mat-card>
- <mat-card-title>Schedule</mat-card-title>
- <mat-card-subtitle>Last updated: {{getRelativeTime(lastScheduleUpdateTime)}}</mat-card-subtitle>
- <button mat-raised-button (click)="getLastestSchedule()">
- <mat-icon>refresh</mat-icon>
- </button>
- </mat-card>
-</div>
diff --git a/gae/frontend/src/app/menu/dashboard/dashboard.component.scss b/gae/frontend/src/app/menu/dashboard/dashboard.component.scss
deleted file mode 100644
index a17cb36..0000000
--- a/gae/frontend/src/app/menu/dashboard/dashboard.component.scss
+++ /dev/null
@@ -1,17 +0,0 @@
-.mat-card {
- width: 50%;
-
- .mat-raised-button {
- position: absolute;
- top: 10px;
- right: 10px;
- min-width: 28px;
- width: 28px;
- height: 28px;
- padding: 0;
- .mat-icon {
- width: 24px;
- height: 24px;
- }
- }
-}
diff --git a/gae/frontend/src/app/menu/dashboard/dashboard.component.ts b/gae/frontend/src/app/menu/dashboard/dashboard.component.ts
deleted file mode 100644
index 0157ea8..0000000
--- a/gae/frontend/src/app/menu/dashboard/dashboard.component.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit } from '@angular/core';
-import { MatSnackBar } from '@angular/material';
-
-import { AppService } from '../../appservice';
-import { BuildService } from "../build/build.service";
-import { MenuBaseClass } from "../menu_base";
-import { ScheduleService } from "../schedule/schedule.service";
-
-/** Component that handles dashboard. */
-@Component({
- selector: 'app-dashboard',
- templateUrl: './dashboard.component.html',
- providers: [ BuildService, ScheduleService ],
- styleUrls: ['./dashboard.component.scss']
-})
-export class DashboardComponent extends MenuBaseClass implements OnInit {
- lastBuildUpdateTime: any = '---';
- lastScheduleUpdateTime: any = '---';
-
- constructor(private buildService: BuildService,
- private scheduleService: ScheduleService,
- appService: AppService,
- snackBar: MatSnackBar) {
- super(appService, snackBar);
- }
-
- ngOnInit(): void {
- this.getLatestBuild();
- this.getLastestSchedule();
- }
-
- /** Fetches the most recently updated build and gets timestamp from it. */
- getLatestBuild() {
- this.lastBuildUpdateTime = '---';
- this.buildService.getBuilds(1, 0, '', 'timestamp', 'desc')
- .subscribe(
- (response) => {
- if (response.builds) {
- this.lastBuildUpdateTime = response.builds[0].timestamp;
- }
- },
- (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
- );
- }
-
- /** Fetches the most recently updated schedule and gets timestamp from it. */
- getLastestSchedule() {
- this.lastScheduleUpdateTime = '---';
- this.scheduleService.getSchedules(1, 0, '', 'timestamp', 'desc')
- .subscribe(
- (response) => {
- if (response.schedules) {
- this.lastScheduleUpdateTime = response.schedules[0].timestamp;
- }
- },
- (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
- );
- }
-}
diff --git a/gae/frontend/src/app/menu/device/device.component.html b/gae/frontend/src/app/menu/device/device.component.html
deleted file mode 100644
index b36491e..0000000
--- a/gae/frontend/src/app/menu/device/device.component.html
+++ /dev/null
@@ -1,80 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<div class="entity-filter">
- <app-filter (applyFilters)="applyFilters($event)" [disabled]="loading"></app-filter>
-</div>
-<div class="mat-elevation-z2 entity-table" [ngStyle]="{'opacity': (loading) ? 0.2 : 1 }">
- <mat-table [dataSource]="dataSource" matSort matSortActive="hostname" matSortDirection="asc">
- <!-- Index Column -->
- <ng-container matColumnDef="_index">
- <mat-header-cell *matHeaderCellDef>No.</mat-header-cell>
- <mat-cell *matCellDef="let i = index"> {{i+1+pageSize*pageIndex}} </mat-cell>
- </ng-container>
-
- <!-- Host Name Column -->
- <ng-container matColumnDef="hostname">
- <mat-header-cell *matHeaderCellDef mat-sort-header disabled>Host Name</mat-header-cell>
- <mat-cell *matCellDef="let device"> {{device.hostname}} </mat-cell>
- </ng-container>
-
- <!-- Product Column -->
- <ng-container matColumnDef="product">
- <mat-header-cell *matHeaderCellDef>Product</mat-header-cell>
- <mat-cell *matCellDef="let device"> {{device.product}} </mat-cell>
- </ng-container>
-
- <!-- Serial Column -->
- <ng-container matColumnDef="serial">
- <mat-header-cell *matHeaderCellDef>Serial</mat-header-cell>
- <mat-cell *matCellDef="let device"> {{device.serial}} </mat-cell>
- </ng-container>
-
- <!-- Status Column -->
- <ng-container matColumnDef="status">
- <mat-header-cell *matHeaderCellDef>Status</mat-header-cell>
- <mat-cell *matCellDef="let device"> {{deviceStatusEnum[device.status]}} </mat-cell>
- </ng-container>
-
- <!-- Scheduling Status Column -->
- <ng-container matColumnDef="scheduling_status">
- <mat-header-cell *matHeaderCellDef>Scheduling Status</mat-header-cell>
- <mat-cell *matCellDef="let device"> {{schedulingStatusEnum[device.scheduling_status]}} </mat-cell>
- </ng-container>
-
- <!-- Equipment Column -->
- <ng-container matColumnDef="device_equipment">
- <mat-header-cell *matHeaderCellDef>Equipment</mat-header-cell>
- <mat-cell *matCellDef="let device"> {{device.device_equipment ? device.device_equipment.join(", ") : "None"}} </mat-cell>
- </ng-container>
-
- <!-- Timestamp Column -->
- <ng-container matColumnDef="timestamp">
- <mat-header-cell *matHeaderCellDef>Timestamp</mat-header-cell>
- <mat-cell *matCellDef="let device">{{getRelativeTime(device.timestamp)}}</mat-cell>
- </ng-container>
-
- <mat-header-row *matHeaderRowDef="columnTitles"></mat-header-row>
- <mat-row *matRowDef="let row; columns: columnTitles;"></mat-row>
- </mat-table>
- <mat-paginator [length]="count"
- [pageSize]="pageSize"
- [pageSizeOptions]="pageSizeOptions"
- [pageIndex]="pageIndex"
- (page)="pageEvent = onPageEvent($event)">
- </mat-paginator>
-</div>
-<div class="loading-spinner" *ngIf="loading">
- <mat-spinner color="primary"></mat-spinner>
-</div>
diff --git a/gae/frontend/src/app/menu/device/device.component.scss b/gae/frontend/src/app/menu/device/device.component.scss
deleted file mode 100644
index 165de43..0000000
--- a/gae/frontend/src/app/menu/device/device.component.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-.mat-header-cell {
- padding: 0 10px 0 10px;
-}
-
-.mat-cell {
- padding: 0 10px 0 10px;
-}
diff --git a/gae/frontend/src/app/menu/device/device.component.ts b/gae/frontend/src/app/menu/device/device.component.ts
deleted file mode 100644
index 6258aed..0000000
--- a/gae/frontend/src/app/menu/device/device.component.ts
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { MatSnackBar, MatTableDataSource, PageEvent } from '@angular/material';
-
-import { AppService } from '../../appservice';
-import { Device } from '../../model/device';
-import { DeviceService } from './device.service';
-import { DeviceStatus, SchedulingStatus } from '../../shared/vtslab_status';
-import { FilterComponent } from '../../shared/filter/filter.component';
-import { FilterItem } from '../../model/filter_item';
-import { MenuBaseClass } from '../menu_base';
-
-
-/** Component that handles device menu. */
-@Component({
- selector: 'app-device',
- templateUrl: './device.component.html',
- providers: [ DeviceService ],
- styleUrls: ['./device.component.scss'],
-})
-export class DeviceComponent extends MenuBaseClass implements OnInit {
- columnTitles = [
- '_index',
- 'hostname',
- 'product',
- 'serial',
- 'status',
- 'scheduling_status',
- 'device_equipment',
- 'timestamp',
- ];
- dataSource = new MatTableDataSource<Device>();
- pageEvent: PageEvent;
- deviceStatusEnum = DeviceStatus;
- schedulingStatusEnum = SchedulingStatus;
- appliedFilters: FilterItem[];
-
- sort = '';
- sortDirection = '';
-
- @ViewChild(FilterComponent) filterComponent: FilterComponent;
-
- constructor(private deviceService: DeviceService,
- appService: AppService,
- snackBar: MatSnackBar) {
- super(appService, snackBar);
- }
-
- ngOnInit(): void {
- this.sort = 'hostname';
- this.sortDirection = 'asc';
-
- this.filterComponent.setSelectorList(Device);
- this.getCount();
- this.getDevices(this.pageSize, this.pageSize * this.pageIndex);
- }
-
- /** Gets a total count of devices. */
- getCount(observer = this.getDefaultCountObservable()) {
- const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
- this.deviceService.getCount(filterJSON).subscribe(observer);
- }
-
- /** Gets devices.
- * @param size A number, at most this many results will be returned.
- * @param offset A Number of results to skip.
- */
- getDevices(size = 0, offset = 0) {
- this.loading = true;
- const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
- this.deviceService.getDevices(size, offset, filterJSON, this.sort, this.sortDirection)
- .subscribe(
- (response) => {
- this.loading = false;
- if (this.count >= 0) {
- let length = 0;
- if (response.devices) {
- length = response.devices.length;
- }
- const total = length + offset;
- if (response.has_next) {
- if (length !== this.pageSize) {
- this.showSnackbar('Received unexpected number of entities.');
- } else if (this.count <= total) {
- this.getCount();
- }
- } else {
- if (this.count !== total) {
- if (length !== this.count) {
- this.getCount();
- } else if (this.count > total) {
- const countObservable = this.getDefaultCountObservable([
- () => {
- this.pageIndex = Math.floor(this.count / this.pageSize);
- this.getDevices(this.pageSize, this.pageSize * this.pageIndex);
- }
- ]);
- this.getCount(countObservable);
- }
- }
- }
- }
- this.dataSource.data = response.devices;
- },
- (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
- );
- }
-
- /** Hooks a page event and handles properly. */
- onPageEvent(event: PageEvent) {
- this.pageSize = event.pageSize;
- this.pageIndex = event.pageIndex;
- this.getDevices(this.pageSize, this.pageSize * this.pageIndex);
- return event;
- }
-
- /** Applies a filter and get entities with it. */
- applyFilters(filters) {
- this.pageIndex = 0;
- this.appliedFilters = filters;
- this.getCount();
- this.getDevices(this.pageSize, this.pageSize * this.pageIndex);
- }
-}
diff --git a/gae/frontend/src/app/menu/device/device.service.ts b/gae/frontend/src/app/menu/device/device.service.ts
deleted file mode 100644
index 2a465ff..0000000
--- a/gae/frontend/src/app/menu/device/device.service.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-
-import { catchError } from 'rxjs/operators';
-import { Observable } from 'rxjs';
-
-import { environment } from '../../../environments/environment';
-import { DeviceWrapper } from '../../model/device_wrapper';
-import { ServiceBase } from '../../shared/servicebase';
-
-
-@Injectable()
-export class DeviceService extends ServiceBase {
- constructor(public httpClient: HttpClient) {
- super(httpClient);
- this.url = environment['baseURL'] + '/host/v1/';
- }
-
- getDevices(size: number,
- offset: number,
- filterInfo: string,
- sort: string,
- direction: string): Observable<DeviceWrapper> {
- const url = this.url + 'get';
- return this.httpClient.post<DeviceWrapper>(url, {size: size, offset: offset, filter: filterInfo, sort: sort, direction: direction})
- .pipe(catchError(this.handleError));
- }
-}
diff --git a/gae/frontend/src/app/menu/job/_job-theme.scss b/gae/frontend/src/app/menu/job/_job-theme.scss
deleted file mode 100644
index 084f1fb..0000000
--- a/gae/frontend/src/app/menu/job/_job-theme.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-@mixin schedule-theme($theme) {
- $primary: map-get($theme, primary);
- $accent: map-get($theme, accent);
- $warn: map-get($theme, warn);
- $background: map-get($theme, background);
- $foreground: map-get($theme, foreground);
-}
diff --git a/gae/frontend/src/app/menu/job/job.component.html b/gae/frontend/src/app/menu/job/job.component.html
deleted file mode 100644
index 634402d..0000000
--- a/gae/frontend/src/app/menu/job/job.component.html
+++ /dev/null
@@ -1,192 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<div class="statistics-table" [ngStyle]="{'opacity': (loading) ? 0.2 : 1 }">
- <mat-table [dataSource]="statDataSource">
- <ng-container matColumnDef="hours">
- <mat-header-cell *matHeaderCellDef>Stats</mat-header-cell>
- <mat-cell *matCellDef="let stat"> {{stat.hours}} </mat-cell>
- </ng-container>
-
- <ng-container matColumnDef="created">
- <mat-header-cell *matHeaderCellDef>Created</mat-header-cell>
- <mat-cell *matCellDef="let stat"> {{stat.created}} </mat-cell>
- </ng-container>
-
- <ng-container matColumnDef="completed">
- <mat-header-cell *matHeaderCellDef>Completed</mat-header-cell>
- <mat-cell *matCellDef="let stat"> {{stat.completed}} ({{stat.created > 0 ? (stat.completed/stat.created*100 | number:'1.0-2') : 0}})% </mat-cell>
- </ng-container>
-
- <ng-container matColumnDef="running">
- <mat-header-cell *matHeaderCellDef>Running/Ready</mat-header-cell>
- <mat-cell *matCellDef="let stat"> {{stat.running}} ({{stat.created > 0 ? (stat.running/stat.created*100 | number:'1.0-2') : 0}})% </mat-cell>
- </ng-container>
-
- <ng-container matColumnDef="bootup_err">
- <mat-header-cell *matHeaderCellDef>Boot-up Error</mat-header-cell>
- <mat-cell *matCellDef="let stat"> {{stat.bootup_err}} ({{stat.created > 0 ? (stat.bootup_err/stat.created*100 | number:'1.0-2') : 0}})% </mat-cell>
- </ng-container>
-
- <ng-container matColumnDef="infra_err">
- <mat-header-cell *matHeaderCellDef>Infra Error</mat-header-cell>
- <mat-cell *matCellDef="let stat"> {{stat.infra_err}} ({{stat.created > 0 ? (stat.infra_err/stat.created*100 | number:'1.0-2') : 0}})% </mat-cell>
- </ng-container>
-
- <ng-container matColumnDef="expired">
- <mat-header-cell *matHeaderCellDef>Expired</mat-header-cell>
- <mat-cell *matCellDef="let stat"> {{stat.expired}} ({{stat.created > 0 ? (stat.expired/stat.created*100 | number:'1.0-2') : 0}})% </mat-cell>
- </ng-container>
-
- <mat-header-row *matHeaderRowDef="statColumnTitles"></mat-header-row>
- <mat-row *matRowDef="let row; columns: statColumnTitles;"></mat-row>
- </mat-table>
-</div>
-<div class="entity-filter">
- <app-filter (applyFilters)="applyFilters($event)" [disabled]="loading"></app-filter>
-</div>
-<div class="mat-elevation-z2 entity-table" [ngStyle]="{'opacity': (loading) ? 0.2 : 1 }">
- <mat-table [dataSource]="dataSource" matSort matSortActive="timestamp" matSortDirection="desc">
- <!-- Index Column -->
- <ng-container matColumnDef="_index">
- <mat-header-cell *matHeaderCellDef>No.</mat-header-cell>
- <mat-cell *matCellDef="let i = index"> {{i+1+pageSize*pageIndex}} </mat-cell>
- </ng-container>
-
- <!-- Test Type Column -->
- <ng-container matColumnDef="test_type">
- <mat-header-cell *matHeaderCellDef>Test Type</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{getTestTypeText(job.test_type)}} </mat-cell>
- </ng-container>
-
- <!-- Test Name Column -->
- <ng-container matColumnDef="test_name">
- <mat-header-cell *matHeaderCellDef>Test Name</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.test_name}} </mat-cell>
- </ng-container>
-
- <!-- Host Name Column -->
- <ng-container matColumnDef="hostname">
- <mat-header-cell *matHeaderCellDef>Hostname</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.hostname}} </mat-cell>
- </ng-container>
-
- <!-- Device Column -->
- <ng-container matColumnDef="device">
- <mat-header-cell *matHeaderCellDef>Device</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.device}} </mat-cell>
- </ng-container>
-
- <!-- Serial Column -->
- <ng-container matColumnDef="serial">
- <mat-header-cell *matHeaderCellDef>Serial</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.serial ? job.serial.join('\n') : ""}} </mat-cell>
- </ng-container>
-
- <!-- Device Branch Column -->
- <ng-container matColumnDef="manifest_branch">
- <mat-header-cell *matHeaderCellDef>Device Branch</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.manifest_branch}} </mat-cell>
- </ng-container>
-
- <!-- Device Build Target Column -->
- <ng-container matColumnDef="build_target">
- <mat-header-cell *matHeaderCellDef>Device Build Target</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.build_target}} </mat-cell>
- </ng-container>
-
- <!-- Device Build ID Column -->
- <ng-container matColumnDef="build_id">
- <mat-header-cell *matHeaderCellDef>Device Build ID</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.build_id}} </mat-cell>
- </ng-container>
-
- <!-- GSI Branch Column -->
- <ng-container matColumnDef="gsi_branch">
- <mat-header-cell *matHeaderCellDef>GSI Branch</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.gsi_branch}} </mat-cell>
- </ng-container>
-
- <!-- GSI Build Target Column -->
- <ng-container matColumnDef="gsi_build_target">
- <mat-header-cell *matHeaderCellDef>GSI Build Target</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.gsi_build_target}} </mat-cell>
- </ng-container>
-
- <!-- Device Build ID Column -->
- <ng-container matColumnDef="gsi_build_id">
- <mat-header-cell *matHeaderCellDef>GSI Build ID</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.gsi_build_id}} </mat-cell>
- </ng-container>
-
- <!-- Test Branch Column -->
- <ng-container matColumnDef="test_branch">
- <mat-header-cell *matHeaderCellDef>Test Branch</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.test_branch}} </mat-cell>
- </ng-container>
-
- <!-- Test Build Target Column -->
- <ng-container matColumnDef="test_build_target">
- <mat-header-cell *matHeaderCellDef>Test Build Target</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.test_build_target}} </mat-cell>
- </ng-container>
-
- <!-- Test Build ID Column -->
- <ng-container matColumnDef="test_build_id">
- <mat-header-cell *matHeaderCellDef>Test Build ID</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{job.test_build_id}} </mat-cell>
- </ng-container>
-
- <!-- Status Column -->
- <ng-container matColumnDef="status">
- <mat-header-cell *matHeaderCellDef>Status</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{jobStatusEnum[job.status]}} </mat-cell>
- </ng-container>
-
- <!-- Timestamp Column -->
- <ng-container matColumnDef="timestamp">
- <mat-header-cell *matHeaderCellDef mat-sort-header disabled>Timestamp</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{getRelativeTime(job.timestamp)}} </mat-cell>
- </ng-container>
-
- <!-- Heartbeat stamp Column -->
- <ng-container matColumnDef="heartbeat_stamp">
- <mat-header-cell *matHeaderCellDef>Heartbeat</mat-header-cell>
- <mat-cell *matCellDef="let job"> {{getRelativeTime(job.heartbeat_stamp)}} </mat-cell>
- </ng-container>
-
- <mat-header-row *matHeaderRowDef="columnTitles"></mat-header-row>
- <mat-row *matRowDef="let row; columns: columnTitles;"
- matRipple
- class="element-row"
- [appCdkDetailRow]="row" [appCdkDetailRowTpl]="job_detail"></mat-row>
- </mat-table>
- <mat-paginator [length]="count"
- [pageSize]="pageSize"
- [pageSizeOptions]="pageSizeOptions"
- [pageIndex]="pageIndex"
- (page)="pageEvent = onPageEvent($event)">
- </mat-paginator>
-</div>
-<ng-template #job_detail let-job>
- <div class="mat-row div-expandable" [@detailExpand] style="overflow: hidden">
- <a href="{{job.infra_log_url}}" download><button mat-raised-button [disabled]="(!job.infra_log_url)">Download Infra Log</button></a>
- <button mat-raised-button (click)="onShowDetailsClicked(job)">
- Show Details
- </button>
- </div>
-</ng-template>
-<div class="loading-spinner" *ngIf="loading">
- <mat-spinner color="primary"></mat-spinner>
-</div>
diff --git a/gae/frontend/src/app/menu/job/job.component.scss b/gae/frontend/src/app/menu/job/job.component.scss
deleted file mode 100644
index c8aee00..0000000
--- a/gae/frontend/src/app/menu/job/job.component.scss
+++ /dev/null
@@ -1,24 +0,0 @@
-.mat-header-cell {
- padding: 0 10px 0 10px;
-}
-
-.mat-cell {
- padding: 0 10px 0 10px;
-}
-
-.element-row {
- position: relative;
- overflow: hidden;
-}
-
-.element-row:not(.expanded) {
- cursor: pointer;
-}
-
-.element-row:not(.expanded):hover {
- background: #f5f5f5;
-}
-
-.element-row.expanded {
- border-bottom-color: transparent;
-}
diff --git a/gae/frontend/src/app/menu/job/job.component.ts b/gae/frontend/src/app/menu/job/job.component.ts
deleted file mode 100644
index 4375581..0000000
--- a/gae/frontend/src/app/menu/job/job.component.ts
+++ /dev/null
@@ -1,221 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { MatSnackBar, MatTableDataSource, PageEvent } from '@angular/material';
-import { animate, state, style, transition, trigger } from '@angular/animations';
-
-import { AppService } from '../../appservice';
-import { FilterComponent } from '../../shared/filter/filter.component';
-import { FilterCondition } from '../../model/filter_condition';
-import { FilterItem } from '../../model/filter_item';
-import { MenuBaseClass } from '../menu_base';
-import { Job } from '../../model/job';
-import { JobService } from './job.service';
-import { JobStatus, TestType } from '../../shared/vtslab_status';
-
-import * as moment from 'moment-timezone';
-
-
-/** Component that handles job menu. */
-@Component({
- selector: 'app-job',
- templateUrl: './job.component.html',
- providers: [ JobService ],
- styleUrls: ['./job.component.scss'],
- animations: [
- trigger('detailExpand', [
- state('void', style({height: '0px', minHeight: '0', visibility: 'hidden'})),
- state('*', style({height: '*', visibility: 'visible'})),
- transition('void <=> *', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
- ]),
- ],
-})
-export class JobComponent extends MenuBaseClass implements OnInit {
- columnTitles = [
- '_index',
- 'test_type',
- 'test_name',
- 'hostname',
- 'device',
- 'serial',
- 'manifest_branch',
- 'build_target',
- 'build_id',
- 'gsi_branch',
- 'gsi_build_target',
- 'gsi_build_id',
- 'test_branch',
- 'test_build_target',
- 'test_build_id',
- 'status',
- 'timestamp',
- 'heartbeat_stamp',
- ];
- statColumnTitles = [
- 'hours',
- 'created',
- 'completed',
- 'running',
- 'bootup_err',
- 'infra_err',
- 'expired',
- ];
- dataSource = new MatTableDataSource<Job>();
- statDataSource = new MatTableDataSource();
- pageEvent: PageEvent;
- jobStatusEnum = JobStatus;
- appliedFilters: FilterItem[];
-
- @ViewChild(FilterComponent) filterComponent: FilterComponent;
-
- sort = '';
- sortDirection = '';
-
- constructor(private jobService: JobService,
- appService: AppService,
- snackBar: MatSnackBar) {
- super(appService, snackBar);
- }
-
- ngOnInit(): void {
- // By default, job page requires list in desc order by timestamp.
- this.sort = 'timestamp';
- this.sortDirection = 'desc';
-
- this.filterComponent.setSelectorList(Job);
- this.getCount();
- this.getStatistics();
- this.getJobs(this.pageSize, this.pageSize * this.pageIndex);
- }
-
- /** Gets a total count of jobs. */
- getCount(observer = this.getDefaultCountObservable()) {
- const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
- this.jobService.getCount(filterJSON).subscribe(observer);
- }
-
- /** Gets jobs.
- * @param size A number, at most this many results will be returned.
- * @param offset A Number of results to skip.
- */
- getJobs(size = 0, offset = 0) {
- this.loading = true;
- const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
- this.jobService.getJobs(size, offset, filterJSON, this.sort, this.sortDirection)
- .subscribe(
- (response) => {
- this.loading = false;
- if (this.count >= 0) {
- let length = 0;
- if (response.jobs) {
- length = response.jobs.length;
- }
- const total = length + offset;
- if (response.has_next) {
- if (length !== this.pageSize) {
- this.showSnackbar('Received unexpected number of entities.');
- } else if (this.count <= total) {
- this.getCount();
- }
- } else {
- if (this.count !== total) {
- if (length !== this.count) {
- this.getCount();
- } else if (this.count > total) {
- const countObservable = this.getDefaultCountObservable([
- () => {
- this.pageIndex = Math.floor(this.count / this.pageSize);
- this.getJobs(this.pageSize, this.pageSize * this.pageIndex);
- }
- ]);
- this.getCount(countObservable);
- }
- }
- }
- }
- this.dataSource.data = response.jobs;
- },
- (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
- );
- }
-
- /** Hooks a page event and handles properly. */
- onPageEvent(event: PageEvent) {
- this.pageSize = event.pageSize;
- this.pageIndex = event.pageIndex;
- this.getJobs(this.pageSize, this.pageSize * this.pageIndex);
- return event;
- }
-
- /** Gets the recent jobs and calculate statistics */
- getStatistics() {
- const timeFilter = new FilterItem();
- timeFilter.key = 'timestamp';
- timeFilter.method = FilterCondition.GreaterThan;
- timeFilter.value = '72';
- const timeFilterString = JSON.stringify([timeFilter]);
- this.jobService.getJobs(0, 0, timeFilterString, '', '')
- .subscribe(
- (response) => {
- const stats_72hrs = this.buildStatisticsData('72 Hours', response.jobs);
- const jobs_24hrs = (response.jobs == null || response.jobs.length === 0) ? undefined : response.jobs.filter(
- job => (moment() - moment.tz(job.timestamp, 'YYYY-MM-DDThh:mm:ss', 'UTC')) / 3600000 < 24);
- const stats_24hrs = this.buildStatisticsData('24 Hours', jobs_24hrs);
- this.statDataSource.data = [stats_24hrs, stats_72hrs];
- },
- (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
- );
- }
-
- /** Builds statistics from given jobs list */
- buildStatisticsData(title, jobs) {
- if (jobs == null || jobs.length === 0) {
- return { hours: title, created: 0, completed: 0, running: 0, bootup_err: 0, infra_err: 0, expired: 0 };
- }
- return {
- hours: title,
- created: jobs.length,
- completed: jobs.filter(job => job.status != null && Number(job.status) === JobStatus.Complete).length,
- running: jobs.filter(job => job.status != null &&
- (Number(job.status) === JobStatus.Leased || Number(job.status) === JobStatus.Ready)).length,
- bootup_err: jobs.filter(job => job.status != null && Number(job.status) === JobStatus.Bootup_err).length,
- infra_err: jobs.filter(job => job.status != null && Number(job.status) === JobStatus.Infra_err).length,
- expired: jobs.filter(job => job.status != null && Number(job.status) === JobStatus.Expired).length,
- };
- }
-
- /** Generates text to represent in HTML with given test type. */
- getTestTypeText(status: number) {
- if (status === undefined || status & TestType.Unknown) {
- return TestType[TestType.Unknown];
- }
-
- const text_list = [];
- [TestType.ToT, TestType.OTA, TestType.Signed, TestType.Manual].forEach(function (value) {
- if (status & value) { text_list.push(TestType[value]); }
- });
-
- return text_list.join(', ');
- }
-
- /** Applies a filter and get entities with it. */
- applyFilters(filters) {
- this.pageIndex = 0;
- this.appliedFilters = filters;
- this.getCount();
- this.getJobs(this.pageSize, this.pageSize * this.pageIndex);
- }
-}
diff --git a/gae/frontend/src/app/menu/job/job.service.ts b/gae/frontend/src/app/menu/job/job.service.ts
deleted file mode 100644
index 71b5417..0000000
--- a/gae/frontend/src/app/menu/job/job.service.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-
-import { catchError } from 'rxjs/operators';
-import { Observable } from 'rxjs';
-
-import { environment } from '../../../environments/environment';
-import { JobWrapper } from '../../model/job_wrapper';
-import { ServiceBase } from '../../shared/servicebase';
-
-
-@Injectable()
-export class JobService extends ServiceBase {
- // url: string;
- constructor(public httpClient: HttpClient) {
- super(httpClient);
- this.url = environment['baseURL'] + '/job/v1/';
- }
-
- getJobs(size: number,
- offset: number,
- filterInfo: string,
- sort: string,
- direction: string): Observable<JobWrapper> {
- const url = this.url + 'get';
- return this.httpClient.post<JobWrapper>(url, {size: size, offset: offset, filter: filterInfo, sort: sort, direction: direction})
- .pipe(catchError(this.handleError));
- }
-}
diff --git a/gae/frontend/src/app/menu/lab/lab.component.html b/gae/frontend/src/app/menu/lab/lab.component.html
deleted file mode 100644
index 0392e2d..0000000
--- a/gae/frontend/src/app/menu/lab/lab.component.html
+++ /dev/null
@@ -1,109 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<mat-tab-group>
- <mat-tab label="Lab">
- <div class="mat-elevation-z2 entity-table">
- <mat-table #table [dataSource]="labDataSource">
- <!-- Index Column -->
- <ng-container matColumnDef="_index">
- <mat-header-cell *matHeaderCellDef class="index-column">No.</mat-header-cell>
- <mat-cell *matCellDef="let i = index" class="index-column"> {{i+1+pageSize*labPageIndex}} </mat-cell>
- </ng-container>
-
- <!-- Name Column -->
- <ng-container matColumnDef="name">
- <mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
- <mat-cell *matCellDef="let lab"> {{lab.name}} </mat-cell>
- </ng-container>
-
- <!-- Owner Column -->
- <ng-container matColumnDef="owner">
- <mat-header-cell *matHeaderCellDef>Owner</mat-header-cell>
- <mat-cell *matCellDef="let lab"> {{lab.owner}} </mat-cell>
- </ng-container>
-
- <!-- Admin Column -->
- <ng-container matColumnDef="admin">
- <mat-header-cell *matHeaderCellDef>Admin</mat-header-cell>
- <mat-cell *matCellDef="let lab"> {{lab.admin ? lab.admin.join(", ") : "None"}} </mat-cell>
- </ng-container>
-
- <!-- Host Count Column -->
- <ng-container matColumnDef="hostCount">
- <mat-header-cell *matHeaderCellDef># of Host</mat-header-cell>
- <mat-cell *matCellDef="let lab"> {{ lab.hosts.length }} </mat-cell>
- </ng-container>
-
- <mat-header-row *matHeaderRowDef="labColumnTitles"></mat-header-row>
- <mat-row *matRowDef="let row; columns: labColumnTitles;"></mat-row>
- </mat-table>
- <mat-paginator [length]="labCount"
- [pageSizeOptions]="pageSizeOptions"
- [pageIndex]="labPageIndex">
- </mat-paginator>
- </div>
- </mat-tab>
- <mat-tab label="Host">
- <div class="mat-elevation-z2 entity-table">
- <mat-table #table [dataSource]="hostDataSource">
- <!-- Index Column -->
- <ng-container matColumnDef="_index">
- <mat-header-cell *matHeaderCellDef class="index-column">No.</mat-header-cell>
- <mat-cell *matCellDef="let i = index" class="index-column"> {{i+1+pageSize*pageIndex}} </mat-cell>
- </ng-container>
-
- <!-- Lab Column -->
- <ng-container matColumnDef="name">
- <mat-header-cell *matHeaderCellDef>Lab</mat-header-cell>
- <mat-cell *matCellDef="let host"> {{host.name}} </mat-cell>
- </ng-container>
-
- <!-- Hostname Column -->
- <ng-container matColumnDef="hostname">
- <mat-header-cell *matHeaderCellDef>Hostname</mat-header-cell>
- <mat-cell *matCellDef="let host"> {{host.hostname}} </mat-cell>
- </ng-container>
-
- <!-- IP Column -->
- <ng-container matColumnDef="ip">
- <mat-header-cell *matHeaderCellDef>IP</mat-header-cell>
- <mat-cell *matCellDef="let host"> {{host.ip}} </mat-cell>
- </ng-container>
-
- <!-- Host Equipment Column -->
- <ng-container matColumnDef="host_equipment">
- <mat-header-cell *matHeaderCellDef>Equipment</mat-header-cell>
- <mat-cell *matCellDef="let host"> {{host.host_equipment}} </mat-cell>
- </ng-container>
-
- <!-- Version Column -->
- <ng-container matColumnDef="vtslab_version">
- <mat-header-cell *matHeaderCellDef>Version</mat-header-cell>
- <mat-cell *matCellDef="let host"> {{host.vtslab_version}} </mat-cell>
- </ng-container>
-
- <mat-header-row *matHeaderRowDef="hostColumnTitles"></mat-header-row>
- <mat-row *matRowDef="let row; columns: hostColumnTitles;"></mat-row>
- </mat-table>
- <mat-paginator [length]="count"
- [pageSizeOptions]="pageSizeOptions"
- [pageIndex]="labPageIndex">
- </mat-paginator>
- </div>
- </mat-tab>
-</mat-tab-group>
-<div class="loading-spinner" *ngIf="loading">
- <mat-spinner color="primary"></mat-spinner>
-</div>
diff --git a/gae/frontend/src/app/menu/lab/lab.component.scss b/gae/frontend/src/app/menu/lab/lab.component.scss
deleted file mode 100644
index fed2fb6..0000000
--- a/gae/frontend/src/app/menu/lab/lab.component.scss
+++ /dev/null
@@ -1,41 +0,0 @@
-.mat-table {
- overflow: auto;
-}
-
-.entity-table {
- display: flex;
- flex-direction: column;
-}
-
-.mat-header-cell {
- padding: 0 10px 0 10px;
-}
-
-.index-column {
- max-width: 40px;
-}
-
-.mat-cell {
- padding: 0 10px 0 10px;
-}
-
-.element-row {
- position: relative;
- overflow: hidden;
-}
-
-.element-row:not(.expanded) {
- cursor: pointer;
-}
-
-.element-row:not(.expanded):hover {
- background: #f5f5f5;
-}
-
-.element-row.expanded {
- border-bottom-color: transparent;
-}
-
-.div-expandable {
- padding: 10px 20px 30px 20px;
-}
diff --git a/gae/frontend/src/app/menu/lab/lab.component.ts b/gae/frontend/src/app/menu/lab/lab.component.ts
deleted file mode 100644
index bb7543b..0000000
--- a/gae/frontend/src/app/menu/lab/lab.component.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit } from '@angular/core';
-import { MatSnackBar, MatTableDataSource, PageEvent } from '@angular/material';
-
-import { AppService } from '../../appservice';
-import { Host } from '../../model/host';
-import { Lab } from '../../model/lab';
-import { LabService } from './lab.service';
-import { MenuBaseClass } from '../menu_base';
-
-/** Component that handles lab and host menu. */
-@Component({
- selector: 'app-lab',
- templateUrl: './lab.component.html',
- providers: [ LabService ],
- styleUrls: ['./lab.component.scss'],
-})
-export class LabComponent extends MenuBaseClass implements OnInit {
- labColumnTitles = [
- '_index',
- 'name',
- 'owner',
- 'admin',
- 'hostCount',
- ];
- hostColumnTitles = [
- '_index',
- 'name',
- 'hostname',
- 'ip',
- 'host_equipment',
- 'vtslab_version',
- ];
- labCount = -1;
- labPageIndex = 0;
-
- constructor(private labService: LabService,
- appService: AppService,
- snackBar: MatSnackBar) {
- super(appService, snackBar);
- }
-
- labDataSource = new MatTableDataSource<Lab>();
- hostDataSource = new MatTableDataSource<Host>();
-
- ngOnInit(): void {
- // For labs and hosts, it does not use query pagination.
- this.getHosts();
- }
-
- /** Gets hosts.
- * @param size A number, at most this many results will be returned.
- * @param offset A Number of results to skip.
- */
- getHosts(size = 0, offset = 0) {
- this.loading = true;
- // Labs will not use filter for query.
- const filterJSON = '';
- this.labService.getLabs(size, offset, filterJSON, '', '')
- .subscribe(
- (response) => {
- this.loading = false;
- if (response.labs) {
- this.count = response.labs.length;
- this.hostDataSource.data = response.labs;
- this.setLabs(response.labs);
- }
- },
- (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
- );
- }
-
- /** Sets labs from given hosts.
- * @param hosts A list of Host instances.
- */
- setLabs(hosts: Host[]) {
- if (hosts == null || hosts.length === 0) { return; }
- const labMap = new Map();
- hosts.forEach(function(host) {
- if (labMap.has(host.name)) {
- labMap.get(host.name).hosts.push(host);
- } else {
- labMap.set(host.name, {name: host.name, owner: host.owner, admin: host.admin, hosts: [host]});
- }
- });
- const labs: Lab[] = [];
- labMap.forEach((value) => labs.push(value));
- this.labDataSource.data = labs;
- }
-}
diff --git a/gae/frontend/src/app/menu/lab/lab.service.ts b/gae/frontend/src/app/menu/lab/lab.service.ts
deleted file mode 100644
index 2d677b1..0000000
--- a/gae/frontend/src/app/menu/lab/lab.service.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-
-import { catchError } from 'rxjs/operators';
-import { Observable } from 'rxjs';
-
-import { environment } from '../../../environments/environment';
-import { HostWrapper } from '../../model/host_wrapper';
-import { ServiceBase } from '../../shared/servicebase';
-
-
-@Injectable()
-export class LabService extends ServiceBase {
- // url: string;
- constructor(public httpClient: HttpClient) {
- super(httpClient);
- this.url = environment['baseURL'] + '/lab/v1/';
- }
-
- getLabs(size: number,
- offset: number,
- filterInfo: string,
- sort: string,
- direction: string): Observable<HostWrapper> {
- const url = this.url + 'get';
- return this.httpClient.post<HostWrapper>(url, {size: size, offset: offset, filter: filterInfo, sort: sort, direction: direction})
- .pipe(catchError(this.handleError));
- }
-}
diff --git a/gae/frontend/src/app/menu/menu-items.ts b/gae/frontend/src/app/menu/menu-items.ts
deleted file mode 100644
index a544366..0000000
--- a/gae/frontend/src/app/menu/menu-items.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export const MENUS = {
- ['VTSLab Scheduler']: '/',
- ['build']: '/build',
- ['device']: '/device',
- ['lab']: '/lab',
- ['schedule']: '/schedule',
- ['job']: '/job',
-};
diff --git a/gae/frontend/src/app/menu/menu_base.ts b/gae/frontend/src/app/menu/menu_base.ts
deleted file mode 100644
index 4d68f03..0000000
--- a/gae/frontend/src/app/menu/menu_base.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/** This class defines and/or implements the common properties and methods
- * used among menus.
- */
-import { AppService } from '../appservice';
-import { MatSnackBar } from '@angular/material';
-import moment from 'moment-timezone';
-
-
-export abstract class MenuBaseClass {
- count = -1;
-
- loading = false;
- pageSizeOptions = [20, 50, 100, 200];
- pageSize = 100;
- pageIndex = 0;
-
- protected constructor(private appService: AppService,
- public snackBar: MatSnackBar) {
- this.appService.closeSideNav();
- this.snackBar.dismiss();
- }
-
- /** Returns an Observable which handles a response of count API.
- * @param additionalOperations A list of lambda functions.
- */
- getDefaultCountObservable(additionalOperations: any[] = []) {
- return {
- next: (response) => {
- this.count = response.count;
- for (const operation of additionalOperations) {
- operation(response);
- }
- },
- error: (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
- };
- }
-
- getRelativeTime(timeString) {
- return (moment.tz(timeString, 'YYYY-MM-DDThh:mm:ss', 'UTC').isValid() ?
- moment.tz(timeString, 'YYYY-MM-DDThh:mm:ss', 'UTC').fromNow() : '---');
- }
-
- /** Checks whether timeString is expired from current time. */
- isExpired(timeString, hours=72) {
- let currentTime = moment.tz(timeString, 'YYYY-MM-DDThh:mm:ss', 'UTC');
- if (!currentTime.isValid()) { return false; }
-
- let diff = moment().diff(currentTime);
- let duration = moment.duration(diff);
- return duration.asHours() > hours;
- }
-
- /** Displays a snackbar notification. */
- showSnackbar(message = 'Error', duration = 5000) {
- this.loading = false;
- this.snackBar.open(message, 'DISMISS', {duration});
- }
-
- /** Displays a side nav window and lists all properties of selected entity. */
- onShowDetailsClicked(entity) {
- this.appService.showDetails(entity);
- }
-}
diff --git a/gae/frontend/src/app/menu/schedule/_schedule-theme.scss b/gae/frontend/src/app/menu/schedule/_schedule-theme.scss
deleted file mode 100644
index 084f1fb..0000000
--- a/gae/frontend/src/app/menu/schedule/_schedule-theme.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-@mixin schedule-theme($theme) {
- $primary: map-get($theme, primary);
- $accent: map-get($theme, accent);
- $warn: map-get($theme, warn);
- $background: map-get($theme, background);
- $foreground: map-get($theme, foreground);
-}
diff --git a/gae/frontend/src/app/menu/schedule/schedule.component.html b/gae/frontend/src/app/menu/schedule/schedule.component.html
deleted file mode 100644
index 910d45b..0000000
--- a/gae/frontend/src/app/menu/schedule/schedule.component.html
+++ /dev/null
@@ -1,121 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<div class="entity-filter">
- <app-filter (applyFilters)="applyFilters($event)" [disabled]="loading"></app-filter>
-</div>
-<div class="mat-elevation-z2 entity-table" [ngStyle]="{'opacity': (loading) ? 0.2 : 1 }">
- <mat-table [dataSource]="dataSource">
- <!-- Index Column -->
- <ng-container matColumnDef="_index">
- <mat-header-cell *matHeaderCellDef>No.</mat-header-cell>
- <mat-cell *matCellDef="let i = index"> {{i+1+pageSize*pageIndex}} </mat-cell>
- </ng-container>
-
- <!-- Test Name Column -->
- <ng-container matColumnDef="test_name">
- <mat-header-cell *matHeaderCellDef>Test Name</mat-header-cell>
- <mat-cell *matCellDef="let schedule"> {{schedule.test_name}} </mat-cell>
- </ng-container>
-
- <!-- Device Column -->
- <ng-container matColumnDef="device">
- <mat-header-cell *matHeaderCellDef>Device</mat-header-cell>
- <mat-cell *matCellDef="let schedule"> {{schedule.device ? schedule.device.join('\n') : ""}} </mat-cell>
- </ng-container>
-
- <!-- Manifest Branch Column -->
- <ng-container matColumnDef="manifest_branch">
- <mat-header-cell *matHeaderCellDef>Manifest Branch</mat-header-cell>
- <mat-cell *matCellDef="let schedule"> {{schedule.manifest_branch}}</mat-cell>
- </ng-container>
-
- <!-- Build Target Column -->
- <ng-container matColumnDef="build_target">
- <mat-header-cell *matHeaderCellDef>Build Target</mat-header-cell>
- <mat-cell *matCellDef="let schedule"> {{schedule.build_target}} </mat-cell>
- </ng-container>
-
- <!-- GSI Branch Column -->
- <ng-container matColumnDef="gsi_branch">
- <mat-header-cell *matHeaderCellDef>GSI Branch</mat-header-cell>
- <mat-cell *matCellDef="let schedule"> {{schedule.gsi_branch}} </mat-cell>
- </ng-container>
-
- <!-- GSI Build Target Column -->
- <ng-container matColumnDef="gsi_build_target">
- <mat-header-cell *matHeaderCellDef>GSI Build Target</mat-header-cell>
- <mat-cell *matCellDef="let schedule"> {{schedule.gsi_build_target}} </mat-cell>
- </ng-container>
-
- <!-- Test Branch Column -->
- <ng-container matColumnDef="test_branch">
- <mat-header-cell *matHeaderCellDef>Test Branch</mat-header-cell>
- <mat-cell *matCellDef="let schedule"> {{schedule.test_branch}} </mat-cell>
- </ng-container>
-
- <!-- Test Build Target Column -->
- <ng-container matColumnDef="test_build_target">
- <mat-header-cell *matHeaderCellDef>Test Build Target</mat-header-cell>
- <mat-cell *matCellDef="let schedule"> {{schedule.test_build_target}}</mat-cell>
- </ng-container>
-
- <!-- Period Column -->
- <ng-container matColumnDef="period">
- <mat-header-cell *matHeaderCellDef>Period</mat-header-cell>
- <mat-cell *matCellDef="let schedule"> {{schedule.period}}</mat-cell>
- </ng-container>
-
- <!-- Status Column -->
- <ng-container matColumnDef="status">
- <mat-header-cell *matHeaderCellDef>Status</mat-header-cell>
- <mat-cell *matCellDef="let schedule"
- [ngStyle]="{color: (schedule.suspended || isExpired(schedule.timestamp)) ? '#FF0000' : '#000000'}">
- {{schedule.suspended ? "Suspended" : (isExpired(schedule.timestamp) ? "Expired" : "Active")}}
- </mat-cell>
- </ng-container>
-
- <!-- Timestamp Column -->
- <ng-container matColumnDef="timestamp">
- <mat-header-cell *matHeaderCellDef>Timestamp</mat-header-cell>
- <mat-cell *matCellDef="let schedule"> {{getRelativeTime(schedule.timestamp)}}</mat-cell>
- </ng-container>
-
- <mat-header-row *matHeaderRowDef="columnTitles"></mat-header-row>
- <mat-row *matRowDef="let row; columns: columnTitles;"
- matRipple
- class="element-row"
- [appCdkDetailRow]="row" [appCdkDetailRowTpl]="schedule_detail"></mat-row>
- </mat-table>
-
- <mat-paginator [length]="count"
- [pageSize]="pageSize"
- [pageSizeOptions]="pageSizeOptions"
- [pageIndex]="pageIndex"
- (page)="pageEvent = onPageEvent($event)">
- </mat-paginator>
-</div>
-<ng-template #schedule_detail let-schedule>
- <div class="mat-row div-expandable" [@detailExpand] style="overflow: hidden">
- <button mat-raised-button (click)="suspendSchedule([{urlsafe_key: schedule.urlsafe_key, suspend: !schedule.suspended}])">
- {{(schedule.suspended ? "Resume" : "Suspend")}}
- </button>
- <button mat-raised-button (click)="onShowDetailsClicked(schedule)">
- Show Details
- </button>
- </div>
-</ng-template>
-<div class="loading-spinner" *ngIf="loading">
- <mat-spinner color="primary"></mat-spinner>
-</div>
diff --git a/gae/frontend/src/app/menu/schedule/schedule.component.scss b/gae/frontend/src/app/menu/schedule/schedule.component.scss
deleted file mode 100644
index c8aee00..0000000
--- a/gae/frontend/src/app/menu/schedule/schedule.component.scss
+++ /dev/null
@@ -1,24 +0,0 @@
-.mat-header-cell {
- padding: 0 10px 0 10px;
-}
-
-.mat-cell {
- padding: 0 10px 0 10px;
-}
-
-.element-row {
- position: relative;
- overflow: hidden;
-}
-
-.element-row:not(.expanded) {
- cursor: pointer;
-}
-
-.element-row:not(.expanded):hover {
- background: #f5f5f5;
-}
-
-.element-row.expanded {
- border-bottom-color: transparent;
-}
diff --git a/gae/frontend/src/app/menu/schedule/schedule.component.ts b/gae/frontend/src/app/menu/schedule/schedule.component.ts
deleted file mode 100644
index 5c1740e..0000000
--- a/gae/frontend/src/app/menu/schedule/schedule.component.ts
+++ /dev/null
@@ -1,160 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { MatSnackBar, MatTableDataSource, PageEvent } from '@angular/material';
-import { animate, state, style, transition, trigger } from "@angular/animations";
-
-import { AppService } from '../../appservice';
-import { FilterComponent } from '../../shared/filter/filter.component';
-import { FilterItem } from '../../model/filter_item';
-import { MenuBaseClass } from '../menu_base';
-import { Schedule, ScheduleSuspendResponse } from '../../model/schedule';
-import { ScheduleService } from './schedule.service';
-
-
-/** Component that handles schedule menu. */
-@Component({
- selector: 'app-schedule',
- templateUrl: './schedule.component.html',
- providers: [ ScheduleService ],
- styleUrls: ['./schedule.component.scss'],
- animations: [
- trigger('detailExpand', [
- state('void', style({height: '0px', minHeight: '0', visibility: 'hidden'})),
- state('*', style({height: '*', visibility: 'visible'})),
- transition('void <=> *', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
- ]),
- ],
-})
-export class ScheduleComponent extends MenuBaseClass implements OnInit {
- columnTitles = [
- '_index',
- 'test_name',
- 'device',
- 'manifest_branch',
- 'build_target',
- 'gsi_branch',
- 'gsi_build_target',
- 'test_branch',
- 'test_build_target',
- 'period',
- 'status',
- 'timestamp',
- ];
- dataSource = new MatTableDataSource<Schedule>();
- pageEvent: PageEvent;
- appliedFilters: FilterItem[];
-
- @ViewChild(FilterComponent) filterComponent: FilterComponent;
-
- constructor(private scheduleService: ScheduleService,
- appService: AppService,
- snackBar: MatSnackBar) {
- super(appService, snackBar);
- }
-
- ngOnInit(): void {
- this.filterComponent.setSelectorList(Schedule);
- this.getCount();
- this.getSchedules(this.pageSize, this.pageSize * this.pageIndex);
- }
-
- /** Gets a total count of schedules. */
- getCount(observer = this.getDefaultCountObservable()) {
- const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
- this.scheduleService.getCount(filterJSON).subscribe(observer);
- }
-
- /** Gets schedules.
- * @param size A number, at most this many results will be returned.
- * @param offset A Number of results to skip.
- */
- getSchedules(size = 0, offset = 0) {
- this.loading = true;
- const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : '';
- this.scheduleService.getSchedules(size, offset, filterJSON, '', '')
- .subscribe(
- (response) => {
- this.loading = false;
- if (this.count >= 0) {
- let length = 0;
- if (response.schedules) {
- length = response.schedules.length;
- }
- const total = length + offset;
- if (response.has_next) {
- if (length !== this.pageSize) {
- this.showSnackbar('Received unexpected number of entities.');
- } else if (this.count <= total) {
- this.getCount();
- }
- } else {
- if (this.count !== total) {
- if (length !== this.count) {
- this.getCount();
- } else if (this.count > total) {
- const countObservable = this.getDefaultCountObservable([
- () => {
- this.pageIndex = Math.floor(this.count / this.pageSize);
- this.getSchedules(this.pageSize, this.pageSize * this.pageIndex);
- }
- ]);
- this.getCount(countObservable);
- }
- }
- }
- }
- this.dataSource.data = response.schedules;
- },
- (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
- );
- }
-
- /** Toggles a schedule from suspend to resume, or vice versa. */
- suspendSchedule(schedules: ScheduleSuspendResponse[]) {
- this.scheduleService.suspendSchedule(schedules)
- .subscribe(
- (response) => {
- if (response.schedules) {
- let self = this;
- response.schedules.forEach(function(schedule) {
- const original = self.dataSource.data.filter(x => x.urlsafe_key === schedule.urlsafe_key);
- if (original) {
- original[0].suspended = schedule.suspend;
- }
- })
- }
- },
- (error) => this.showSnackbar(`[${error.status}] ${error.name}`)
- );
- }
-
- /** Hooks a page event and handles properly. */
- onPageEvent(event: PageEvent) {
- this.pageSize = event.pageSize;
- this.pageIndex = event.pageIndex;
- this.getSchedules(this.pageSize, this.pageSize * this.pageIndex);
- return event;
- }
-
- /** Applies a filter and get entities with it. */
- applyFilters(filters) {
- this.pageIndex = 0;
- this.appliedFilters = filters;
- this.getCount();
- this.getSchedules(this.pageSize, this.pageSize * this.pageIndex);
- }
-}
diff --git a/gae/frontend/src/app/menu/schedule/schedule.service.ts b/gae/frontend/src/app/menu/schedule/schedule.service.ts
deleted file mode 100644
index ae534dd..0000000
--- a/gae/frontend/src/app/menu/schedule/schedule.service.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-
-import { catchError } from 'rxjs/operators';
-import { Observable } from 'rxjs';
-
-import { environment } from '../../../environments/environment';
-import { ScheduleWrapper } from '../../model/schedule_wrapper';
-import { ServiceBase } from '../../shared/servicebase';
-import { ScheduleSuspendResponse, ScheduleSuspendResponseWrapper } from '../../model/schedule';
-
-
-@Injectable()
-export class ScheduleService extends ServiceBase {
- // url: string;
- constructor(public httpClient: HttpClient) {
- super(httpClient);
- this.url = environment['baseURL'] + '/schedule/v1/';
- }
-
- getSchedules(size: number,
- offset: number,
- filterInfo: string,
- sort: string,
- direction: string): Observable<ScheduleWrapper> {
- const url = this.url + 'get';
- return this.httpClient.post<ScheduleWrapper>(url, {size: size, offset: offset, filter: filterInfo, sort: sort, direction: direction})
- .pipe(catchError(this.handleError));
- }
-
- suspendSchedule(schedules: ScheduleSuspendResponse[]): Observable<ScheduleSuspendResponseWrapper> {
- const url = this.url + 'suspend';
- return this.httpClient.post<ScheduleSuspendResponseWrapper>(url, {schedules: schedules})
- .pipe(catchError(this.handleError));
- }
-}
diff --git a/gae/frontend/src/app/model/build.ts b/gae/frontend/src/app/model/build.ts
deleted file mode 100644
index bf32a4a..0000000
--- a/gae/frontend/src/app/model/build.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export class Build {
- manifest_branch: string = void 0;
- build_id: string = void 0;
- build_target: string = void 0;
- build_type: string = void 0;
- artifact_type: string = void 0;
- artifacts: string[] = void 0;
- signed: boolean = void 0;
- timestamp: any = void 0;
-}
diff --git a/gae/frontend/src/app/model/build_wrapper.ts b/gae/frontend/src/app/model/build_wrapper.ts
deleted file mode 100644
index 797d097..0000000
--- a/gae/frontend/src/app/model/build_wrapper.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Build} from './build';
-
-export interface BuildWrapper {
- builds: Build[];
- has_next: boolean;
-}
diff --git a/gae/frontend/src/app/model/device.ts b/gae/frontend/src/app/model/device.ts
deleted file mode 100644
index 21fdfb7..0000000
--- a/gae/frontend/src/app/model/device.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export class Device {
- serial: string = void 0;
- product: string = void 0;
- status: number = void 0;
- scheduling_status: number = void 0;
- hostname: string = void 0;
- device_equipment: string[] = void 0;
- timestamp: any = void 0;
-}
diff --git a/gae/frontend/src/app/model/device_wrapper.ts b/gae/frontend/src/app/model/device_wrapper.ts
deleted file mode 100644
index af18dce..0000000
--- a/gae/frontend/src/app/model/device_wrapper.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Device} from './device';
-
-export interface DeviceWrapper {
- devices: Device[];
- has_next: boolean;
-}
diff --git a/gae/frontend/src/app/model/filter_condition.ts b/gae/frontend/src/app/model/filter_condition.ts
deleted file mode 100644
index 9f76de9..0000000
--- a/gae/frontend/src/app/model/filter_condition.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export enum FilterCondition {
- EqualTo = 1,
- LessThan,
- GreaterThan,
- LessThanOrEqualTo,
- GreaterThanOrEqualTo,
- NotEqualTo,
- Has,
-}
diff --git a/gae/frontend/src/app/model/filter_item.ts b/gae/frontend/src/app/model/filter_item.ts
deleted file mode 100644
index de457a1..0000000
--- a/gae/frontend/src/app/model/filter_item.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {FilterCondition} from './filter_condition';
-
-export class FilterItem {
- key: string;
- method: FilterCondition;
- value: string; // back-end should handle type-casting.
-}
diff --git a/gae/frontend/src/app/model/host.ts b/gae/frontend/src/app/model/host.ts
deleted file mode 100644
index 3836c30..0000000
--- a/gae/frontend/src/app/model/host.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export class Host {
- name: string = void 0; // lab name
- owner: string = void 0;
- admin: string[] = void 0;
- hostname: string = void 0;
- ip: string = void 0;
- devices: string = void 0;
- vtslab_version: string = void 0;
- host_equipment: string[] = void 0;
-}
diff --git a/gae/frontend/src/app/model/host_wrapper.ts b/gae/frontend/src/app/model/host_wrapper.ts
deleted file mode 100644
index ae18a04..0000000
--- a/gae/frontend/src/app/model/host_wrapper.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Host} from './host';
-
-export interface HostWrapper {
- // Back-end stores each host information as LabModel entity, so it sends
- // host information as 'labs'.
- labs: Host[];
- has_next: boolean;
-}
diff --git a/gae/frontend/src/app/model/job.ts b/gae/frontend/src/app/model/job.ts
deleted file mode 100644
index 69e45b7..0000000
--- a/gae/frontend/src/app/model/job.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export class Job {
- test_type: number = void 0;
-
- hostname: string = void 0;
- priority: string = void 0;
- test_name: string = void 0;
- require_signed_device_build: boolean = void 0;
- has_bootloader_img: boolean = void 0;
- has_radio_img: boolean = void 0;
- device: string = void 0;
- serial: string = void 0;
-
- // device image information
- build_storage_type: number = void 0;
- manifest_branch: string = void 0;
- build_target: string = void 0;
- build_id: string = void 0;
- pab_account_id: string = void 0;
-
- shards: number = void 0;
- param: string = void 0;
- status: number = void 0;
- period: number = void 0;
-
- // GSI information
- gsi_storage_type: number = void 0;
- gsi_branch: string = void 0;
- gsi_build_target: string = void 0;
- gsi_build_id: string = void 0;
- gsi_pab_account_id: string = void 0;
- gsi_vendor_version: string = void 0;
-
- // test suite information
- test_storage_type: number = void 0;
- test_branch: string = void 0;
- test_build_target: string = void 0;
- test_build_id: string = void 0;
- test_pab_account_id: string = void 0;
-
- retry_count: number = void 0;
-
- infra_log_url: string = void 0;
-
- image_package_repo_base: string = void 0;
-
- report_bucket: string = void 0;
- report_spreadsheet_id: string = void 0;
-
- timestamp = void 0;
- heartbeat_stamp = void 0;
-}
diff --git a/gae/frontend/src/app/model/job_wrapper.ts b/gae/frontend/src/app/model/job_wrapper.ts
deleted file mode 100644
index 5a1f915..0000000
--- a/gae/frontend/src/app/model/job_wrapper.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Job} from './job';
-
-export interface JobWrapper {
- jobs: Job[];
- has_next: boolean;
-}
diff --git a/gae/frontend/src/app/model/lab.ts b/gae/frontend/src/app/model/lab.ts
deleted file mode 100644
index 0f98360..0000000
--- a/gae/frontend/src/app/model/lab.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Host} from './host';
-
-export class Lab {
- name: string = void 0;
- owner: string = void 0;
- admin: string[] = void 0;
- hosts: Host[] = void 0;
-}
diff --git a/gae/frontend/src/app/model/schedule.ts b/gae/frontend/src/app/model/schedule.ts
deleted file mode 100644
index 9115a97..0000000
--- a/gae/frontend/src/app/model/schedule.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export class Schedule {
- name: string = void 0;
- schedule_type: string = void 0;
-
- // device image information
- build_storage_type: number = void 0;
- manifest_branch: string = void 0;
- build_target: string = void 0;
- device_pab_account_id: string = void 0;
- require_signed_device_build: boolean = void 0;
- has_bootloader_img: boolean = void 0;
- has_radio_img: boolean = void 0;
-
- // GSI information
- gsi_storage_type: number = void 0;
- gsi_branch: string = void 0;
- gsi_build_target: string = void 0;
- gsi_pab_account_id: string = void 0;
- gsi_vendor_version: string = void 0;
-
- // test suite information
- test_storage_type: number = void 0;
- test_branch: string = void 0;
- test_build_target: string = void 0;
- test_pab_account_id: string = void 0;
-
- test_name: string = void 0;
- period: number = void 0;
- schedule: string = void 0;
- priority: string = void 0;
- device: string[] = void 0;
- shards: number = void 0;
- param: string[] = void 0;
- retry_count: number = void 0;
-
- required_host_equipment: string[] = void 0;
- required_device_equipment: string[] = void 0;
-
- report_bucket: string[] = void 0;
- report_spreadsheet_id: string[] = void 0;
- report_persistent_url: string[] = void 0;
- report_reference_url: string[] = void 0;
-
- image_package_repo_base: string = void 0;
- timestamp = void 0;
- owner: string[] = void 0;
-
- error_count: number = void 0;
- suspended: boolean = void 0;
- urlsafe_key: string = void 0;
-}
-
-export interface ScheduleSuspendResponseWrapper {
- schedules: ScheduleSuspendResponse[];
-}
-
-export interface ScheduleSuspendResponse {
- urlsafe_key: string;
- suspend: boolean;
-}
diff --git a/gae/frontend/src/app/model/schedule_wrapper.ts b/gae/frontend/src/app/model/schedule_wrapper.ts
deleted file mode 100644
index 2dae800..0000000
--- a/gae/frontend/src/app/model/schedule_wrapper.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Schedule} from './schedule';
-
-export interface ScheduleWrapper {
- schedules: Schedule[];
- has_next: boolean;
-}
diff --git a/gae/frontend/src/app/model/tslint.json b/gae/frontend/src/app/model/tslint.json
deleted file mode 100644
index eb9bcd8..0000000
--- a/gae/frontend/src/app/model/tslint.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "../../tslint.json",
- "rules": {
- "variable-name": [
- true,
- "allow-snake-case"
- ]
- }
-}
diff --git a/gae/frontend/src/app/shared/dict.pipe.ts b/gae/frontend/src/app/shared/dict.pipe.ts
deleted file mode 100644
index 44f5933..0000000
--- a/gae/frontend/src/app/shared/dict.pipe.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {Pipe, PipeTransform} from '@angular/core';
-
-@Pipe({name: 'dict'})
-export class DictPipe implements PipeTransform {
- transform(value: Object): any {
- const dict = [];
- for (const key in value) {
- if (value.hasOwnProperty(key)) {
- dict.push({key: key, value: value[key]});
- }
- }
- return dict;
- }
-}
diff --git a/gae/frontend/src/app/shared/filter/filter.component.html b/gae/frontend/src/app/shared/filter/filter.component.html
deleted file mode 100644
index 7381359..0000000
--- a/gae/frontend/src/app/shared/filter/filter.component.html
+++ /dev/null
@@ -1,66 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<div fxLayout="column" id="filter-wrapper">
- <mat-expansion-panel id="expansion-panel" (opened)="panelOpenState = true" (closed)="panelOpenState = false" [ngStyle]="{'padding-bottom': (panelOpenState) ? '20px' : '0' }">
- <mat-expansion-panel-header>
- <mat-panel-title>
- Filter
- </mat-panel-title>
- <mat-panel-description>
- {{ panelOpenState ? "" : appliedFilters.length + " filters are applied." }}
- </mat-panel-description>
- </mat-expansion-panel-header>
- <mat-form-field>
- <mat-select placeholder="Key" [(value)]="currentFilter.key">
- <mat-option *ngFor="let key of selectorList" [value]="key">
- {{ key }}
- </mat-option>
- </mat-select>
- </mat-form-field>
- <mat-form-field>
- <mat-select [(value)]="currentFilter.method">
- <mat-option *ngFor="let method of filterMethods" [value]="method.value">
- {{ method.text }}
- </mat-option>
- </mat-select>
- </mat-form-field>
- <mat-form-field>
- <input matInput [(ngModel)]="currentFilter.value">
- </mat-form-field>
- <button mat-icon-button (click)="addFilter()" [disabled]="!currentFilter.key || !currentFilter.method || !currentFilter.value">
- <mat-icon>done</mat-icon>
- </button>
- <button mat-icon-button (click)="clearCurrentFilter()">
- <mat-icon>clear</mat-icon>
- </button>
- <mat-chip-list>
- <mat-chip *ngFor="let filter of applyingFilters" [removable]="true" (removed)="removed(filter)">
- {{ filter.key }} {{ getSign(filter) }} {{ filter.value }}
- <mat-icon matChipRemove>cancel</mat-icon>
- </mat-chip>
- </mat-chip-list>
- <div fxLayout="row" id="row_buttons">
- <button mat-stroked-button (click)="onApplyClicked()" [disabled]="!applyingFilterChanged">
- <span>Apply</span>
- </button>
- <button mat-stroked-button (click)="onCancelChangesClicked()" [disabled]="!applyingFilterChanged">
- <span>Cancel Changes</span>
- </button>
- <button mat-stroked-button (click)="onClearAllClicked()" [disabled]="appliedFilters.length == 0">
- <span>Clear All</span>
- </button>
- </div>
- </mat-expansion-panel>
-</div>
diff --git a/gae/frontend/src/app/shared/filter/filter.component.scss b/gae/frontend/src/app/shared/filter/filter.component.scss
deleted file mode 100644
index 88ae569..0000000
--- a/gae/frontend/src/app/shared/filter/filter.component.scss
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#filter-wrapper {
- position: relative;
-
- mat-form-field {
- margin-right: 20px;
- }
-}
-
-#row_buttons {
- float: right;
-}
-
-.mat-stroked-button {
- min-width: 80px;
- min-height: 15px;
- padding-left: 15px;
- padding-right: 15px;
- font-size: 12px;
- margin-right: 15px;
-}
diff --git a/gae/frontend/src/app/shared/filter/filter.component.ts b/gae/frontend/src/app/shared/filter/filter.component.ts
deleted file mode 100644
index 0ce66fe..0000000
--- a/gae/frontend/src/app/shared/filter/filter.component.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { FilterItem } from '../../model/filter_item';
-import { FilterCondition } from '../../model/filter_condition';
-
-@Component({
- selector: 'app-filter',
- templateUrl: './filter.component.html',
- styleUrls: ['./filter.component.scss']
-})
-export class FilterComponent implements OnInit {
- currentFilter: FilterItem;
- applyingFilters: FilterItem[] = [];
- applyingFilterChanged = false;
- appliedFilters: FilterItem[] = [];
- selectorList: string[];
-
- filterMethods = [
- {value: FilterCondition.EqualTo, text: 'is equal to', sign: '='},
- {value: FilterCondition.LessThan, text: 'is less than', sign: '<'},
- {value: FilterCondition.GreaterThan, text: 'is greater than', sign: '>'},
- {value: FilterCondition.LessThanOrEqualTo, text: 'is less than or equal to', sign: '<='},
- {value: FilterCondition.GreaterThanOrEqualTo, text: 'is greater than or equal to', sign: '>='},
- {value: FilterCondition.NotEqualTo, text: 'is not equal to', sign: '!='},
- {value: FilterCondition.Has, text: 'has', sign: 'has'},
- ];
-
- @Output() applyFilters = new EventEmitter();
- @Input() disabled: boolean;
-
- panelOpenState = false;
-
- ngOnInit(): void {
- this.currentFilter = new FilterItem();
- this.currentFilter.value = '';
- }
-
- /** Sets a filter key list with the given class. */
- setSelectorList(typeOfClass: any) {
- const instance = new typeOfClass();
- this.selectorList = Object.getOwnPropertyNames(instance);
- }
-
- /** Adds the current filter to the list of filters to be applied. */
- addFilter() {
- this.applyingFilters.push(this.currentFilter);
- this.currentFilter = new FilterItem();
- this.currentFilter.value = '';
- this.applyingFilterChanged = true;
- }
-
- /** Clears the current filter. */
- clearCurrentFilter() {
- this.currentFilter.key = undefined;
- this.currentFilter.method = undefined;
- this.currentFilter.value = '';
- }
-
- /** Removes the selected filter from the list of filters to be applied. */
- removed(filter: FilterItem) {
- const index = this.applyingFilters.indexOf(filter);
- if (index >= 0) {
- this.applyingFilters.splice(index, 1);
- this.applyingFilterChanged = true;
- }
- }
-
- /** Gets a filter sign with method value. */
- getSign(filter: FilterItem) {
- return this.filterMethods.find((x) => x.value === filter.method).sign;
- }
-
- /** Applies the list of filters. */
- onApplyClicked() {
- this.applyFilters.emit(this.applyingFilters);
- this.appliedFilters = this.applyingFilters.slice();
- this.applyingFilterChanged = false;
- }
-
- /** Cancels the current changes and roll back to the last applied filters. */
- onCancelChangesClicked() {
- this.applyingFilters = this.appliedFilters.slice();
- this.applyingFilterChanged = false;
- }
-
- /** Reset all filters. */
- onClearAllClicked() {
- this.applyingFilters = [];
- this.appliedFilters = [];
- this.applyFilters.emit(this.appliedFilters);
- this.applyingFilterChanged = false;
- }
-}
diff --git a/gae/frontend/src/app/shared/navbar/_navbar-theme.scss b/gae/frontend/src/app/shared/navbar/_navbar-theme.scss
deleted file mode 100644
index bba0989..0000000
--- a/gae/frontend/src/app/shared/navbar/_navbar-theme.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-@mixin nav-bar-theme($theme) {
- $primary: map-get($theme, primary);
- $accent: map-get($theme, accent);
- $warn: map-get($theme, warn);
- $background: map-get($theme, background);
- $foreground: map-get($theme, foreground);
-
- mat-toolbar.main-toolbar {
- .mat-list-item {
- color: mat-color($primary, '600-contrast') !important;
- }
- }
-}
diff --git a/gae/frontend/src/app/shared/navbar/navbar.component.html b/gae/frontend/src/app/shared/navbar/navbar.component.html
deleted file mode 100644
index 7719d56..0000000
--- a/gae/frontend/src/app/shared/navbar/navbar.component.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<mat-toolbar class="mat-elevation-z6 main-toolbar" color="primary">
- <mat-nav-list>
- <a mat-list-item *ngFor="let menu of (menus | dict)" [routerLink]="menu.value">{{ menu.key }}</a>
- </mat-nav-list>
- <span class="flex-spacer"></span>
-</mat-toolbar>
diff --git a/gae/frontend/src/app/shared/navbar/navbar.component.scss b/gae/frontend/src/app/shared/navbar/navbar.component.scss
deleted file mode 100644
index 5b6dc86..0000000
--- a/gae/frontend/src/app/shared/navbar/navbar.component.scss
+++ /dev/null
@@ -1,10 +0,0 @@
-mat-toolbar {
- .mat-list-item {
- font-family: 'Google Sans', Roboto, sans-serif;
- text-transform: capitalize;
- }
-}
-
-.mat-list-item {
- float: left;
-}
diff --git a/gae/frontend/src/app/shared/navbar/navbar.component.ts b/gae/frontend/src/app/shared/navbar/navbar.component.ts
deleted file mode 100644
index 3efe93f..0000000
--- a/gae/frontend/src/app/shared/navbar/navbar.component.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { Component } from '@angular/core';
-
-import { MENUS } from '../../menu/menu-items';
-
-@Component({
- selector: 'app-nav-bar',
- templateUrl: './navbar.component.html',
- styleUrls: ['./navbar.component.scss']
-})
-export class NavBarComponent {
- get menus() {
- return MENUS;
- }
-}
diff --git a/gae/frontend/src/app/shared/navbar/navbar.ts b/gae/frontend/src/app/shared/navbar/navbar.ts
deleted file mode 100644
index 805dcc5..0000000
--- a/gae/frontend/src/app/shared/navbar/navbar.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// Angular modules.
-import { BrowserModule } from '@angular/platform-browser';
-import { NgModule } from '@angular/core';
-import { RouterModule } from '@angular/router';
-
-// Angular Material modules.
-import { MatButtonModule } from '@angular/material/button';
-import { MatListModule } from '@angular/material/list';
-import { MatToolbarModule } from '@angular/material/toolbar';
-
-// User modules.
-import { DictPipe } from '../dict.pipe';
-import { NavBarComponent } from './navbar.component';
-
-@NgModule({
- declarations: [
- DictPipe,
- NavBarComponent,
- ],
- imports: [
- BrowserModule,
- MatButtonModule,
- MatToolbarModule,
- MatListModule,
- RouterModule,
- ],
- exports: [
- NavBarComponent,
- ],
- providers: [],
-})
-export class NavModule { }
diff --git a/gae/frontend/src/app/shared/servicebase.ts b/gae/frontend/src/app/shared/servicebase.ts
deleted file mode 100644
index 9eaecf8..0000000
--- a/gae/frontend/src/app/shared/servicebase.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { HttpClient, HttpErrorResponse, HttpParams, HttpResponse } from '@angular/common/http';
-import { Observable, throwError } from 'rxjs';
-
-export class ServiceBase {
- url: string;
- protected constructor(public httpClient: HttpClient) {
- }
- protected handleError(error: HttpErrorResponse) {
- if (error.error instanceof ErrorEvent) {
- // A client-side or network error occurred. Handle it accordingly.
- console.error('An error occurred:', error.error.message);
- } else {
- // The backend returned an unsuccessful response code.
- // The response body may contain clues as to what went wrong,
- console.error(
- `Backend returned code ${error.status}, ` +
- `body was: ${error.error}`);
- }
- // return an observable with a user-facing error message
- return throwError(error);
- }
- public getCount(filterInfo: string): Observable<number> {
- const url = this.url + 'count';
- return this.httpClient.post<number>(url, {filter: filterInfo});
- }
-}
diff --git a/gae/frontend/src/app/shared/vtslab_status.ts b/gae/frontend/src/app/shared/vtslab_status.ts
deleted file mode 100644
index 2836f97..0000000
--- a/gae/frontend/src/app/shared/vtslab_status.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-export enum JobStatus {
- Ready = 0,
- Leased,
- Complete,
- Infra_err,
- Expired,
- Bootup_err,
-}
-
-export enum DeviceStatus {
- Unknown = 0,
- Fastboot,
- Online,
- Ready,
- Use,
- Error,
- No_response,
-}
-
-export enum SchedulingStatus {
- Free = 0,
- Reserved,
- Use,
-}
-
-/**
- * bit 0-1 : version related test type
- * 00 - Unknown
- * 01 - ToT
- * 10 - OTA
- * bit 2 : device signed build
- * bit 3-4 : reserved for gerrit related test type
- * 01 - pre-submit
- * bit 5 : manually created test job
- */
-export enum TestType {
- Unknown = 0,
- ToT = 1,
- OTA = 1 << 1,
- Signed = 1 << 2,
- Presubmit = 1 << 3,
- Manual = 1 << 5,
-}
diff --git a/gae/frontend/src/browserslist b/gae/frontend/src/browserslist
deleted file mode 100644
index 3206b4e..0000000
--- a/gae/frontend/src/browserslist
+++ /dev/null
@@ -1,5 +0,0 @@
-# For autoprefixer to adjust CSS to support the below specified browsers
-> 0.5%
-last 2 versions
-Firefox ESR
-not dead
diff --git a/gae/frontend/src/environments/environment.prod.ts b/gae/frontend/src/environments/environment.prod.ts
deleted file mode 100644
index 8b051e6..0000000
--- a/gae/frontend/src/environments/environment.prod.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export const environment = {
- production: true,
- baseURL: '/_ah/api',
-};
diff --git a/gae/frontend/src/environments/environment.ts b/gae/frontend/src/environments/environment.ts
deleted file mode 100644
index 387543e..0000000
--- a/gae/frontend/src/environments/environment.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export const environment = {
- production: false,
- baseURL: 'http://localhost:8080/_ah/api',
-};
diff --git a/gae/frontend/src/favicon.ico b/gae/frontend/src/favicon.ico
deleted file mode 100644
index 8081c7c..0000000
--- a/gae/frontend/src/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/gae/frontend/src/index.html b/gae/frontend/src/index.html
deleted file mode 100644
index 3234be2..0000000
--- a/gae/frontend/src/index.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<html lang="en">
-<head>
- <meta charset="utf-8">
- <title>VTSLab Scheduler</title>
- <base href="/">
-
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link rel="icon" type="image/x-icon" href="favicon.ico">
- <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
- <link href="https://fonts.googleapis.com/css?family=Google+Sans" rel="stylesheet">
-</head>
-<body>
- <app-root>Loading...</app-root>
-</body>
-</html>
diff --git a/gae/frontend/src/karma.conf.js b/gae/frontend/src/karma.conf.js
deleted file mode 100644
index b6e0042..0000000
--- a/gae/frontend/src/karma.conf.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// Karma configuration file, see link for more information
-// https://karma-runner.github.io/1.0/config/configuration-file.html
-
-module.exports = function (config) {
- config.set({
- basePath: '',
- frameworks: ['jasmine', '@angular-devkit/build-angular'],
- plugins: [
- require('karma-jasmine'),
- require('karma-chrome-launcher'),
- require('karma-jasmine-html-reporter'),
- require('karma-coverage-istanbul-reporter'),
- require('@angular-devkit/build-angular/plugins/karma')
- ],
- client: {
- clearContext: false // leave Jasmine Spec Runner output visible in browser
- },
- coverageIstanbulReporter: {
- dir: require('path').join(__dirname, '../coverage'),
- reports: ['html', 'lcovonly'],
- fixWebpackSourcePaths: true
- },
- reporters: ['progress', 'kjhtml'],
- port: 9876,
- colors: true,
- logLevel: config.LOG_INFO,
- autoWatch: true,
- browsers: ['Chrome'],
- singleRun: false
- });
-}; \ No newline at end of file
diff --git a/gae/frontend/src/main.ts b/gae/frontend/src/main.ts
deleted file mode 100644
index 91ec6da..0000000
--- a/gae/frontend/src/main.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { enableProdMode } from '@angular/core';
-import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
-
-import { AppModule } from './app/app.module';
-import { environment } from './environments/environment';
-
-if (environment.production) {
- enableProdMode();
-}
-
-platformBrowserDynamic().bootstrapModule(AppModule)
- .catch(err => console.log(err));
diff --git a/gae/frontend/src/polyfills.ts b/gae/frontend/src/polyfills.ts
deleted file mode 100644
index 25a0787..0000000
--- a/gae/frontend/src/polyfills.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-// Evergreen browsers require these.
-import 'core-js/es7/reflect';
-
-// Zone JS is required by default for Angular itself.
-import 'zone.js/dist/zone';
diff --git a/gae/frontend/src/styles.scss b/gae/frontend/src/styles.scss
deleted file mode 100644
index 574f294..0000000
--- a/gae/frontend/src/styles.scss
+++ /dev/null
@@ -1,54 +0,0 @@
-@import '~@angular/material/theming';
-@import 'styles/app-theme';
-
-body {
- margin: 0;
- font-family: Roboto, sans-serif;
-}
-
-.entity-filter {
- margin: 20px 20px 0 20px;
-
- filter {
- width: 100%;
- }
-}
-
-.statistics-table {
- margin: 10px 20px 20px 20px;
-
- table {
- width: 100%;
- }
-}
-
-.mat-card {
- margin: 20px;
-}
-
-.entity-table {
- margin: 10px 20px 20px 20px;
-
- table {
- width: 100%;
- }
-}
-
-.loading-spinner {
- display: flex;
- align-items: center;
- justify-content: center;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
- position: fixed;
-}
-
-.div-expandable {
- padding: 10px 20px 30px 20px;
-
- button {
- margin-right: 20px;
- }
-}
diff --git a/gae/frontend/src/styles/_app-theme.scss b/gae/frontend/src/styles/_app-theme.scss
deleted file mode 100644
index 6c18f48..0000000
--- a/gae/frontend/src/styles/_app-theme.scss
+++ /dev/null
@@ -1,14 +0,0 @@
-@import '~@angular/material/theming';
-@import 'apply-theme';
-@import 'blue-theme';
-
-@include mat-core();
-
-$main-theme: $blue-theme;
-
-$primary: mat-palette($main-theme, 600, 100, 900);
-$accent: mat-palette($main-theme, A200, A100, A400);
-$app-theme: mat-light-theme($primary, $accent);
-
-@include angular-material-theme($app-theme);
-@include apply-theme($app-theme);
diff --git a/gae/frontend/src/styles/_apply-theme.scss b/gae/frontend/src/styles/_apply-theme.scss
deleted file mode 100644
index fd5173f..0000000
--- a/gae/frontend/src/styles/_apply-theme.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-@import '../app/shared/navbar/navbar-theme';
-
-@mixin apply-theme($theme) {
- @include nav-bar-theme($theme);
-}
diff --git a/gae/frontend/src/styles/_blue-theme.scss b/gae/frontend/src/styles/_blue-theme.scss
deleted file mode 100644
index 53fd744..0000000
--- a/gae/frontend/src/styles/_blue-theme.scss
+++ /dev/null
@@ -1,34 +0,0 @@
-@import '~@angular/material/theming';
-
-$blue-theme: (
- 50: #e8f0fe,
- 100: #d2e3fc,
- 200: #a1c2fa,
- 300: #7baaf7,
- 400: #5e97f6,
- 500: #4285f4,
- 600: #1a73e8,
- 700: #1967d2,
- 800: #185abc,
- 900: #174ea6,
- A100: #82b1ff,
- A200: #448aff,
- A400: #2979ff,
- A700: #2962ff,
- contrast: (
- 50: #1a73e8,
- 100: #1a73e8,
- 200: $black-87-opacity,
- 300: $black-87-opacity,
- 400: $black-87-opacity,
- 500: white,
- 600: white,
- 700: white,
- 800: white,
- 900: white,
- A100: $black-87-opacity,
- A200: white,
- A400: white,
- A700: white,
- )
-);
diff --git a/gae/frontend/src/test.ts b/gae/frontend/src/test.ts
deleted file mode 100644
index 1631789..0000000
--- a/gae/frontend/src/test.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-// This file is required by karma.conf.js and loads recursively all the .spec and framework files
-
-import 'zone.js/dist/zone-testing';
-import { getTestBed } from '@angular/core/testing';
-import {
- BrowserDynamicTestingModule,
- platformBrowserDynamicTesting
-} from '@angular/platform-browser-dynamic/testing';
-
-declare const require: any;
-
-// First, initialize the Angular testing environment.
-getTestBed().initTestEnvironment(
- BrowserDynamicTestingModule,
- platformBrowserDynamicTesting()
-);
-// Then we find all the tests.
-const context = require.context('./', true, /\.spec\.ts$/);
-// And load the modules.
-context.keys().map(context);
diff --git a/gae/frontend/src/tsconfig.app.json b/gae/frontend/src/tsconfig.app.json
deleted file mode 100644
index 722c370..0000000
--- a/gae/frontend/src/tsconfig.app.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "extends": "../tsconfig.json",
- "compilerOptions": {
- "outDir": "../out-tsc/app",
- "module": "es2015",
- "types": []
- },
- "exclude": [
- "src/test.ts",
- "**/*.spec.ts"
- ]
-}
diff --git a/gae/frontend/src/tsconfig.spec.json b/gae/frontend/src/tsconfig.spec.json
deleted file mode 100644
index 8f7cede..0000000
--- a/gae/frontend/src/tsconfig.spec.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "extends": "../tsconfig.json",
- "compilerOptions": {
- "outDir": "../out-tsc/spec",
- "module": "commonjs",
- "types": [
- "jasmine",
- "node"
- ]
- },
- "files": [
- "test.ts",
- "polyfills.ts"
- ],
- "include": [
- "**/*.spec.ts",
- "**/*.d.ts"
- ]
-}
diff --git a/gae/frontend/src/tslint.json b/gae/frontend/src/tslint.json
deleted file mode 100644
index 52e2c1a..0000000
--- a/gae/frontend/src/tslint.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "extends": "../tslint.json",
- "rules": {
- "directive-selector": [
- true,
- "attribute",
- "app",
- "camelCase"
- ],
- "component-selector": [
- true,
- "element",
- "app",
- "kebab-case"
- ]
- }
-}
diff --git a/gae/frontend/tsconfig.json b/gae/frontend/tsconfig.json
deleted file mode 100644
index ef44e28..0000000
--- a/gae/frontend/tsconfig.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "compileOnSave": false,
- "compilerOptions": {
- "baseUrl": "./",
- "outDir": "./dist/out-tsc",
- "sourceMap": true,
- "declaration": false,
- "moduleResolution": "node",
- "emitDecoratorMetadata": true,
- "experimentalDecorators": true,
- "target": "es5",
- "typeRoots": [
- "node_modules/@types"
- ],
- "lib": [
- "es2017",
- "dom"
- ]
- }
-}
diff --git a/gae/frontend/tslint.json b/gae/frontend/tslint.json
deleted file mode 100644
index 259320f..0000000
--- a/gae/frontend/tslint.json
+++ /dev/null
@@ -1,130 +0,0 @@
-{
- "rulesDirectory": [
- "node_modules/codelyzer"
- ],
- "rules": {
- "arrow-return-shorthand": true,
- "callable-types": true,
- "class-name": true,
- "comment-format": [
- true,
- "check-space"
- ],
- "curly": true,
- "deprecation": {
- "severity": "warn"
- },
- "eofline": true,
- "forin": true,
- "import-blacklist": [
- true,
- "rxjs/Rx"
- ],
- "import-spacing": true,
- "indent": [
- true,
- "spaces"
- ],
- "interface-over-type-literal": true,
- "label-position": true,
- "max-line-length": [
- true,
- 140
- ],
- "member-access": false,
- "member-ordering": [
- true,
- {
- "order": [
- "static-field",
- "instance-field",
- "static-method",
- "instance-method"
- ]
- }
- ],
- "no-arg": true,
- "no-bitwise": false,
- "no-console": [
- true,
- "debug",
- "info",
- "time",
- "timeEnd",
- "trace"
- ],
- "no-construct": true,
- "no-debugger": true,
- "no-duplicate-super": true,
- "no-empty": false,
- "no-empty-interface": true,
- "no-eval": true,
- "no-inferrable-types": [
- true,
- "ignore-params"
- ],
- "no-misused-new": true,
- "no-non-null-assertion": true,
- "no-shadowed-variable": true,
- "no-string-literal": false,
- "no-string-throw": true,
- "no-switch-case-fall-through": true,
- "no-trailing-whitespace": true,
- "no-unnecessary-initializer": true,
- "no-unused-expression": true,
- "no-use-before-declare": true,
- "no-var-keyword": true,
- "object-literal-sort-keys": false,
- "one-line": [
- true,
- "check-open-brace",
- "check-catch",
- "check-else",
- "check-whitespace"
- ],
- "prefer-const": true,
- "quotemark": [
- true,
- "single"
- ],
- "radix": true,
- "semicolon": [
- true,
- "always"
- ],
- "triple-equals": [
- true,
- "allow-null-check"
- ],
- "typedef-whitespace": [
- true,
- {
- "call-signature": "nospace",
- "index-signature": "nospace",
- "parameter": "nospace",
- "property-declaration": "nospace",
- "variable-declaration": "nospace"
- }
- ],
- "unified-signatures": true,
- "variable-name": false,
- "whitespace": [
- true,
- "check-branch",
- "check-decl",
- "check-operator",
- "check-separator",
- "check-type"
- ],
- "no-output-on-prefix": true,
- "use-input-property-decorator": true,
- "use-output-property-decorator": true,
- "use-host-property-decorator": true,
- "no-input-rename": true,
- "no-output-rename": true,
- "use-life-cycle-interface": true,
- "use-pipe-transform-interface": true,
- "component-class-suffix": true,
- "directive-class-suffix": true
- }
-}
diff --git a/gae/hostv1openapi.json b/gae/hostv1openapi.json
deleted file mode 100644
index 35116b2..0000000
--- a/gae/hostv1openapi.json
+++ /dev/null
@@ -1,243 +0,0 @@
-{
- "basePath": "/_ah/api",
- "consumes": [
- "application/json"
- ],
- "definitions": {
- "WebappSrcProtoModelBuildInfoMessage": {
- "properties": {
- "artifact_type": {
- "type": "string"
- },
- "artifacts": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "build_id": {
- "type": "string"
- },
- "build_target": {
- "type": "string"
- },
- "build_type": {
- "type": "string"
- },
- "manifest_branch": {
- "type": "string"
- },
- "signed": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelBuildResponseMessage": {
- "properties": {
- "builds": {
- "description": "A message for representing an individual build entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/WebappSrcProtoModelBuildInfoMessage"
- },
- "type": "array"
- },
- "has_next": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelCountRequestMessage": {
- "properties": {
- "filter": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelCountResponseMessage": {
- "properties": {
- "count": {
- "format": "int64",
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDefaultResponse": {
- "properties": {
- "return_code": {
- "enum": [
- "SUCCESS",
- "FAIL"
- ],
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDeviceInfoMessage": {
- "properties": {
- "product": {
- "type": "string"
- },
- "scheduling_status": {
- "format": "int64",
- "type": "string"
- },
- "serial": {
- "type": "string"
- },
- "status": {
- "format": "int64",
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDeviceResponseMessage": {
- "properties": {
- "devices": {
- "description": "A message for representing an individual host's device entry.",
- "items": {
- "$ref": "#/definitions/WebappSrcProtoModelDeviceInfoMessage"
- },
- "type": "array"
- },
- "has_next": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelGetRequestMessage": {
- "properties": {
- "direction": {
- "type": "string"
- },
- "filter": {
- "type": "string"
- },
- "offset": {
- "format": "int64",
- "type": "string"
- },
- "size": {
- "format": "int64",
- "type": "string"
- },
- "sort": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelHostInfoMessage": {
- "properties": {
- "devices": {
- "description": "A message for representing an individual host's device entry.",
- "items": {
- "$ref": "#/definitions/WebappSrcProtoModelDeviceInfoMessage"
- },
- "type": "array"
- },
- "hostname": {
- "type": "string"
- }
- },
- "type": "object"
- }
- },
- "host": "vtslab-schedule-prod.appspot.com",
- "info": {
- "description": "Endpoint API for host_info.",
- "title": "host",
- "version": "v1"
- },
- "paths": {
- "/host/v1/count": {
- "post": {
- "operationId": "HostInfoApi_count",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelCountRequestMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelCountResponseMessage"
- }
- }
- }
- }
- },
- "/host/v1/get": {
- "post": {
- "operationId": "HostInfoApi_get",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelGetRequestMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelDeviceResponseMessage"
- }
- }
- }
- }
- },
- "/host/v1/set": {
- "post": {
- "operationId": "HostInfoApi_set",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelHostInfoMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
- }
- }
- }
- }
- }
- },
- "produces": [
- "application/json"
- ],
- "schemes": [
- "https"
- ],
- "securityDefinitions": {
- "google_id_token": {
- "authorizationUrl": "",
- "flow": "implicit",
- "type": "oauth2",
- "x-google-issuer": "https://accounts.google.com",
- "x-google-jwks_uri": "https://www.googleapis.com/oauth2/v3/certs"
- }
- },
- "swagger": "2.0",
- "x-google-api-name": "host"
-} \ No newline at end of file
diff --git a/gae/index.yaml b/gae/index.yaml
deleted file mode 100644
index edde291..0000000
--- a/gae/index.yaml
+++ /dev/null
@@ -1,112 +0,0 @@
-indexes:
-- kind: DeviceModel
- ancestor: no
- properties:
- - name: hostname
- direction: asc
- - name: product
- - name: serial
- - name: status
- - name: scheduling_status
- - name: timestamp
-
-- kind: BuildModel
- ancestor: no
- properties:
- - name: manifest_branch
- - name: build_id
- direction: desc
- - name: build_target
- - name: build_type
- - name: artifact_type
- - name: artifacts
- - name: timestamp
-
-- kind: ScheduleModel
- ancestor: no
- properties:
- - name: manifest_branch
- - name: build_target
- - name: test_name
- - name: require_signed_device_build
- - name: has_bootloader_img
- - name: has_radio_img
- - name: period
- - name: priority
- - name: priority_value
- - name: device
- - name: shards
- - name: param
- - name: retry_count
- - name: gsi_branch
- - name: gsi_build_target
- - name: gsi_pab_account_id
- - name: test_branch
- - name: test_build_target
- - name: test_pab_account_id
- - name: timestamp
- - name: children_jobs
- - name: suspended
- - name: error_count
- - name: image_package_repo_base
- - name: required_host_equipment
- - name: required_device_equipment
- - name: report_bucket
- - name: report_spreadsheet_id
- - name: report_persistent_url
- - name: report_reference_url
-
-- kind: LabModel
- ancestor: no
- properties:
- - name: name
- - name: owner
- - name: admin
- - name: hostname
- - name: ip
- - name: script
- - name: devices
- - name: timestamp
- - name: vtslab_version
-
-- kind: JobModel
- ancestor: no
- properties:
- - name: hostname
- - name: priority
- - name: period
- - name: retry_count
- - name: test_name
- - name: device
- - name: serial
- - name: manifest_branch
- - name: build_target
- - name: shards
- - name: param
- - name: build_id
- - name: status
- - name: gsi_branch
- - name: gsi_build_target
- - name: gsi_pab_account_id
- - name: test_branch
- - name: test_build_target
- - name: test_pab_account_id
- - name: infra_log_url
- - name: timestamp
- direction: desc
- - name: parent_schedule
- - name: test_type
- - name: require_signed_device_build
- - name: has_bootloader_img
- - name: has_radio_img
- - name: image_package_repo_base
- - name: report_bucket
- - name: report_spreadsheet_id
- - name: report_persistent_url
- - name: report_reference_url
-
-- kind: JobModel
- properties:
- - name: hostname
- - name: timestamp
- direction: desc \ No newline at end of file
diff --git a/gae/jobv1openapi.json b/gae/jobv1openapi.json
deleted file mode 100644
index e2badde..0000000
--- a/gae/jobv1openapi.json
+++ /dev/null
@@ -1,718 +0,0 @@
-{
- "basePath": "/_ah/api",
- "consumes": [
- "application/json"
- ],
- "definitions": {
- "WebappSrcProtoModelBuildInfoMessage": {
- "properties": {
- "artifact_type": {
- "type": "string"
- },
- "artifacts": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "build_id": {
- "type": "string"
- },
- "build_target": {
- "type": "string"
- },
- "build_type": {
- "type": "string"
- },
- "manifest_branch": {
- "type": "string"
- },
- "signed": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelBuildResponseMessage": {
- "properties": {
- "builds": {
- "description": "A message for representing an individual build entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/#/definitions/#/definitions/#/definitions/WebappSrcProtoModelBuildInfoMessage"
- },
- "type": "array"
- },
- "has_next": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelCountRequestMessage": {
- "properties": {
- "filter": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelCountResponseMessage": {
- "properties": {
- "count": {
- "format": "int64",
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDefaultResponse": {
- "properties": {
- "return_code": {
- "enum": [
- "SUCCESS",
- "FAIL"
- ],
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDeviceInfoMessage": {
- "properties": {
- "product": {
- "type": "string"
- },
- "scheduling_status": {
- "format": "int64",
- "type": "string"
- },
- "serial": {
- "type": "string"
- },
- "status": {
- "format": "int64",
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDeviceResponseMessage": {
- "properties": {
- "devices": {
- "description": "A message for representing an individual host's device entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/#/definitions/#/definitions/WebappSrcProtoModelDeviceInfoMessage"
- },
- "type": "array"
- },
- "has_next": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelGetRequestMessage": {
- "properties": {
- "direction": {
- "type": "string"
- },
- "filter": {
- "type": "string"
- },
- "offset": {
- "format": "int64",
- "type": "string"
- },
- "size": {
- "format": "int64",
- "type": "string"
- },
- "sort": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelHostInfoMessage": {
- "properties": {
- "devices": {
- "description": "A message for representing an individual host's device entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/#/definitions/#/definitions/WebappSrcProtoModelDeviceInfoMessage"
- },
- "type": "array"
- },
- "hostname": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelJobLeaseResponse": {
- "properties": {
- "jobs": {
- "description": "A message for representing an individual job entry.",
- "items": {
- "$ref": "#/definitions/WebappSrcProtoModelJobMessage"
- },
- "type": "array"
- },
- "return_code": {
- "enum": [
- "SUCCESS",
- "FAIL"
- ],
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelJobMessage": {
- "properties": {
- "build_id": {
- "type": "string"
- },
- "build_storage_type": {
- "format": "int64",
- "type": "string"
- },
- "build_target": {
- "type": "string"
- },
- "device": {
- "type": "string"
- },
- "gsi_branch": {
- "type": "string"
- },
- "gsi_build_id": {
- "type": "string"
- },
- "gsi_build_target": {
- "type": "string"
- },
- "gsi_pab_account_id": {
- "type": "string"
- },
- "gsi_storage_type": {
- "format": "int64",
- "type": "string"
- },
- "gsi_vendor_version": {
- "type": "string"
- },
- "has_bootloader_img": {
- "type": "boolean"
- },
- "has_radio_img": {
- "type": "boolean"
- },
- "hostname": {
- "type": "string"
- },
- "image_package_repo_base": {
- "type": "string"
- },
- "infra_log_url": {
- "type": "string"
- },
- "manifest_branch": {
- "type": "string"
- },
- "pab_account_id": {
- "type": "string"
- },
- "param": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "period": {
- "format": "int64",
- "type": "string"
- },
- "priority": {
- "type": "string"
- },
- "report_bucket": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "report_persistent_url": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "report_reference_url": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "report_spreadsheet_id": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "require_signed_device_build": {
- "type": "boolean"
- },
- "retry_count": {
- "format": "int64",
- "type": "string"
- },
- "serial": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "shards": {
- "format": "int64",
- "type": "string"
- },
- "status": {
- "format": "int64",
- "type": "string"
- },
- "test_branch": {
- "type": "string"
- },
- "test_build_id": {
- "type": "string"
- },
- "test_build_target": {
- "type": "string"
- },
- "test_name": {
- "type": "string"
- },
- "test_pab_account_id": {
- "type": "string"
- },
- "test_storage_type": {
- "format": "int64",
- "type": "string"
- },
- "test_type": {
- "format": "int64",
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelJobResponseMessage": {
- "properties": {
- "has_next": {
- "type": "boolean"
- },
- "jobs": {
- "description": "A message for representing an individual job entry.",
- "items": {
- "$ref": "#/definitions/WebappSrcProtoModelJobMessage"
- },
- "type": "array"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabDeviceInfoMessage": {
- "properties": {
- "device_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "product": {
- "type": "string"
- },
- "serial": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabHostInfoMessage": {
- "properties": {
- "device": {
- "description": "A message for representing an individual lab host's device entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/#/definitions/WebappSrcProtoModelLabDeviceInfoMessage"
- },
- "type": "array"
- },
- "host_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "hostname": {
- "type": "string"
- },
- "ip": {
- "type": "string"
- },
- "script": {
- "type": "string"
- },
- "vtslab_version": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabInfoMessage": {
- "properties": {
- "admin": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "host": {
- "description": "A message for representing an individual lab's host entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/#/definitions/WebappSrcProtoModelLabHostInfoMessage"
- },
- "type": "array"
- },
- "name": {
- "type": "string"
- },
- "owner": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabMessage": {
- "properties": {
- "admin": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "devices": {
- "type": "string"
- },
- "host_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "hostname": {
- "type": "string"
- },
- "ip": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "owner": {
- "type": "string"
- },
- "vtslab_version": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabResponseMessage": {
- "properties": {
- "has_next": {
- "type": "boolean"
- },
- "labs": {
- "description": "A model for representing a LabModel entity.",
- "items": {
- "$ref": "#/definitions/#/definitions/#/definitions/WebappSrcProtoModelLabMessage"
- },
- "type": "array"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelScheduleInfoMessage": {
- "properties": {
- "build_storage_type": {
- "format": "int64",
- "type": "string"
- },
- "build_target": {
- "type": "string"
- },
- "device": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "device_pab_account_id": {
- "type": "string"
- },
- "gsi_branch": {
- "type": "string"
- },
- "gsi_build_target": {
- "type": "string"
- },
- "gsi_pab_account_id": {
- "type": "string"
- },
- "gsi_storage_type": {
- "format": "int64",
- "type": "string"
- },
- "gsi_vendor_version": {
- "type": "string"
- },
- "has_bootloader_img": {
- "type": "boolean"
- },
- "has_radio_img": {
- "type": "boolean"
- },
- "image_package_repo_base": {
- "type": "string"
- },
- "manifest_branch": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "owner": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "param": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "period": {
- "format": "int64",
- "type": "string"
- },
- "priority": {
- "type": "string"
- },
- "report_bucket": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "report_persistent_url": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "report_reference_url": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "report_spreadsheet_id": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "require_signed_device_build": {
- "type": "boolean"
- },
- "required_device_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "required_host_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "retry_count": {
- "format": "int64",
- "type": "string"
- },
- "schedule": {
- "type": "string"
- },
- "schedule_type": {
- "type": "string"
- },
- "shards": {
- "format": "int64",
- "type": "string"
- },
- "test_branch": {
- "type": "string"
- },
- "test_build_target": {
- "type": "string"
- },
- "test_name": {
- "type": "string"
- },
- "test_pab_account_id": {
- "type": "string"
- },
- "test_storage_type": {
- "format": "int64",
- "type": "string"
- },
- "timestamp": {
- "format": "date-time",
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelScheduleResponseMessage": {
- "properties": {
- "has_next": {
- "type": "boolean"
- },
- "schedules": {
- "description": "A message for representing an individual schedule entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/WebappSrcProtoModelScheduleInfoMessage"
- },
- "type": "array"
- }
- },
- "type": "object"
- }
- },
- "host": "vtslab-schedule-prod.appspot.com",
- "info": {
- "description": "Endpoint API for job_queue.",
- "title": "job",
- "version": "v1"
- },
- "paths": {
- "/job/v1/count": {
- "post": {
- "operationId": "JobQueueApi_count",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelCountRequestMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelCountResponseMessage"
- }
- }
- }
- }
- },
- "/job/v1/get": {
- "post": {
- "operationId": "JobQueueApi_get",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelGetRequestMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelJobResponseMessage"
- }
- }
- }
- }
- },
- "/job/v1/heartbeat": {
- "post": {
- "operationId": "JobQueueApi_heartbeat",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelJobMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelJobLeaseResponse"
- }
- }
- }
- }
- },
- "/job/v1/lease": {
- "post": {
- "operationId": "JobQueueApi_lease",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelJobMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelJobLeaseResponse"
- }
- }
- }
- }
- }
- },
- "produces": [
- "application/json"
- ],
- "schemes": [
- "https"
- ],
- "securityDefinitions": {
- "google_id_token": {
- "authorizationUrl": "",
- "flow": "implicit",
- "type": "oauth2",
- "x-google-issuer": "https://accounts.google.com",
- "x-google-jwks_uri": "https://www.googleapis.com/oauth2/v3/certs"
- }
- },
- "swagger": "2.0",
- "x-google-api-name": "job"
-} \ No newline at end of file
diff --git a/gae/labv1openapi.json b/gae/labv1openapi.json
deleted file mode 100644
index 37f31d2..0000000
--- a/gae/labv1openapi.json
+++ /dev/null
@@ -1,408 +0,0 @@
-{
- "basePath": "/_ah/api",
- "consumes": [
- "application/json"
- ],
- "definitions": {
- "WebappSrcProtoModelBuildInfoMessage": {
- "properties": {
- "artifact_type": {
- "type": "string"
- },
- "artifacts": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "build_id": {
- "type": "string"
- },
- "build_target": {
- "type": "string"
- },
- "build_type": {
- "type": "string"
- },
- "manifest_branch": {
- "type": "string"
- },
- "signed": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelBuildResponseMessage": {
- "properties": {
- "builds": {
- "description": "A message for representing an individual build entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/#/definitions/WebappSrcProtoModelBuildInfoMessage"
- },
- "type": "array"
- },
- "has_next": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelCountRequestMessage": {
- "properties": {
- "filter": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelCountResponseMessage": {
- "properties": {
- "count": {
- "format": "int64",
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDefaultResponse": {
- "properties": {
- "return_code": {
- "enum": [
- "SUCCESS",
- "FAIL"
- ],
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDeviceInfoMessage": {
- "properties": {
- "product": {
- "type": "string"
- },
- "scheduling_status": {
- "format": "int64",
- "type": "string"
- },
- "serial": {
- "type": "string"
- },
- "status": {
- "format": "int64",
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDeviceResponseMessage": {
- "properties": {
- "devices": {
- "description": "A message for representing an individual host's device entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/WebappSrcProtoModelDeviceInfoMessage"
- },
- "type": "array"
- },
- "has_next": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelGetRequestMessage": {
- "properties": {
- "direction": {
- "type": "string"
- },
- "filter": {
- "type": "string"
- },
- "offset": {
- "format": "int64",
- "type": "string"
- },
- "size": {
- "format": "int64",
- "type": "string"
- },
- "sort": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelHostInfoMessage": {
- "properties": {
- "devices": {
- "description": "A message for representing an individual host's device entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/WebappSrcProtoModelDeviceInfoMessage"
- },
- "type": "array"
- },
- "hostname": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabDeviceInfoMessage": {
- "properties": {
- "device_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "product": {
- "type": "string"
- },
- "serial": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabHostInfoMessage": {
- "properties": {
- "device": {
- "description": "A message for representing an individual lab host's device entry.",
- "items": {
- "$ref": "#/definitions/WebappSrcProtoModelLabDeviceInfoMessage"
- },
- "type": "array"
- },
- "host_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "hostname": {
- "type": "string"
- },
- "ip": {
- "type": "string"
- },
- "script": {
- "type": "string"
- },
- "vtslab_version": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabInfoMessage": {
- "properties": {
- "admin": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "host": {
- "description": "A message for representing an individual lab's host entry.",
- "items": {
- "$ref": "#/definitions/WebappSrcProtoModelLabHostInfoMessage"
- },
- "type": "array"
- },
- "name": {
- "type": "string"
- },
- "owner": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabMessage": {
- "properties": {
- "admin": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "devices": {
- "type": "string"
- },
- "host_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "hostname": {
- "type": "string"
- },
- "ip": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "owner": {
- "type": "string"
- },
- "vtslab_version": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabResponseMessage": {
- "properties": {
- "has_next": {
- "type": "boolean"
- },
- "labs": {
- "description": "A model for representing a LabModel entity.",
- "items": {
- "$ref": "#/definitions/WebappSrcProtoModelLabMessage"
- },
- "type": "array"
- }
- },
- "type": "object"
- }
- },
- "host": "vtslab-schedule-prod.appspot.com",
- "info": {
- "description": "Endpoint API for lab_info.",
- "title": "lab",
- "version": "v1"
- },
- "paths": {
- "/lab/v1/clear": {
- "post": {
- "operationId": "LabInfoApi_clear",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelLabInfoMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
- }
- }
- }
- }
- },
- "/lab/v1/count": {
- "post": {
- "operationId": "LabInfoApi_count",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelCountRequestMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelCountResponseMessage"
- }
- }
- }
- }
- },
- "/lab/v1/get": {
- "post": {
- "operationId": "LabInfoApi_get",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelGetRequestMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelLabResponseMessage"
- }
- }
- }
- }
- },
- "/lab/v1/set": {
- "post": {
- "operationId": "LabInfoApi_set",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelLabInfoMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
- }
- }
- }
- }
- },
- "/lab/v1/set_version": {
- "post": {
- "operationId": "LabInfoApi_setVersion",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelLabHostInfoMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
- }
- }
- }
- }
- }
- },
- "produces": [
- "application/json"
- ],
- "schemes": [
- "https"
- ],
- "securityDefinitions": {
- "google_id_token": {
- "authorizationUrl": "",
- "flow": "implicit",
- "type": "oauth2",
- "x-google-issuer": "https://accounts.google.com",
- "x-google-jwks_uri": "https://www.googleapis.com/oauth2/v3/certs"
- }
- },
- "swagger": "2.0",
- "x-google-api-name": "lab"
-} \ No newline at end of file
diff --git a/gae/queue.yaml b/gae/queue.yaml
deleted file mode 100644
index b460b11..0000000
--- a/gae/queue.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-queue:
-- name: queue-schedule
- mode: push
- rate: 1/s
- bucket_size: 5
- max_concurrent_requests: 1
- retry_parameters:
- task_retry_limit: 2
- min_backoff_seconds: 1
-
-- name: queue-indexing
- mode: push
- rate: 1/s
- bucket_size: 5
- max_concurrent_requests: 1
- retry_parameters:
- task_retry_limit: 7
- min_backoff_seconds: 1 \ No newline at end of file
diff --git a/gae/requirements.txt b/gae/requirements.txt
deleted file mode 100644
index e8c00fc..0000000
--- a/gae/requirements.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-google-api-python-client
-google-endpoints
-
-pytz
-stripe
-
diff --git a/gae/schedulev1openapi.json b/gae/schedulev1openapi.json
deleted file mode 100644
index b1db4e9..0000000
--- a/gae/schedulev1openapi.json
+++ /dev/null
@@ -1,545 +0,0 @@
-{
- "basePath": "/_ah/api",
- "consumes": [
- "application/json"
- ],
- "definitions": {
- "WebappSrcProtoModelBuildInfoMessage": {
- "properties": {
- "artifact_type": {
- "type": "string"
- },
- "artifacts": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "build_id": {
- "type": "string"
- },
- "build_target": {
- "type": "string"
- },
- "build_type": {
- "type": "string"
- },
- "manifest_branch": {
- "type": "string"
- },
- "signed": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelBuildResponseMessage": {
- "properties": {
- "builds": {
- "description": "A message for representing an individual build entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/#/definitions/#/definitions/WebappSrcProtoModelBuildInfoMessage"
- },
- "type": "array"
- },
- "has_next": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelCountRequestMessage": {
- "properties": {
- "filter": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelCountResponseMessage": {
- "properties": {
- "count": {
- "format": "int64",
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDefaultResponse": {
- "properties": {
- "return_code": {
- "enum": [
- "SUCCESS",
- "FAIL"
- ],
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDeviceInfoMessage": {
- "properties": {
- "product": {
- "type": "string"
- },
- "scheduling_status": {
- "format": "int64",
- "type": "string"
- },
- "serial": {
- "type": "string"
- },
- "status": {
- "format": "int64",
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelDeviceResponseMessage": {
- "properties": {
- "devices": {
- "description": "A message for representing an individual host's device entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/#/definitions/WebappSrcProtoModelDeviceInfoMessage"
- },
- "type": "array"
- },
- "has_next": {
- "type": "boolean"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelGetRequestMessage": {
- "properties": {
- "direction": {
- "type": "string"
- },
- "filter": {
- "type": "string"
- },
- "offset": {
- "format": "int64",
- "type": "string"
- },
- "size": {
- "format": "int64",
- "type": "string"
- },
- "sort": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelHostInfoMessage": {
- "properties": {
- "devices": {
- "description": "A message for representing an individual host's device entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/#/definitions/WebappSrcProtoModelDeviceInfoMessage"
- },
- "type": "array"
- },
- "hostname": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabDeviceInfoMessage": {
- "properties": {
- "device_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "product": {
- "type": "string"
- },
- "serial": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabHostInfoMessage": {
- "properties": {
- "device": {
- "description": "A message for representing an individual lab host's device entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/WebappSrcProtoModelLabDeviceInfoMessage"
- },
- "type": "array"
- },
- "host_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "hostname": {
- "type": "string"
- },
- "ip": {
- "type": "string"
- },
- "script": {
- "type": "string"
- },
- "vtslab_version": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabInfoMessage": {
- "properties": {
- "admin": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "host": {
- "description": "A message for representing an individual lab's host entry.",
- "items": {
- "$ref": "#/definitions/#/definitions/WebappSrcProtoModelLabHostInfoMessage"
- },
- "type": "array"
- },
- "name": {
- "type": "string"
- },
- "owner": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabMessage": {
- "properties": {
- "admin": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "devices": {
- "type": "string"
- },
- "host_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "hostname": {
- "type": "string"
- },
- "ip": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "owner": {
- "type": "string"
- },
- "vtslab_version": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelLabResponseMessage": {
- "properties": {
- "has_next": {
- "type": "boolean"
- },
- "labs": {
- "description": "A model for representing a LabModel entity.",
- "items": {
- "$ref": "#/definitions/#/definitions/WebappSrcProtoModelLabMessage"
- },
- "type": "array"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelScheduleInfoMessage": {
- "properties": {
- "build_storage_type": {
- "format": "int64",
- "type": "string"
- },
- "build_target": {
- "type": "string"
- },
- "device": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "device_pab_account_id": {
- "type": "string"
- },
- "gsi_branch": {
- "type": "string"
- },
- "gsi_build_target": {
- "type": "string"
- },
- "gsi_pab_account_id": {
- "type": "string"
- },
- "gsi_storage_type": {
- "format": "int64",
- "type": "string"
- },
- "gsi_vendor_version": {
- "type": "string"
- },
- "has_bootloader_img": {
- "type": "boolean"
- },
- "has_radio_img": {
- "type": "boolean"
- },
- "image_package_repo_base": {
- "type": "string"
- },
- "manifest_branch": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "owner": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "param": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "period": {
- "format": "int64",
- "type": "string"
- },
- "priority": {
- "type": "string"
- },
- "report_bucket": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "report_persistent_url": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "report_reference_url": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "report_spreadsheet_id": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "require_signed_device_build": {
- "type": "boolean"
- },
- "required_device_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "required_host_equipment": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "retry_count": {
- "format": "int64",
- "type": "string"
- },
- "schedule": {
- "type": "string"
- },
- "schedule_type": {
- "type": "string"
- },
- "shards": {
- "format": "int64",
- "type": "string"
- },
- "test_branch": {
- "type": "string"
- },
- "test_build_target": {
- "type": "string"
- },
- "test_name": {
- "type": "string"
- },
- "test_pab_account_id": {
- "type": "string"
- },
- "test_storage_type": {
- "format": "int64",
- "type": "string"
- },
- "timestamp": {
- "format": "date-time",
- "type": "string"
- }
- },
- "type": "object"
- },
- "WebappSrcProtoModelScheduleResponseMessage": {
- "properties": {
- "has_next": {
- "type": "boolean"
- },
- "schedules": {
- "description": "A message for representing an individual schedule entry.",
- "items": {
- "$ref": "#/definitions/WebappSrcProtoModelScheduleInfoMessage"
- },
- "type": "array"
- }
- },
- "type": "object"
- }
- },
- "host": "vtslab-schedule-prod.appspot.com",
- "info": {
- "description": "Endpoint API for schedule_info.",
- "title": "schedule",
- "version": "v1"
- },
- "paths": {
- "/schedule/v1/clear": {
- "post": {
- "operationId": "ScheduleInfoApi_clear",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelScheduleInfoMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
- }
- }
- }
- }
- },
- "/schedule/v1/count": {
- "post": {
- "operationId": "ScheduleInfoApi_count",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelCountRequestMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelCountResponseMessage"
- }
- }
- }
- }
- },
- "/schedule/v1/get": {
- "post": {
- "operationId": "ScheduleInfoApi_get",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelGetRequestMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelScheduleResponseMessage"
- }
- }
- }
- }
- },
- "/schedule/v1/set": {
- "post": {
- "operationId": "ScheduleInfoApi_set",
- "parameters": [
- {
- "in": "body",
- "name": "body",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelScheduleInfoMessage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A successful response",
- "schema": {
- "$ref": "#/definitions/WebappSrcProtoModelDefaultResponse"
- }
- }
- }
- }
- }
- },
- "produces": [
- "application/json"
- ],
- "schemes": [
- "https"
- ],
- "securityDefinitions": {
- "google_id_token": {
- "authorizationUrl": "",
- "flow": "implicit",
- "type": "oauth2",
- "x-google-issuer": "https://accounts.google.com",
- "x-google-jwks_uri": "https://www.googleapis.com/oauth2/v3/certs"
- }
- },
- "swagger": "2.0",
- "x-google-api-name": "schedule"
-} \ No newline at end of file
diff --git a/gae/script/build.sh b/gae/script/build.sh
deleted file mode 100755
index 6cc6a97..0000000
--- a/gae/script/build.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [ "$#" -ne 1 ]; then
- echo "usage: build.sh prod|test|public"
- exit 1
-fi
-
-if [ $1 = "prod" ]; then
- SERVICE="vtslab-schedule-prod.appspot.com"
-elif [ $1 = "public" ]; then
- SERVICE="vtslab-schedule.appspot.com"
-else
- SERVICE="vtslab-schedule-test.appspot.com"
-fi
-
-echo "Building the webapp for $SERVICE ..."
-
-python lib/endpoints/endpointscfg.py get_openapi_spec webapp.src.endpoint.build_info.BuildInfoApi --hostname $SERVICE
-python lib/endpoints/endpointscfg.py get_openapi_spec webapp.src.endpoint.host_info.HostInfoApi --hostname $SERVICE
-python lib/endpoints/endpointscfg.py get_openapi_spec webapp.src.endpoint.schedule_info.ScheduleInfoApi --hostname $SERVICE
-python lib/endpoints/endpointscfg.py get_openapi_spec webapp.src.endpoint.lab_info.LabInfoApi --hostname $SERVICE
-
-echo "Build complete."
diff --git a/gae/script/create-datastore.sh b/gae/script/create-datastore.sh
deleted file mode 100755
index 1101298..0000000
--- a/gae/script/create-datastore.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-gcloud datastore create-indexes index.yaml
diff --git a/gae/script/deploy-endpoint.sh b/gae/script/deploy-endpoint.sh
deleted file mode 100755
index a6cf10b..0000000
--- a/gae/script/deploy-endpoint.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [ "$#" -ne 1 ]; then
- echo "usage: deploy-endpoint.sh prod|test|public"
- exit 1
-fi
-
-if [ $1 = "public" ]; then
- SERVICE="vtslab-schedule"
-else
- SERVICE="vtslab-schedule-$1"
-fi
-
-echo "Creating OpenAPI spec files for $SERVICE.appspot.com ..."
-python lib/endpoints/endpointscfg.py get_openapi_spec webapp.src.endpoint.build_info.BuildInfoApi webapp.src.endpoint.host_info.HostInfoApi webapp.src.endpoint.lab_info.LabInfoApi webapp.src.endpoint.schedule_info.ScheduleInfoApi webapp.src.endpoint.job_queue.JobQueueApi --hostname $SERVICE.appspot.com --x-google-api-name
-
-echo "Depolying the endpoint API implementation to $SERVICE ..."
-
-gcloud endpoints services deploy buildv1openapi.json hostv1openapi.json labv1openapi.json schedulev1openapi.json jobv1openapi.json --project=$SERVICE
-gcloud endpoints configs list --service=$SERVICE.appspot.com
-
-echo "Deployment done!"
diff --git a/gae/script/deploy-webapp.sh b/gae/script/deploy-webapp.sh
deleted file mode 100755
index 187ee7d..0000000
--- a/gae/script/deploy-webapp.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [ "$#" -lt 1 ]; then
- echo "usage: deploy-webapp.sh prod|test|public|local [deploy options]"
- exit 1
-fi
-
-NPM_PATH=$(which npm)
-NG_PATH=$(which ng)
-if [ ! -f "${NPM_PATH}" ]; then
- echo "Cannot find npm in your PATH."
- echo "Please install node.js and npm to deploy frontend."
- exit 0
-fi
-if [ ! -f "${NG_PATH}" ]; then
- echo "Cannot find Angular CLI in your PATH."
- echo "Please install Angular CLI to deploy frontend."
- exit 0
-fi
-
-pushd frontend
-echo "Installing frontend dependencies..."
-npm install
-
-echo "Removing files in dist directory..."
-rm -r dist/*
-
-echo "Building frontend codes..."
-if [ $1 = "local" ]; then
- ng build
-else
- ng build --prod
-fi
-popd
-
-echo "Copying frontend files to webapp/static directory..."
-rm -rf webapp/static/
-mkdir webapp/static
-cp -r frontend/dist/* webapp/static/
-
-if [ $1 = "public" ]; then
- SERVICE="vtslab-schedule"
-elif [ $1 = "local" ]; then
- dev_appserver.py ./
- exit 0
-else
- SERVICE="vtslab-schedule-$1"
-fi
-
-echo "Fetching endpoints service version of $SERVICE ..."
-ENDPOINTS=$(gcloud endpoints configs list --service=$SERVICE.appspot.com)
-arr=($ENDPOINTS)
-
-if [ ${#arr[@]} -lt 4 ]; then
- echo "You need to deploy endpoints first."
- exit 0
-else
- VERSION=${arr[2]}
- NAME=${arr[3]}
- echo "ENDPOINTS_SERVICE_NAME: $NAME"
- echo "ENDPOINTS_SERVICE_VERSION: $VERSION"
-fi
-
-echo "Updating app.yaml ..."
-if [ "$(uname)" == "Darwin" ]; then
- sed -i "" "s/ENDPOINTS_SERVICE_NAME:.*/ENDPOINTS_SERVICE_NAME: $NAME/g" app.yaml
- sed -i "" "s/ENDPOINTS_SERVICE_VERSION:.*/ENDPOINTS_SERVICE_VERSION: $VERSION/g" app.yaml
-else
- sed -i "s/ENDPOINTS_SERVICE_NAME:.*/ENDPOINTS_SERVICE_NAME: $NAME/g" app.yaml
- sed -i "s/ENDPOINTS_SERVICE_VERSION:.*/ENDPOINTS_SERVICE_VERSION: $VERSION/g" app.yaml
-fi
-
-echo "Deploying the web app to $SERVICE ..."
-
-gcloud app deploy app.yaml cron.yaml index.yaml queue.yaml worker.yaml --project=$SERVICE ${@:2}
-
-echo "Deployment done!"
diff --git a/gae/script/install-pip.sh b/gae/script/install-pip.sh
deleted file mode 100755
index 39601d6..0000000
--- a/gae/script/install-pip.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-pip install -t lib -r requirements.txt
diff --git a/gae/testing/README.md b/gae/testing/README.md
deleted file mode 100644
index e567288..0000000
--- a/gae/testing/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-## E2E Test
-
-A Makefile is provided to deploy and run the e2e test.
-
-To run:
-
- export GAE_PROJECT=your-project-id
- make
-
-To manually run, install the requirements
-
- pip install -r e2e/requirements-dev.txt
-
-Finally, run the test
-
- python e2e/test_e2e.py
diff --git a/gae/testing/e2e_test.py b/gae/testing/e2e_test.py
deleted file mode 100644
index 3305862..0000000
--- a/gae/testing/e2e_test.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""App Engine local test runner.
-
-This program handles properly importing the App Engine SDK so that test modules
-can use google.appengine.* APIs and the Google App Engine testbed.
-
-Example invocation:
-
- $ python testrunner.py [--sdk-path ~/google-cloud-sdk]
-"""
-
-import argparse
-import os
-import subprocess
-import sys
-import unittest
-
-
-def ExecuteOneShellCommand(cmd):
- """Executes one shell command and returns (stdout, stderr, exit_code).
-
- Args:
- cmd: string, a shell command.
-
- Returns:
- tuple(string, string, int), containing stdout, stderr, exit_code of
- the shell command.
- """
- p = subprocess.Popen(
- str(cmd), shell=True,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- stdout, stderr = p.communicate()
- return (stdout, stderr, p.returncode)
-
-
-def fixup_paths(path):
- """Adds GAE SDK path to system path and appends it to the google path
- if that already exists."""
- # Not all Google packages are inside namespace packages, which means
- # there might be another non-namespace package named `google` already on
- # the path and simply appending the App Engine SDK to the path will not
- # work since the other package will get discovered and used first.
- # This emulates namespace packages by first searching if a `google` package
- # exists by importing it, and if so appending to its module search path.
- try:
- import google
- google.__path__.append("{0}/google".format(path))
- except ImportError:
- pass
-
- sys.path.insert(0, path)
-
-
-def main(sdk_path, test_path, test_pattern):
-
- if not sdk_path:
- # Get sdk path by running gcloud command.
- stdout, stderr, _ = ExecuteOneShellCommand(
- "gcloud info --format='value(installation.sdk_root)'")
-
- if stderr:
- print("Cannot find google cloud sdk path.")
- return 1
- sdk_path = str.strip(stdout)
-
- # If the SDK path points to a Google Cloud SDK installation
- # then we should alter it to point to the GAE platform location.
- if os.path.exists(os.path.join(sdk_path, 'platform/google_appengine')):
- sdk_path = os.path.join(sdk_path, 'platform/google_appengine')
-
- # Make sure google.appengine.* modules are importable.
- fixup_paths(sdk_path)
-
- # Make sure all bundled third-party packages are available.
- import dev_appserver
- dev_appserver.fix_sys_path()
-
- # Loading appengine_config from the current project ensures that any
- # changes to configuration there are available to all tests (e.g.
- # sys.path modifications, namespaces, etc.)
- try:
- import appengine_config
- (appengine_config)
- except ImportError:
- print('Note: unable to import appengine_config.')
-
- # Discover and run tests.
- suite = unittest.loader.TestLoader().discover(test_path, test_pattern)
- print('Suite', suite)
- return unittest.TextTestRunner(verbosity=2).run(suite)
-
-
-if __name__ == '__main__':
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter)
- parser.add_argument(
- '--sdk_path',
- help='The path to the Google App Engine SDK or the Google Cloud SDK.',
- default=None)
- parser.add_argument(
- '--test-path',
- help='The path to look for tests, defaults to the current directory.',
- default=os.getcwd())
- parser.add_argument(
- '--test-pattern',
- help='The file pattern for test modules, defaults to *_test.py.',
- default='*_test.py')
-
- args = parser.parse_args()
-
- result = main(args.sdk_path, args.test_path, args.test_pattern)
-
- if not result.wasSuccessful():
- sys.exit(1)
diff --git a/gae/testing/requirements-dev.txt b/gae/testing/requirements-dev.txt
deleted file mode 100644
index ca0dee4..0000000
--- a/gae/testing/requirements-dev.txt
+++ /dev/null
@@ -1 +0,0 @@
-requests==2.9.1
diff --git a/gae/testing/test-endpoint.sh b/gae/testing/test-endpoint.sh
deleted file mode 100755
index 66e5cfc..0000000
--- a/gae/testing/test-endpoint.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-curl -H "Content-Type: application/json" -X POST -d '{"devices": [{"serial": "123", "product": "myfish", "serial": "myserial", "status": 1}], "hostname": "hc1"}' https://vtslab-schedule-prod.appspot.com/_ah/api/host_info/v1/set
-
-curl -H "Content-Type: application/json" -X POST -d '{"manifest_branch": "master", "build_id": "a2131", "build_target": "sailfish", "build_type": "userdebug"}' https://vtslab-schedule-prod.appspot.com/_ah/api/build_info/v1/set
-
-curl -H "Content-Type: application/json" -X POST -d '{"device": [{"index": 1}], "host_name": "hc1"}' https://vtslab-schedule-prod.appspot.com/_ah/api/host_info/v1/set
-
-curl -H "Content-Type: application/json" -X POST -d '{"hostname": "vtslab-mtv43-2"}' https://vtslab-schedule-prod.appspot.com/_ah/api/job_queue/v1/get
diff --git a/gae/testing/test_e2e.py b/gae/testing/test_e2e.py
deleted file mode 100644
index 567c8ce..0000000
--- a/gae/testing/test_e2e.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import os
-import requests
-
-URL = os.environ.get("URL")
-
-
-def test_e2e():
- assert URL
- print ("Running test against {}".format(URL))
- r = requests.get(URL)
- assert b'VTS' in r.content
- print("Success")
-
-if __name__ == "__main__":
- test_e2e()
diff --git a/gae/webapp/__init__.py b/gae/webapp/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/__init__.py b/gae/webapp/src/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/endpoint/__init__.py b/gae/webapp/src/endpoint/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/endpoint/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/endpoint/build_info.py b/gae/webapp/src/endpoint/build_info.py
deleted file mode 100644
index 0ba77bb..0000000
--- a/gae/webapp/src/endpoint/build_info.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# Copyright 2017 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Build Info APIs implemented using Google Cloud Endpoints."""
-
-import datetime
-import endpoints
-import logging
-
-from webapp.src.endpoint import endpoint_base
-from webapp.src.proto import model
-
-BUILD_INFO_RESOURCE = endpoints.ResourceContainer(model.BuildInfoMessage)
-
-
-@endpoints.api(name="build", version="v1")
-class BuildInfoApi(endpoint_base.EndpointBase):
- """Endpoint API for build_info."""
-
- @endpoints.method(
- BUILD_INFO_RESOURCE,
- model.DefaultResponse,
- path="set",
- http_method="POST",
- name="set")
- def set(self, request):
- """Sets the build info based on the `request`."""
- build_query = model.BuildModel.query(
- model.BuildModel.build_id == request.build_id,
- model.BuildModel.build_target == request.build_target,
- model.BuildModel.build_type == request.build_type,
- model.BuildModel.artifact_type == request.artifact_type)
- existing_builds = build_query.fetch()
-
- if existing_builds and len(existing_builds) > 1:
- logging.warning(
- "Duplicated builds found for [build_id]{} "
- "[build_target]{} [build_type]{} [artifact_type]{}".format(
- request.build_id, request.build_target, request.build_type,
- request.artifact_type))
-
- if existing_builds:
- build = existing_builds[0]
- if request.signed:
- # only signed builds need to overwrite the exist entities.
- build.signed = request.signed
- else:
- build = model.BuildModel()
- common_attributes = self.GetCommonAttributes(request,
- model.BuildModel)
- for attr in common_attributes:
- setattr(build, attr, getattr(request, attr))
-
- build.timestamp = datetime.datetime.now()
- build.put()
-
- return model.DefaultResponse(
- return_code=model.ReturnCodeMessage.SUCCESS)
-
- @endpoints.method(
- endpoint_base.GET_REQUEST_RESOURCE,
- model.BuildResponseMessage,
- path="get",
- http_method="POST",
- name="get")
- def get(self, request):
- """Gets the builds from datastore."""
- return_list, more = self.Get(request=request,
- metaclass=model.BuildModel,
- message=model.BuildInfoMessage)
- return model.BuildResponseMessage(builds=return_list, has_next=more)
-
- @endpoints.method(
- endpoint_base.COUNT_REQUEST_RESOURCE,
- model.CountResponseMessage,
- path="count",
- http_method="POST",
- name="count")
- def count(self, request):
- """Gets total number of BuildModel entities stored in datastore."""
- filters = self.CreateFilterList(
- filter_string=request.filter, metaclass=model.BuildModel)
- count = self.Count(metaclass=model.BuildModel, filters=filters)
-
- return model.CountResponseMessage(count=count)
diff --git a/gae/webapp/src/endpoint/build_info_test.py b/gae/webapp/src/endpoint/build_info_test.py
deleted file mode 100644
index 8b70831..0000000
--- a/gae/webapp/src/endpoint/build_info_test.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from webapp.src.endpoint import build_info
-from webapp.src.proto import model
-from webapp.src.testing import unittest_base
-
-
-class BuildInfoTest(unittest_base.UnitTestBase):
- """A class to test build_info endpoint API."""
-
- def setUp(self):
- """Initializes test"""
- super(BuildInfoTest, self).setUp()
-
- def testSetNewBuildModel(self):
- """Asserts build_info/set API receives a new build."""
- builds = model.BuildModel.query().fetch()
- self.assertEqual(len(builds), 0)
- container = (
- build_info.BUILD_INFO_RESOURCE.combined_message_class(
- manifest_branch=self.GetRandomString(),
- build_id=self.GetRandomString(),
- build_target=self.GetRandomString(),
- build_type=self.GetRandomString(),
- artifact_type=self.GetRandomString(),
- ))
- api = build_info.BuildInfoApi()
- response = api.set(container)
-
- self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
- builds = model.BuildModel.query().fetch()
- self.assertEqual(len(builds), 1)
-
- def testSetDuplicatedBuildModel(self):
- """Asserts build_info/set API receives a duplicated build."""
- manifest_branch = self.GetRandomString()
- build_id = self.GetRandomString()
- build_target = self.GetRandomString()
- build_type = self.GetRandomString()
- artifact_type = self.GetRandomString()
-
- builds = model.BuildModel.query().fetch()
- self.assertEqual(len(builds), 0)
- container = (
- build_info.BUILD_INFO_RESOURCE.combined_message_class(
- manifest_branch=manifest_branch,
- build_id=build_id,
- build_target=build_target,
- build_type=build_type,
- artifact_type=artifact_type,
- ))
- api = build_info.BuildInfoApi()
- response = api.set(container)
-
- self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
- builds = model.BuildModel.query().fetch()
- self.assertEqual(len(builds), 1)
-
- container = (
- build_info.BUILD_INFO_RESOURCE.combined_message_class(
- manifest_branch=manifest_branch,
- build_id=build_id,
- build_target=build_target,
- build_type=build_type,
- artifact_type=artifact_type,
- ))
- api = build_info.BuildInfoApi()
- response = api.set(container)
- self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
- builds = model.BuildModel.query().fetch()
- self.assertEqual(len(builds), 1)
-
- def testUpdateSignedBuildModel(self):
- """Asserts build_info/set API receives a duplicated build."""
- manifest_branch = self.GetRandomString()
- build_id = self.GetRandomString()
- build_target = self.GetRandomString()
- build_type = self.GetRandomString()
- artifact_type = self.GetRandomString()
-
- builds = model.BuildModel.query().fetch()
- self.assertEqual(len(builds), 0)
- container = (
- build_info.BUILD_INFO_RESOURCE.combined_message_class(
- manifest_branch=manifest_branch,
- build_id=build_id,
- build_target=build_target,
- build_type=build_type,
- artifact_type=artifact_type,
- signed=False,
- ))
- api = build_info.BuildInfoApi()
- response = api.set(container)
-
- self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
- builds = model.BuildModel.query().fetch()
- self.assertEqual(len(builds), 1)
-
- container = (
- build_info.BUILD_INFO_RESOURCE.combined_message_class(
- manifest_branch=manifest_branch,
- build_id=build_id,
- build_target=build_target,
- build_type=build_type,
- artifact_type=artifact_type,
- signed=True
- ))
- api = build_info.BuildInfoApi()
- response = api.set(container)
- self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
- builds = model.BuildModel.query().fetch()
- self.assertEqual(len(builds), 1)
- self.assertEqual(builds[0].signed, True)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/gae/webapp/src/endpoint/endpoint_base.py b/gae/webapp/src/endpoint/endpoint_base.py
deleted file mode 100644
index d0dddd5..0000000
--- a/gae/webapp/src/endpoint/endpoint_base.py
+++ /dev/null
@@ -1,330 +0,0 @@
-# Copyright 2018 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import datetime
-import inspect
-import logging
-import json
-
-import endpoints
-from protorpc import messages
-from protorpc import remote
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-
-MAX_QUERY_SIZE = 1000
-
-COUNT_REQUEST_RESOURCE = endpoints.ResourceContainer(model.CountRequestMessage)
-GET_REQUEST_RESOURCE = endpoints.ResourceContainer(model.GetRequestMessage)
-
-
-class EndpointBase(remote.Service):
- """A base class for endpoint implementation."""
-
- def GetCommonAttributes(self, resource, reference):
- """Gets a list of common attribute names.
-
- This method finds the attributes assigned in 'resource' instance, and
- filters out if the attributes are not a member of 'reference' class.
-
- Args:
- resource: either a protorpc.messages.Message instance,
- or a ndb.Model instance.
- reference: either a protorpc.messages.Message class,
- or a ndb.Model class.
-
- Returns:
- a list of string, attribute names exist on resource and reference.
-
- Raises:
- ValueError if resource or reference is not supported class.
- """
- # check resource type and absorb list of assigned attributes.
- resource_attrs = self.GetAttributes(resource, assigned_only=True)
- reference_attrs = self.GetAttributes(reference)
- return [x for x in resource_attrs if x in reference_attrs]
-
- def GetAttributes(self, value, assigned_only=False):
- """Gets a list of attributes.
-
- Args:
- value: a class instance or a class itself.
- assigned_only: True to get only assigned attributes when value is
- an instance, False to get all attributes.
-
- Raises:
- ValueError if value is not supported class.
- """
- attrs = []
- if inspect.isclass(value):
- if assigned_only:
- logging.warning(
- "Please use a class instance for 'resource' argument.")
-
- if (issubclass(value, messages.Message)
- or issubclass(value, ndb.Model)):
- attrs = [
- x[0] for x in value.__dict__.items()
- if not x[0].startswith("_")
- ]
- else:
- raise ValueError("Only protorpc.messages.Message or ndb.Model "
- "class are supported.")
- else:
- if isinstance(value, messages.Message):
- attrs = [
- x.name for x in value.all_fields()
- if not assigned_only or (
- value.get_assigned_value(x.name) not in [None, []])
- ]
- elif isinstance(value, ndb.Model):
- attrs = [
- x for x in list(value.to_dict())
- if not assigned_only or (
- getattr(value, x, None) not in [None, []])
- ]
- else:
- raise ValueError("Only protorpc.messages.Message or ndb.Model "
- "class are supported.")
-
- return attrs
-
- def Count(self, metaclass, filters=None):
- """Counts entities from datastore with options.
-
- Args:
- metaclass: a metaclass for ndb model.
- filters: a list of tuples. Each tuple consists of three values:
- key, method, and value.
-
- Returns:
- a number of entities.
- """
- query, _ = self.CreateQueryFilter(metaclass=metaclass, filters=filters)
- return query.count()
-
- def Fetch(self,
- metaclass,
- size,
- offset=0,
- filters=None,
- sort_key="",
- direction="asc"):
- """Fetches entities from datastore with options.
-
- Args:
- metaclass: a metaclass for ndb model.
- size: an integer, max number of entities to fetch at once.
- offset: an integer, number of query results to skip.
- filters: a list of filter tuple, a form of (key: string,
- method: integer, value: string).
- sort_key: a string, key name to sort by.
- direction: a string, "asc" for ascending order and "desc" for
- descending order.
-
- Returns:
- a list of fetched entities.
- a boolean, True if there is next page or False if not.
- """
- query, empty_repeated_field = self.CreateQueryFilter(
- metaclass=metaclass, filters=filters)
- sorted_query = self.SortQuery(
- query=query,
- metaclass=metaclass,
- sort_key=sort_key,
- direction=direction)
-
- if size:
- entities, _, more = sorted_query.fetch_page(
- page_size=size, offset=offset)
- else:
- entities = sorted_query.fetch()
- more = False
-
- if empty_repeated_field:
- entities = [
- x for x in entities
- if all([not getattr(x, attr) for attr in empty_repeated_field])
- ]
-
- return entities, more
-
- def CreateQueryFilter(self, metaclass, filters):
- """Creates a query with the given filters.
-
- Args:
- metaclass: a metaclass for ndb model.
- filters: a list of tuples. Each tuple consists of three values:
- key, method, and value.
-
- Returns:
- a filtered query for the given metaclass.
- a list of strings that failed to create the query due to its empty
- value for the repeated property.
- """
- empty_repeated_field = []
- query = metaclass.query()
- if not filters:
- return query, empty_repeated_field
-
- for _filter in filters:
- property_key = _filter["key"]
- method = _filter["method"]
- value = _filter["value"]
- if type(value) is str or type(value) is unicode:
- if isinstance(metaclass._properties[property_key],
- ndb.BooleanProperty):
- value = value.lower() in ("yes", "true", "1")
- elif isinstance(metaclass._properties[property_key],
- ndb.IntegerProperty):
- value = int(value)
- if metaclass._properties[property_key]._repeated:
- if value:
- value = [value]
- if method == Status.FILTER_METHOD[Status.FILTER_Has]:
- query = query.filter(
- getattr(metaclass, property_key).IN(value))
- else:
- logging.warning(
- "You cannot compare repeated "
- "properties except 'IN(has)' operation.")
- else:
- logging.debug("Empty repeated list cannot be queried.")
- empty_repeated_field.append(value)
- elif isinstance(metaclass._properties[property_key],
- ndb.DateTimeProperty):
- if method == Status.FILTER_METHOD[Status.FILTER_LessThan]:
- query = query.filter(
- getattr(metaclass, property_key) < datetime.datetime.
- now() - datetime.timedelta(hours=int(value)))
- elif method == Status.FILTER_METHOD[Status.FILTER_GreaterThan]:
- query = query.filter(
- getattr(metaclass, property_key) > datetime.datetime.
- now() - datetime.timedelta(hours=int(value)))
- else:
- logging.debug("DateTimeProperty only allows <=(less than) "
- "and >=(greater than) operation.")
- else:
- if method == Status.FILTER_METHOD[Status.FILTER_EqualTo]:
- query = query.filter(
- getattr(metaclass, property_key) == value)
- elif method == Status.FILTER_METHOD[Status.FILTER_LessThan]:
- query = query.filter(
- getattr(metaclass, property_key) < value)
- elif method == Status.FILTER_METHOD[Status.FILTER_GreaterThan]:
- query = query.filter(
- getattr(metaclass, property_key) > value)
- elif method == Status.FILTER_METHOD[
- Status.FILTER_LessThanOrEqualTo]:
- query = query.filter(
- getattr(metaclass, property_key) <= value)
- elif method == Status.FILTER_METHOD[
- Status.FILTER_GreaterThanOrEqualTo]:
- query = query.filter(
- getattr(metaclass, property_key) >= value)
- elif method == Status.FILTER_METHOD[Status.FILTER_NotEqualTo]:
- query = query.filter(
- getattr(metaclass, property_key) != value).order(
- getattr(metaclass, property_key), metaclass.key)
- elif method == Status.FILTER_METHOD[Status.FILTER_Has]:
- query = query.filter(
- getattr(metaclass, property_key).IN(value)).order(
- getattr(metaclass, property_key), metaclass.key)
- else:
- logging.warning(
- "{} is not supported filter method.".format(method))
- return query, empty_repeated_field
-
- def SortQuery(self, query, metaclass, sort_key, direction):
- """Sorts the given query with sort_key and direction.
-
- Args:
- query: a ndb query to sort.
- metaclass: a metaclass for ndb model.
- sort_key: a string, key name to sort by.
- direction: a string, "asc" for ascending order and "desc" for
- descending order.
- """
- if sort_key:
- if direction == "desc":
- query = query.order(-getattr(metaclass, sort_key))
- else:
- query = query.order(getattr(metaclass, sort_key))
-
- return query
-
- def CreateFilterList(self, filter_string, metaclass):
- """Creates a list of filters.
-
- Args:
- filter_string: a string, stringified JSON which contains 'key',
- 'method', 'value' to build filter information.
- metaclass: a metaclass for ndb model.
-
- Returns:
- a list of tuples where each tuple consists of three values:
- key, method, and value.
- """
- model_properties = self.GetAttributes(metaclass)
- filters = []
- if filter_string:
- filters = json.loads(filter_string)
- for _filter in filters:
- if _filter["key"] not in model_properties:
- filters.remove(_filter)
- return filters
-
- def Get(self, request, metaclass, message):
- """Handles a request through /get endpoints API to retrieves entities.
-
- Args:
- request: a request body message received through /get API.
- metaclass: a metaclass for ndb model. This method will fetch the
- 'metaclass' type of model from datastore.
- message: a Protocol RPC message class. Fetched entities will be
- converted to this message class instances.
-
- Returns:
- a list of fetched entities.
- a boolean, True if there is next page or False if not.
- """
- size = request.size if request.size else MAX_QUERY_SIZE
- offset = request.offset if request.offset else 0
-
- filters = self.CreateFilterList(
- filter_string=request.filter, metaclass=metaclass)
-
- entities, more = self.Fetch(
- metaclass=metaclass,
- size=size,
- filters=filters,
- offset=offset,
- sort_key=request.sort,
- direction=request.direction,
- )
-
- return_list = []
- for entity in entities:
- entity_dict = {}
- assigned_attributes = self.GetCommonAttributes(
- resource=entity, reference=message)
- for attr in assigned_attributes:
- entity_dict[attr] = getattr(entity, attr, None)
- if hasattr(message, "urlsafe_key"):
- entity_dict["urlsafe_key"] = entity.key.urlsafe()
- return_list.append(entity_dict)
-
- return return_list, more
diff --git a/gae/webapp/src/endpoint/endpoint_base_test.py b/gae/webapp/src/endpoint/endpoint_base_test.py
deleted file mode 100644
index 2eb397a..0000000
--- a/gae/webapp/src/endpoint/endpoint_base_test.py
+++ /dev/null
@@ -1,256 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import endpoints
-import json
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import endpoint_base
-from webapp.src.proto import model
-from webapp.src.testing import unittest_base
-
-
-class EndpointBaseTest(unittest_base.UnitTestBase):
- """A class to test endpoint_base.EndpointBase class.
-
- Attributes:
- eb: An EndpointBase class instance.
- """
-
- def setUp(self):
- """Initializes test"""
- super(EndpointBaseTest, self).setUp()
- self.eb = endpoint_base.EndpointBase()
-
- def testGetAssignedMessagesAttributes(self):
- attrs = ["hostname", "priority", "test_branch"]
- job_message = model.JobMessage()
- for attr in attrs:
- setattr(job_message, attr, attr)
- result = self.eb.GetAttributes(job_message, assigned_only=True)
- self.assertEqual(set(attrs), set(result))
-
- def testGetAssignedModelAttributes(self):
- attrs = ["hostname", "priority", "test_branch"]
- job = model.JobModel()
- for attr in attrs:
- setattr(job, attr, attr)
- result = self.eb.GetAttributes(job, assigned_only=True)
- self.assertEqual(set(attrs), set(result))
-
- def testGetAllMessagesAttributes(self):
- attrs = ["hostname", "priority", "test_branch"]
- full_attrs = [
- "test_type", "hostname", "priority", "test_name",
- "require_signed_device_build", "has_bootloader_img",
- "has_radio_img", "device", "serial", "build_storage_type",
- "manifest_branch", "build_target", "build_id", "pab_account_id",
- "shards", "param", "status", "period", "gsi_storage_type",
- "gsi_branch", "gsi_build_target", "gsi_build_id",
- "gsi_pab_account_id", "gsi_vendor_version", "test_storage_type",
- "test_branch", "test_build_target", "test_build_id",
- "test_pab_account_id", "retry_count", "infra_log_url",
- "image_package_repo_base", "report_bucket",
- "report_spreadsheet_id", "report_persistent_url",
- "report_reference_url"
- ]
- job_message = model.JobMessage()
- for attr in attrs:
- setattr(job_message, attr, attr)
- result = self.eb.GetAttributes(job_message, assigned_only=False)
- self.assertTrue(set(full_attrs) <= set(result))
-
- def testGetAllModelAttributes(self):
- attrs = ["hostname", "priority", "test_branch"]
- full_attrs = [
- "test_type", "hostname", "priority", "test_name",
- "require_signed_device_build", "has_bootloader_img",
- "has_radio_img", "device", "serial", "build_storage_type",
- "manifest_branch", "build_target", "build_id", "pab_account_id",
- "shards", "param", "status", "period", "gsi_storage_type",
- "gsi_branch", "gsi_build_target", "gsi_build_id",
- "gsi_pab_account_id", "gsi_vendor_version", "test_storage_type",
- "test_branch", "test_build_target", "test_build_id",
- "test_pab_account_id", "timestamp", "heartbeat_stamp",
- "retry_count", "infra_log_url", "parent_schedule",
- "image_package_repo_base", "report_bucket",
- "report_spreadsheet_id", "report_persistent_url",
- "report_reference_url"
- ]
- job = model.JobModel()
- for attr in attrs:
- setattr(job, attr, attr)
- result = self.eb.GetAttributes(job, assigned_only=False)
- self.assertTrue(set(full_attrs) <= set(result))
-
- def testGetSingleEntity(self):
- """Asserts to get a single entity."""
- device = self.GenerateDeviceModel()
- device.put()
-
- request_body = (endpoints.ResourceContainer(
- model.GetRequestMessage).combined_message_class(
- size=0,
- offset=0,
- filter="",
- sort="",
- direction="",
- ))
- result, more = self.eb.Get(
- request=request_body,
- metaclass=model.DeviceModel,
- message=model.DeviceInfoMessage)
- self.assertEqual(len(result), 1)
- self.assertFalse(more)
-
- def testGetHundredEntities(self):
- """Asserts to get hundred entities."""
- for _ in xrange(100):
- device = self.GenerateDeviceModel()
- device.put()
-
- request_body = (endpoints.ResourceContainer(
- model.GetRequestMessage).combined_message_class(
- size=0,
- offset=0,
- filter="",
- sort="",
- direction="",
- ))
- result, more = self.eb.Get(
- request=request_body,
- metaclass=model.DeviceModel,
- message=model.DeviceInfoMessage)
- self.assertEqual(len(result), 100)
- self.assertFalse(more)
-
- def testGetEntitiesWithPagination(self):
- """Asserts to get entities with pagination."""
- for _ in xrange(100):
- device = self.GenerateDeviceModel()
- device.put()
-
- request_body = (endpoints.ResourceContainer(
- model.GetRequestMessage).combined_message_class(
- size=60,
- offset=0,
- filter="",
- sort="",
- direction="",
- ))
- result, more = self.eb.Get(
- request=request_body,
- metaclass=model.DeviceModel,
- message=model.DeviceInfoMessage)
- self.assertEqual(len(result), 60)
- self.assertTrue(more)
-
- request_body = (endpoints.ResourceContainer(
- model.GetRequestMessage).combined_message_class(
- size=100,
- offset=60,
- filter="",
- sort="",
- direction="",
- ))
- result, more = self.eb.Get(
- request=request_body,
- metaclass=model.DeviceModel,
- message=model.DeviceInfoMessage)
- self.assertEqual(len(result), 40)
- self.assertFalse(more)
-
- def testGetWithFilter(self):
- """Asserts to get entities with filter."""
- for _ in xrange(50):
- device = self.GenerateDeviceModel()
- device.put()
-
- for _ in xrange(50):
- device = self.GenerateDeviceModel(product="product")
- device.put()
-
- filter = [{
- "key": "product",
- "method": Status.FILTER_METHOD[Status.FILTER_EqualTo],
- "value": "product"
- }]
- filter_string = json.dumps(filter)
- request_body = (endpoints.ResourceContainer(
- model.GetRequestMessage).combined_message_class(
- size=0,
- offset=0,
- filter=filter_string,
- sort="",
- direction="",
- ))
- result, more = self.eb.Get(
- request=request_body,
- metaclass=model.DeviceModel,
- message=model.DeviceInfoMessage)
- self.assertEqual(len(result), 50)
- self.assertFalse(more)
-
- def testGetWithSort(self):
- """Asserts to get entities with sort."""
- for _ in xrange(100):
- device = self.GenerateDeviceModel()
- device.put()
-
- request_body = (endpoints.ResourceContainer(
- model.GetRequestMessage).combined_message_class(
- size=0,
- offset=0,
- filter="",
- sort="serial",
- direction="asc",
- ))
-
- result, more = self.eb.Get(
- request=request_body,
- metaclass=model.DeviceModel,
- message=model.DeviceInfoMessage)
- self.assertEqual(len(result), 100)
- for i in xrange(len(result) - 1):
- self.assertTrue(result[i]["serial"] < result[i + 1]["serial"])
-
- request_body = (endpoints.ResourceContainer(
- model.GetRequestMessage).combined_message_class(
- size=0,
- offset=0,
- filter="",
- sort="serial",
- direction="desc",
- ))
-
- result, more = self.eb.Get(
- request=request_body,
- metaclass=model.DeviceModel,
- message=model.DeviceInfoMessage)
- self.assertEqual(len(result), 100)
- for i in xrange(len(result) - 1):
- self.assertTrue(result[i]["serial"] > result[i + 1]["serial"])
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/gae/webapp/src/endpoint/host_info.py b/gae/webapp/src/endpoint/host_info.py
deleted file mode 100644
index ac89a11..0000000
--- a/gae/webapp/src/endpoint/host_info.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# Copyright 2017 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Host Info APIs implemented using Google Cloud Endpoints."""
-
-import datetime
-import endpoints
-import logging
-
-from google.appengine.api import users
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import endpoint_base
-from webapp.src.proto import model
-
-HOST_INFO_RESOURCE = endpoints.ResourceContainer(model.HostInfoMessage)
-
-# Product type name for null device.
-_NULL_DEVICE_PRODUCT_TYPE = "null"
-
-
-def AddNullDevices(hostname, null_device_count):
- """Adds null devices to DeviceModel data store.
-
- Args:
- hostname: string, the host name.
- null_device_count: integer, the number of null devices.
- """
- device_query = model.DeviceModel.query(
- model.DeviceModel.hostname == hostname,
- model.DeviceModel.product == _NULL_DEVICE_PRODUCT_TYPE
- )
- null_devices = device_query.fetch()
- existing_null_device_count = len(null_devices)
-
- if existing_null_device_count < null_device_count:
- devices_to_put = []
- for _ in range(null_device_count - existing_null_device_count):
- device = model.DeviceModel()
- device.hostname = hostname
- device.serial = "n/a"
- device.product = _NULL_DEVICE_PRODUCT_TYPE
- device.status = Status.DEVICE_STATUS_DICT["ready"]
- device.scheduling_status = Status.DEVICE_SCHEDULING_STATUS_DICT[
- "free"]
- device.timestamp = datetime.datetime.now()
- devices_to_put.append(device)
- if devices_to_put:
- ndb.put_multi(devices_to_put)
-
-
-@endpoints.api(name='host', version='v1')
-class HostInfoApi(endpoint_base.EndpointBase):
- """Endpoint API for host_info."""
-
- @endpoints.method(
- HOST_INFO_RESOURCE,
- model.DefaultResponse,
- path='set',
- http_method='POST',
- name='set')
- def set(self, request):
- """Sets the host info based on the `request`."""
- if users.get_current_user():
- username = users.get_current_user().email()
- else:
- username = "anonymous"
-
- devices_to_put = []
- for request_device in request.devices:
- device_query = model.DeviceModel.query(
- model.DeviceModel.serial == request_device.serial
- )
- existing_device = device_query.fetch()
- if existing_device:
- device = existing_device[0]
- else:
- device = model.DeviceModel()
- device.serial = request_device.serial
- device.scheduling_status = Status.DEVICE_SCHEDULING_STATUS_DICT[
- "free"]
- if not device.product or request_device.product != "error":
- device.product = request_device.product
-
- device.username = username
- device.hostname = request.hostname
- device.status = request_device.status
- device.timestamp = datetime.datetime.now()
- devices_to_put.append(device)
- if devices_to_put:
- ndb.put_multi(devices_to_put)
-
- return model.DefaultResponse(
- return_code=model.ReturnCodeMessage.SUCCESS)
-
- @endpoints.method(
- endpoint_base.GET_REQUEST_RESOURCE,
- model.DeviceResponseMessage,
- path="get",
- http_method="POST",
- name="get")
- def get(self, request):
- """Gets the devices from datastore."""
- return_list, more = self.Get(request=request,
- metaclass=model.DeviceModel,
- message=model.DeviceInfoMessage)
-
- return model.DeviceResponseMessage(devices=return_list, has_next=more)
-
- @endpoints.method(
- endpoint_base.COUNT_REQUEST_RESOURCE,
- model.CountResponseMessage,
- path="count",
- http_method="POST",
- name="count")
- def count(self, request):
- """Gets total number of DeviceModel entities stored in datastore."""
- filters = self.CreateFilterList(
- filter_string=request.filter, metaclass=model.DeviceModel)
-
- count = self.Count(metaclass=model.DeviceModel, filters=filters)
-
- return model.CountResponseMessage(count=count)
diff --git a/gae/webapp/src/endpoint/host_info_test.py b/gae/webapp/src/endpoint/host_info_test.py
deleted file mode 100644
index e41037c..0000000
--- a/gae/webapp/src/endpoint/host_info_test.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import host_info
-from webapp.src.proto import model
-from webapp.src.testing import unittest_base
-
-
-class HostInfoTest(unittest_base.UnitTestBase):
- """A class to test host_info endpoint API."""
-
- def setUp(self):
- """Initializes test"""
- super(HostInfoTest, self).setUp()
-
-
- def testUpdateExistingDevice(self):
- """Asserts that device update does not create a duplicate."""
- hostname = self.GetRandomString()
- serial = self.GetRandomString()
- product = self.GetRandomString()
- error_device = {
- "serial": serial,
- "product": "error",
- }
- container = (
- host_info.HOST_INFO_RESOURCE.combined_message_class(
- hostname=hostname,
- devices=[error_device],
- ))
-
- api = host_info.HostInfoApi()
- api.set(container)
-
- devices = model.DeviceModel.query().fetch()
- self.assertEqual(len(devices), 1)
-
- # name "error" is allowed as initial name.
- self.assertEqual(devices[0].product, "error")
-
- correct_device = {
- "serial": serial,
- "product": product,
- }
- container = (
- host_info.HOST_INFO_RESOURCE.combined_message_class(
- hostname=hostname,
- devices=[correct_device],
- ))
- api.set(container)
-
- devices = model.DeviceModel.query().fetch()
- self.assertEqual(len(devices), 1)
- # correct product name (which is not "error") should be overwritten.
- self.assertEqual(devices[0].product, product)
-
- container = (
- host_info.HOST_INFO_RESOURCE.combined_message_class(
- hostname=hostname,
- devices=[error_device],
- ))
- api.set(container)
-
- devices = model.DeviceModel.query().fetch()
- self.assertEqual(len(devices), 1)
- # "error" should be ignored.
- self.assertEqual(devices[0].product, product)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/gae/webapp/src/endpoint/job_queue.py b/gae/webapp/src/endpoint/job_queue.py
deleted file mode 100644
index 7416f8c..0000000
--- a/gae/webapp/src/endpoint/job_queue.py
+++ /dev/null
@@ -1,206 +0,0 @@
-# Copyright 2017 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Job Queue Info APIs implemented using Google Cloud Endpoints."""
-
-import datetime
-import endpoints
-import logging
-import re
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import endpoint_base
-from webapp.src.proto import model
-from webapp.src.utils import email_util
-from webapp.src.utils import model_util
-
-from google.appengine.ext import ndb
-
-JOB_QUEUE_RESOURCE = endpoints.ResourceContainer(model.JobMessage)
-GCS_URL_PREFIX = "gs://"
-HTTP_HTTPS_REGEX = "^https?://"
-STORAGE_API_URL = "https://storage.cloud.google.com/"
-
-
-@endpoints.api(name='job', version='v1')
-class JobQueueApi(endpoint_base.EndpointBase):
- """Endpoint API for job_queue."""
-
- @endpoints.method(
- JOB_QUEUE_RESOURCE,
- model.JobLeaseResponse,
- path='lease',
- http_method='POST',
- name='lease')
- def lease(self, request):
- """Gets the job(s) based on the condition specified in `request`."""
- job_query = model.JobModel.query(
- model.JobModel.hostname == request.hostname,
- model.JobModel.status == Status.JOB_STATUS_DICT["ready"])
- existing_jobs = job_query.fetch()
-
- priority_sorted_jobs = sorted(
- existing_jobs,
- key=lambda x: (Status.GetPriorityValue(x.priority), x.timestamp))
-
- if priority_sorted_jobs:
- job = priority_sorted_jobs[0]
- job.status = Status.JOB_STATUS_DICT["leased"]
- job.put()
-
- job_message = model.JobMessage()
- common_attributes = self.GetCommonAttributes(job, model.JobMessage)
- for attr in common_attributes:
- setattr(job_message, attr, getattr(job, attr))
-
- device_query = model.DeviceModel.query(
- model.DeviceModel.serial.IN(job.serial))
- devices = device_query.fetch()
- devices_to_put = []
- for device in devices:
- device.scheduling_status = Status.DEVICE_SCHEDULING_STATUS_DICT[
- "use"]
- devices_to_put.append(device)
- if devices_to_put:
- ndb.put_multi(devices_to_put)
-
- return model.JobLeaseResponse(
- return_code=model.ReturnCodeMessage.SUCCESS,
- jobs=[job_message])
- else:
- return model.JobLeaseResponse(
- return_code=model.ReturnCodeMessage.FAIL, jobs=[])
-
- @endpoints.method(
- JOB_QUEUE_RESOURCE,
- model.JobLeaseResponse,
- path='heartbeat',
- http_method='POST',
- name='heartbeat')
- def heartbeat(self, request):
- """Processes the heartbeat signal from HC which leased queued job(s)."""
- # minify jobs by query and confirm with serial from fetched jobs
- job_query = model.JobModel.query(
- model.JobModel.hostname == request.hostname,
- model.JobModel.manifest_branch == request.manifest_branch,
- model.JobModel.build_target == request.build_target,
- model.JobModel.test_name == request.test_name,
- model.JobModel.status == Status.JOB_STATUS_DICT["leased"])
- existing_jobs = job_query.fetch()
- same_jobs = [
- x for x in existing_jobs if set(x.serial) == set(request.serial)
- ]
-
- if len(same_jobs) > 1:
- logging.warning("[heartbeat] more than one job is found!")
- logging.warning(
- "[heartbeat] <hostname>{} <manifest_branch>{} "
- "<build_target>{} <test_name>{} <serials>{}".format(
- request.hostname, request.manifest_branch,
- request.build_target, request.test_name, request.serial))
-
- if same_jobs:
- job = same_jobs[0]
- job_message = model.JobMessage()
- common_attributes = self.GetCommonAttributes(job, model.JobMessage)
- for attr in common_attributes:
- setattr(job_message, attr, getattr(job, attr))
-
- device_query = model.DeviceModel.query(
- model.DeviceModel.serial.IN(job.serial))
- devices = device_query.fetch()
- logging.debug("[heartbeat] heartbeat job: hostname={}, "
- "test_name={}, job creation time={}".format(
- job.hostname, job.test_name, job.timestamp))
- logging.debug("[heartbeat] request status: {}".format(
- request.status))
- logging.debug("[heartbeat] - devices = {}".format(
- ", ".join([device.serial for device in devices])))
- devices_to_put = []
- if request.status == Status.JOB_STATUS_DICT["complete"]:
- job.status = request.status
- for device in devices:
- device.scheduling_status = (
- Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
- devices_to_put.append(device)
- elif (request.status in [
- Status.JOB_STATUS_DICT["infra-err"],
- Status.JOB_STATUS_DICT["bootup-err"]
- ]):
- job.status = request.status
- email_util.send_job_notification(job)
- for device in devices:
- device.scheduling_status = (
- Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
- device.status = Status.DEVICE_STATUS_DICT["unknown"]
- devices_to_put.append(device)
- elif request.status == Status.JOB_STATUS_DICT["leased"]:
- job.status = request.status
- for device in devices:
- device.timestamp = datetime.datetime.now()
- devices_to_put.append(device)
- else:
- logging.error(
- "[heartbeat] Unexpected job status is received. - {}".
- format(request.serial))
- if devices_to_put:
- ndb.put_multi(devices_to_put)
-
- if request.infra_log_url:
- if request.infra_log_url.startswith(GCS_URL_PREFIX):
- url = "{}{}".format(
- STORAGE_API_URL,
- request.infra_log_url[len(GCS_URL_PREFIX):])
- job.infra_log_url = url
- elif re.match(HTTP_HTTPS_REGEX, request.infra_log_url):
- job.infra_log_url = request.infra_log_url
- else:
- logging.debug("[heartbeat] Wrong infra_log_url address.")
-
- job.heartbeat_stamp = datetime.datetime.now()
- job.put()
- model_util.UpdateParentSchedule(job, request.status)
- return model.JobLeaseResponse(
- return_code=model.ReturnCodeMessage.SUCCESS,
- jobs=[job_message])
-
- return model.JobLeaseResponse(
- return_code=model.ReturnCodeMessage.FAIL, jobs=[])
-
- @endpoints.method(
- endpoint_base.GET_REQUEST_RESOURCE,
- model.JobResponseMessage,
- path="get",
- http_method="POST",
- name="get")
- def get(self, request):
- """Gets the jobs from datastore."""
- return_list, more = self.Get(request=request,
- metaclass=model.JobModel,
- message=model.JobMessage)
-
- return model.JobResponseMessage(jobs=return_list, has_next=more)
-
- @endpoints.method(
- endpoint_base.COUNT_REQUEST_RESOURCE,
- model.CountResponseMessage,
- path="count",
- http_method="POST",
- name="count")
- def count(self, request):
- """Gets total number of JobModel entities stored in datastore."""
- filters = self.CreateFilterList(
- filter_string=request.filter, metaclass=model.JobModel)
- count = self.Count(metaclass=model.JobModel, filters=filters)
-
- return model.CountResponseMessage(count=count)
diff --git a/gae/webapp/src/endpoint/job_queue_test.py b/gae/webapp/src/endpoint/job_queue_test.py
deleted file mode 100644
index 140c4f4..0000000
--- a/gae/webapp/src/endpoint/job_queue_test.py
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import job_queue
-from webapp.src.proto import model
-from webapp.src.testing import unittest_base
-
-
-class JobQueueTest(unittest_base.UnitTestBase):
- """A class to test job_queue endpoint API."""
-
- def setUp(self):
- """Initializes test"""
- super(JobQueueTest, self).setUp()
-
- def testGetJobModel(self):
- """Asserts job_queue/get API receives a job lease request."""
- test_values = {
- "test_type": Status.TEST_TYPE_DICT[Status.TEST_TYPE_TOT],
- "hostname": self.GetRandomString(),
- "priority": self.GetRandomString(),
- "test_name": self.GetRandomString(),
- "require_signed_device_build": False,
- "has_bootloader_img": True,
- "has_radio_img": False,
- "device": self.GetRandomString(),
- "serial": ["serial01", "serial02"],
- "build_storage_type": Status.STORAGE_TYPE_DICT["GCS"],
- "manifest_branch": self.GetRandomString(),
- "build_target": self.GetRandomString(),
- "build_id": self.GetRandomString(),
- "pab_account_id": self.GetRandomString(),
- "shards": 1,
- "param": [""],
- "status": Status.JOB_STATUS_DICT["ready"],
- "period": 360,
- "gsi_storage_type": Status.STORAGE_TYPE_DICT["GCS"],
- "gsi_branch": self.GetRandomString(),
- "gsi_build_target": self.GetRandomString(),
- "gsi_build_id": self.GetRandomString(),
- "gsi_pab_account_id": self.GetRandomString(),
- "gsi_vendor_version": self.GetRandomString(),
- "test_storage_type": Status.STORAGE_TYPE_DICT["GCS"],
- "test_branch": self.GetRandomString(),
- "test_build_target": self.GetRandomString(),
- "test_build_id": self.GetRandomString(),
- "test_pab_account_id": self.GetRandomString(),
- "retry_count": 2,
- "infra_log_url": self.GetRandomString(),
- "image_package_repo_base": self.GetRandomString(),
- "report_bucket": [self.GetRandomString()],
- "report_spreadsheet_id": [self.GetRandomString()],
- "report_persistent_url": [self.GetRandomString()],
- "report_reference_url": [self.GetRandomString()],
- }
-
- for serial in test_values["serial"]:
- self.GenerateDeviceModel(serial=serial).put()
-
- job = model.JobModel()
- for key in test_values:
- setattr(job, key, test_values[key])
- job.timestamp = datetime.datetime.now()
- job.put()
-
- container = (job_queue.JOB_QUEUE_RESOURCE.combined_message_class(
- hostname=test_values["hostname"]))
- api = job_queue.JobQueueApi()
- response = api.lease(container)
-
- self.assertEqual(response.return_code,
- model.ReturnCodeMessage.SUCCESS)
- self.assertEqual(len(response.jobs), 1)
- for key in test_values:
- if key is "status":
- self.assertEqual(
- getattr(response.jobs[0], key),
- Status.JOB_STATUS_DICT["leased"])
- else:
- self.assertEqual(
- getattr(response.jobs[0], key), test_values[key])
-
- devices = model.DeviceModel.query().fetch()
- for device in devices:
- self.assertEqual(device.scheduling_status,
- Status.DEVICE_SCHEDULING_STATUS_DICT["use"])
-
- # test job heartbeat api
- container = (job_queue.JOB_QUEUE_RESOURCE.combined_message_class(
- hostname=response.jobs[0].hostname,
- manifest_branch=response.jobs[0].manifest_branch,
- build_target=response.jobs[0].build_target,
- test_name=response.jobs[0].test_name,
- serial=response.jobs[0].serial,
- status=response.jobs[0].status,
- ))
- api = job_queue.JobQueueApi()
- response = api.heartbeat(container)
- self.assertEqual(response.return_code,
- model.ReturnCodeMessage.SUCCESS)
-
- jobs = model.JobModel.query().fetch()
- self.assertEqual(len(jobs), 1)
- self.assertEqual(jobs[0].status, Status.JOB_STATUS_DICT["leased"])
- self.assertTrue(datetime.datetime.now() - jobs[0].heartbeat_stamp <
- datetime.timedelta(seconds=1))
-
- # test job heartbeat api to complete the job
- container = (job_queue.JOB_QUEUE_RESOURCE.combined_message_class(
- hostname=response.jobs[0].hostname,
- manifest_branch=response.jobs[0].manifest_branch,
- build_target=response.jobs[0].build_target,
- test_name=response.jobs[0].test_name,
- serial=response.jobs[0].serial,
- status=Status.JOB_STATUS_DICT["complete"],
- ))
- api = job_queue.JobQueueApi()
- response = api.heartbeat(container)
- self.assertEqual(response.return_code,
- model.ReturnCodeMessage.SUCCESS)
-
- jobs = model.JobModel.query().fetch()
- self.assertEqual(len(jobs), 1)
- self.assertEqual(jobs[0].status, Status.JOB_STATUS_DICT["complete"])
- self.assertTrue(datetime.datetime.now() - jobs[0].heartbeat_stamp <
- datetime.timedelta(seconds=1))
-
- devices = model.DeviceModel.query().fetch()
- for device in devices:
- self.assertEqual(device.scheduling_status,
- Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/gae/webapp/src/endpoint/lab_info.py b/gae/webapp/src/endpoint/lab_info.py
deleted file mode 100644
index d42148b..0000000
--- a/gae/webapp/src/endpoint/lab_info.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# Copyright 2017 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Lab Info APIs implemented using Google Cloud Endpoints."""
-
-import datetime
-import endpoints
-import logging
-
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import endpoint_base
-from webapp.src.endpoint import host_info
-from webapp.src.proto import model
-
-LAB_INFO_RESOURCE = endpoints.ResourceContainer(model.LabInfoMessage)
-LAB_HOST_INFO_RESOURCE = endpoints.ResourceContainer(model.LabHostInfoMessage)
-
-
-@endpoints.api(name='lab', version='v1')
-class LabInfoApi(endpoint_base.EndpointBase):
- """Endpoint API for lab_info."""
-
- @endpoints.method(
- LAB_INFO_RESOURCE,
- model.DefaultResponse,
- path="clear",
- http_method="POST",
- name="clear")
- def clear(self, request):
- """Clears lab info in DB."""
- lab_query = model.LabModel.query()
- existing_labs = lab_query.fetch(keys_only=True)
- if existing_labs and len(existing_labs) > 0:
- ndb.delete_multi(existing_labs)
- return model.DefaultResponse(
- return_code=model.ReturnCodeMessage.SUCCESS)
-
- @endpoints.method(
- LAB_INFO_RESOURCE,
- model.DefaultResponse,
- path="set",
- http_method="POST",
- name="set")
- def set(self, request):
- """Sets the lab info based on `request`."""
- if "host" in [x.name for x in request.all_fields()]:
- labs_to_put = []
- for host in request.host:
- duplicate_query = model.LabModel.query(
- model.LabModel.name == request.name,
- model.LabModel.owner == request.owner,
- model.LabModel.hostname == host.hostname)
- duplicates = duplicate_query.fetch()
- if duplicates:
- lab = duplicates[0]
- else:
- lab = model.LabModel()
- lab.name = request.name
- lab.owner = request.owner
- lab.admin = request.admin
- lab.hostname = host.hostname
- lab.ip = host.ip
- lab.script = host.script
-
- null_device_count = 0
- devices_to_put = []
- for config_device in host.device:
- if config_device.product == "null":
- null_device_count += 1
- continue
- if config_device.serial and config_device.product:
- device_query = model.DeviceModel.query(
- model.DeviceModel.serial == config_device.serial)
- devices = device_query.fetch()
- if devices:
- device = devices[0]
- if (device.hostname != host.hostname) and (
- device.status !=
- Status.DEVICE_STATUS_DICT["no-response"]):
- logging.error(
- "{} is alive in another host.".format(
- config_device.serial))
- # TODO: send an alert to lab.admin
- continue
- if device.hostname == host.hostname and set(
- device.device_equipment) == set(
- config_device.device_equipment):
- # no need to update.
- continue
- else:
- device = model.DeviceModel()
- device.status = Status.DEVICE_STATUS_DICT[
- "no-response"]
- device.product = config_device.product
- device.serial = config_device.serial
- device.hostname = host.hostname
- device.scheduling_status = (
- Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
- device.timestamp = datetime.datetime.now()
- device.device_equipment = config_device.device_equipment
- devices_to_put.append(device)
- else:
- logging.error("Lab config does not have device "
- "information correctly; it should "
- "specify device product and serial.")
- if devices_to_put:
- ndb.put_multi(devices_to_put)
-
- lab.timestamp = datetime.datetime.now()
- labs_to_put.append(lab)
-
- if null_device_count > 0:
- host_info.AddNullDevices(host.hostname, null_device_count)
-
- if labs_to_put:
- ndb.put_multi(labs_to_put)
-
- return model.DefaultResponse(
- return_code=model.ReturnCodeMessage.SUCCESS)
-
- @endpoints.method(
- LAB_HOST_INFO_RESOURCE,
- model.DefaultResponse,
- path="set_version",
- http_method="POST",
- name="set_version")
- def set_version(self, request):
- """Sets vtslab version of the host <hostname>"""
- lab_query = model.LabModel.query(
- model.LabModel.hostname == request.hostname)
- labs = lab_query.fetch()
-
- labs_to_put = []
- for lab in labs:
- lab.vtslab_version = request.vtslab_version.split(":")[0]
- labs_to_put.append(lab)
- if labs_to_put:
- ndb.put_multi(labs_to_put)
-
- return model.DefaultResponse(
- return_code=model.ReturnCodeMessage.SUCCESS)
-
- @endpoints.method(
- endpoint_base.GET_REQUEST_RESOURCE,
- model.LabResponseMessage,
- path="get",
- http_method="POST",
- name="get")
- def get(self, request):
- """Gets the labs from datastore."""
- return_list, more = self.Get(request=request,
- metaclass=model.LabModel,
- message=model.LabMessage)
-
- return model.LabResponseMessage(labs=return_list, has_next=more)
-
- @endpoints.method(
- endpoint_base.COUNT_REQUEST_RESOURCE,
- model.CountResponseMessage,
- path="count",
- http_method="POST",
- name="count")
- def count(self, request):
- """Gets total number of BuildModel entities stored in datastore."""
- filters = self.CreateFilterList(
- filter_string=request.filter, metaclass=model.LabModel)
-
- count = self.Count(metaclass=model.LabModel, filters=filters)
-
- return model.CountResponseMessage(count=count)
diff --git a/gae/webapp/src/endpoint/lab_info_test.py b/gae/webapp/src/endpoint/lab_info_test.py
deleted file mode 100644
index 7320c7b..0000000
--- a/gae/webapp/src/endpoint/lab_info_test.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from webapp.src.endpoint import lab_info
-from webapp.src.proto import model
-from webapp.src.testing import unittest_base
-
-
-class LabInfoTest(unittest_base.UnitTestBase):
- """A class to test lab_info endpoint API."""
-
- def setUp(self):
- """Initializes test"""
- super(LabInfoTest, self).setUp()
-
- def testUpdateErrorDevice(self):
- """Asserts that device update does not create a duplicate."""
- device_serial = self.GetRandomString()
- product = self.GetRandomString()
- device_equipment = [self.GetRandomString()]
- device_info = {
- "serial": device_serial,
- "product": product,
- "device_equipment": device_equipment
- }
-
- hostname = self.GetRandomString()
- host_info = {
- "hostname": hostname,
- "ip": self.GetRandomString(),
- "script": self.GetRandomString(),
- "device": [device_info],
- "vtslab_version": self.GetRandomString(),
- "host_equipment": [],
- }
-
- lab_name = self.GetRandomString()
- container = (
- lab_info.LAB_INFO_RESOURCE.combined_message_class(
- name=lab_name,
- owner=self.GetRandomString(),
- admin=[self.GetRandomString()],
- host=[host_info],
- ))
-
- api = lab_info.LabInfoApi()
- api.set(container)
-
- devices = model.DeviceModel.query().fetch()
- self.assertEqual(len(devices), 1)
- self.assertEqual(devices[0].product, product)
-
- # change device product name.
- devices[0].product = "error"
- devices[0].put()
-
- api.set(container)
-
- devices = model.DeviceModel.query().fetch()
- # there should not be duplicates.
- self.assertEqual(len(devices), 1)
- # stored device name should be kept.
- self.assertEqual(devices[0].product, "error")
-
-
- def testUpdateExistingDevice(self):
- """Asserts that device update does not create a duplicate."""
- device_serial = self.GetRandomString()
- product = self.GetRandomString()
- device_equipment = [self.GetRandomString()]
- device_info = {
- "serial": device_serial,
- "product": product,
- "device_equipment": device_equipment,
- }
-
- hostname = self.GetRandomString()
- host_info = {
- "hostname": hostname,
- "ip": self.GetRandomString(),
- "script": self.GetRandomString(),
- "device": [device_info],
- "vtslab_version": self.GetRandomString(),
- "host_equipment": [],
- }
-
- lab_name = self.GetRandomString()
- container = (
- lab_info.LAB_INFO_RESOURCE.combined_message_class(
- name=lab_name,
- owner=self.GetRandomString(),
- admin=[self.GetRandomString()],
- host=[host_info],
- ))
-
- device = self.GenerateDeviceModel(product="error",
- serial=device_serial,
- hostname=hostname)
- device.put()
-
- api = lab_info.LabInfoApi()
- api.set(container)
-
- devices = model.DeviceModel.query().fetch()
- self.assertEqual(len(devices), 1)
-
- # stored device name should be kept.
- self.assertEqual(devices[0].product, "error")
-
- # device equipment should be updated.
- self.assertEqual(set(devices[0].device_equipment),
- set(device_equipment))
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/gae/webapp/src/endpoint/schedule_info.py b/gae/webapp/src/endpoint/schedule_info.py
deleted file mode 100644
index e353902..0000000
--- a/gae/webapp/src/endpoint/schedule_info.py
+++ /dev/null
@@ -1,218 +0,0 @@
-# Copyright 2017 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Schedule Info APIs implemented using Google Cloud Endpoints."""
-
-import datetime
-import endpoints
-
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import endpoint_base
-from webapp.src.proto import model
-from webapp.src.utils import email_util
-
-SCHEDULE_INFO_RESOURCE = endpoints.ResourceContainer(model.ScheduleInfoMessage)
-SCHEDULE_SUSPEND_RESOURCE = endpoints.ResourceContainer(
- model.ScheduleSuspendMessage)
-
-
-@endpoints.api(name="schedule", version="v1")
-class ScheduleInfoApi(endpoint_base.EndpointBase):
- """Endpoint API for schedule_info."""
-
- @endpoints.method(
- SCHEDULE_INFO_RESOURCE,
- model.DefaultResponse,
- path="clear",
- http_method="POST",
- name="clear")
- def clear(self, request):
- """Clears test schedule info in DB."""
- schedule_query = model.ScheduleModel.query(
- model.ScheduleModel.schedule_type != "green")
- existing_schedules = schedule_query.fetch(keys_only=True)
- if existing_schedules and len(existing_schedules) > 0:
- ndb.delete_multi(existing_schedules)
- return model.DefaultResponse(
- return_code=model.ReturnCodeMessage.SUCCESS)
-
- @endpoints.method(
- SCHEDULE_INFO_RESOURCE,
- model.DefaultResponse,
- path="set",
- http_method="POST",
- name="set")
- def set(self, request):
- """Sets the schedule info based on `request`."""
- exist_on_both = self.GetCommonAttributes(request, model.ScheduleModel)
- # check duplicates
- exclusions = [
- "name", "schedule_type", "schedule", "param", "timestamp",
- "children_jobs", "error_count", "suspended"
- ]
- # list of protorpc message fields.
- duplicate_checklist = [x for x in exist_on_both if x not in exclusions]
- empty_list_field = []
- query = model.ScheduleModel.query()
- for attr_name in duplicate_checklist:
- if model.ScheduleModel._properties[attr_name]._repeated:
- value = request.get_assigned_value(attr_name)
- if value:
- query = query.filter(
- getattr(model.ScheduleModel, attr_name).IN(
- request.get_assigned_value(attr_name)))
- else:
- # empty list cannot be queried.
- empty_list_field.append(attr_name)
- else:
- query = query.filter(
- getattr(model.ScheduleModel, attr_name) ==
- request.get_assigned_value(attr_name))
- duplicated_schedules = query.fetch()
-
- if empty_list_field:
- duplicated_schedules = [
- schedule for schedule in duplicated_schedules
- if all(
- [not getattr(schedule, attr) for attr in empty_list_field])
- ]
-
- if duplicated_schedules:
- schedule = duplicated_schedules[0]
- else:
- schedule = model.ScheduleModel()
- for attr_name in exist_on_both:
- setattr(schedule, attr_name,
- request.get_assigned_value(attr_name))
- schedule.schedule_type = "test"
- schedule.error_count = 0
- schedule.suspended = False
- schedule.priority_value = Status.GetPriorityValue(schedule.priority)
-
- schedule.timestamp = datetime.datetime.now()
- schedule.put()
-
- return model.DefaultResponse(
- return_code=model.ReturnCodeMessage.SUCCESS)
-
- @endpoints.method(
- endpoint_base.GET_REQUEST_RESOURCE,
- model.ScheduleResponseMessage,
- path="get",
- http_method="POST",
- name="get")
- def get(self, request):
- """Gets the schedules from datastore."""
- return_list, more = self.Get(request=request,
- metaclass=model.ScheduleModel,
- message=model.ScheduleInfoMessage)
-
- return model.ScheduleResponseMessage(
- schedules=return_list, has_next=more)
-
- @endpoints.method(
- endpoint_base.COUNT_REQUEST_RESOURCE,
- model.CountResponseMessage,
- path="count",
- http_method="POST",
- name="count")
- def count(self, request):
- """Gets total number of ScheduleModel entities stored in datastore."""
- filters = self.CreateFilterList(
- filter_string=request.filter, metaclass=model.ScheduleModel)
-
- count = self.Count(metaclass=model.ScheduleModel, filters=filters)
-
- return model.CountResponseMessage(count=count)
-
- @endpoints.method(
- SCHEDULE_SUSPEND_RESOURCE,
- model.ScheduleSuspendMessage,
- path="suspend",
- http_method="POST",
- name="suspend")
- def suspend(self, request):
- """Toggles a schedule from suspend to resume, or vice versa."""
- schedules_to_put = []
- schedules_to_return = []
- for schedule in request.schedules:
- schedule_key = ndb.key.Key(urlsafe=schedule.urlsafe_key)
- schedule_entity = schedule_key.get()
- if schedule.suspend: # to suspend
- schedule_entity.suspended = True
- else: # to resume
- schedule_entity.error_count = 0
- schedule_entity.suspended = False
- schedules_to_put.append(schedule_entity)
- schedules_to_return.append({"urlsafe_key": schedule.urlsafe_key,
- "suspend": schedule_entity.suspended})
- # TODO(jongmok): Minimize a number of emails by merging schedules.
- email_util.send_schedule_suspension_notification(schedule_entity)
-
- ndb.put_multi(schedules_to_put)
- return model.ScheduleSuspendMessage(schedules=schedules_to_return)
-
-
-@endpoints.api(name="green_schedule_info", version="v1")
-class GreenScheduleInfoApi(endpoint_base.EndpointBase):
- """Endpoint API for green_schedule_info."""
-
- @endpoints.method(
- SCHEDULE_INFO_RESOURCE,
- model.DefaultResponse,
- path="clear",
- http_method="POST",
- name="clear")
- def clear(self, request):
- """Clears green build schedule info in DB."""
- schedule_query = model.ScheduleModel.query(
- model.ScheduleModel.schedule_type == "green")
- existing_schedules = schedule_query.fetch(keys_only=True)
- if existing_schedules and len(existing_schedules) > 0:
- ndb.delete_multi(existing_schedules)
- return model.DefaultResponse(
- return_code=model.ReturnCodeMessage.SUCCESS)
-
- @endpoints.method(
- SCHEDULE_INFO_RESOURCE,
- model.DefaultResponse,
- path="set",
- http_method="POST",
- name="set")
- def set(self, request):
- """Sets the green build schedule info based on `request`."""
- schedule = model.ScheduleModel()
- schedule.name = request.name
- schedule.manifest_branch = request.manifest_branch
- schedule.build_target = request.build_target
- schedule.device_pab_account_id = request.device_pab_account_id
- schedule.test_name = request.test_name
- schedule.schedule = request.schedule
- schedule.priority = request.priority
- schedule.device = request.device
- schedule.shards = request.shards
- schedule.gsi_branch = request.gsi_branch
- schedule.gsi_build_target = request.gsi_build_target
- schedule.gsi_pab_account_id = request.gsi_pab_account_id
- schedule.gsi_vendor_version = request.gsi_vendor_version
- schedule.test_branch = request.test_branch
- schedule.test_build_target = request.test_build_target
- schedule.test_pab_account_id = request.test_pab_account_id
- schedule.timestamp = datetime.datetime.now()
- schedule.schedule_type = "green"
- schedule.put()
-
- return model.DefaultResponse(
- return_code=model.ReturnCodeMessage.SUCCESS)
diff --git a/gae/webapp/src/endpoint/schedule_info_test.py b/gae/webapp/src/endpoint/schedule_info_test.py
deleted file mode 100644
index 61e69ae..0000000
--- a/gae/webapp/src/endpoint/schedule_info_test.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.endpoint import schedule_info
-from webapp.src.proto import model
-from webapp.src.testing import unittest_base
-
-
-class ScheduleInfoTest(unittest_base.UnitTestBase):
- """A class to test schedule_info endpoint API."""
-
- def setUp(self):
- """Initializes test"""
- super(ScheduleInfoTest, self).setUp()
-
- def testSetWithSimpleMessage(self):
- """Asserts schedule_info/set API receives a simple message."""
- # As of June 8, 2018, these are uploaded from host controller.
- container = (
- schedule_info.SCHEDULE_INFO_RESOURCE.combined_message_class(
- manifest_branch=self.GetRandomString(),
- build_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
- build_target=self.GetRandomString(),
- require_signed_device_build=False,
- has_bootloader_img=True,
- has_radio_img=True,
- test_name=self.GetRandomString(),
- period=360,
- priority="high",
- device=[self.GetRandomString()],
- required_host_equipment=[self.GetRandomString()],
- required_device_equipment=[self.GetRandomString()],
- device_pab_account_id=self.GetRandomString(),
- shards=1,
- param=[self.GetRandomString()],
- retry_count=1,
- gsi_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
- gsi_branch=self.GetRandomString(),
- gsi_build_target=self.GetRandomString(),
- gsi_pab_account_id=self.GetRandomString(),
- gsi_vendor_version=self.GetRandomString(),
- test_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
- test_branch=self.GetRandomString(),
- test_build_target=self.GetRandomString(),
- test_pab_account_id=self.GetRandomString(),
- image_package_repo_base=self.GetRandomString(),
- report_bucket=[self.GetRandomString()],
- report_spreadsheet_id=[self.GetRandomString()],
- report_persistent_url=[self.GetRandomString()],
- report_reference_url=[self.GetRandomString()],
- ))
- api = schedule_info.ScheduleInfoApi()
- response = api.set(container)
-
- self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
-
- def testSetWithEmptyRepeatedField(self):
- """Asserts schedule_info/set API receives a message.
-
- This test sets required_host_equipment to empty and sends to endpoint
- method.
- """
- # As of June 8, 2018, these are uploaded from host controller.
- container = (
- schedule_info.SCHEDULE_INFO_RESOURCE.combined_message_class(
- manifest_branch=self.GetRandomString(),
- build_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
- build_target=self.GetRandomString(),
- require_signed_device_build=False,
- has_bootloader_img=True,
- has_radio_img=True,
- test_name=self.GetRandomString(),
- period=360,
- priority="high",
- device=[self.GetRandomString()],
- required_host_equipment=[self.GetRandomString()],
- required_device_equipment=[self.GetRandomString()],
- device_pab_account_id=self.GetRandomString(),
- shards=1,
- param=[self.GetRandomString()],
- retry_count=1,
- gsi_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
- gsi_branch=self.GetRandomString(),
- gsi_build_target=self.GetRandomString(),
- gsi_pab_account_id=self.GetRandomString(),
- gsi_vendor_version=self.GetRandomString(),
- test_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
- test_branch=self.GetRandomString(),
- test_build_target=self.GetRandomString(),
- test_pab_account_id=self.GetRandomString(),
- image_package_repo_base=self.GetRandomString(),
- report_bucket=[],
- report_spreadsheet_id=[],
- report_persistent_url=[],
- report_reference_url=[],
- ))
- api = schedule_info.ScheduleInfoApi()
- response = api.set(container)
-
- self.assertEqual(response.return_code, model.ReturnCodeMessage.SUCCESS)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/gae/webapp/src/endpoint_main.py b/gae/webapp/src/endpoint_main.py
deleted file mode 100644
index 090d6d6..0000000
--- a/gae/webapp/src/endpoint_main.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import endpoints
-
-from webapp.src.endpoint import build_info
-from webapp.src.endpoint import host_info
-from webapp.src.endpoint import job_queue
-from webapp.src.endpoint import lab_info
-from webapp.src.endpoint import schedule_info
-
-api = endpoints.api_server([
- build_info.BuildInfoApi,
- host_info.HostInfoApi,
- lab_info.LabInfoApi,
- schedule_info.ScheduleInfoApi,
- schedule_info.GreenScheduleInfoApi,
- job_queue.JobQueueApi])
diff --git a/gae/webapp/src/handlers/__init__.py b/gae/webapp/src/handlers/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/handlers/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/handlers/base.py b/gae/webapp/src/handlers/base.py
deleted file mode 100644
index 2862ecb..0000000
--- a/gae/webapp/src/handlers/base.py
+++ /dev/null
@@ -1,215 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import httplib
-import logging
-import os
-import urlparse
-
-from google.appengine.api import users
-import stripe
-import webapp2
-from webapp2_extras import jinja2 as wa2_jinja2
-from webapp2_extras import sessions
-
-import errors
-from webapp.src.utils import datetime_util
-
-
-class BaseHandler(webapp2.RequestHandler):
- """BaseHandler for all requests."""
-
- def initialize(self, request, response):
- """Initializes this request handler."""
- webapp2.RequestHandler.initialize(self, request, response)
- self.session_backend = 'datastore'
-
- def verify_origin(self):
- """This function will check the request is comming from the same domain."""
- server_host = os.environ.get('ENDPOINTS_SERVICE_NAME')
- request_host = self.request.headers.get('Host')
- request_referer = self.request.headers.get('Referer')
- if request_referer:
- request_referer = urlparse.urlsplit(request_referer)[1]
- else:
- request_referer = request_host
- logging.info('server: %s, request: %s', server_host, request_referer)
- if server_host and request_referer and server_host != request_referer:
- raise errors.Error(httplib.FORBIDDEN)
-
- def dispatch(self):
- """Dispatch the request.
-
- This will first check if there's a handler_method defined
- in the matched route, and if not it'll use the method correspondent to
- the request method (get(), post() etc).
- """
- self.session_store = sessions.get_store(request=self.request)
- # Forwards the method for RESTful support.
- self.forward_method()
- # Security headers.
- # https://www.owasp.org/index.php/List_of_useful_HTTP_headers
- self.response.headers['x-content-type-options'] = 'nosniff'
- self.response.headers['x-frame-options'] = 'SAMEORIGIN'
- self.response.headers['x-xss-protection'] = '1; mode=block'
- try:
- webapp2.RequestHandler.dispatch(self)
- finally:
- self.session_store.save_sessions(self.response)
- # Disabled for now because host is appspot.com in production.
- #self.verify_origin()
-
- @webapp2.cached_property
- def session(self):
- # Returns a session using the default cookie key.
- return self.session_store.get_session()
-
- def handle_exception(self, exception, debug=False):
- """Render the exception as HTML."""
- logging.exception(exception)
-
- # Create response dictionary and status defaults.
- tpl = 'error.html'
- status = httplib.INTERNAL_SERVER_ERROR
- resp_dict = {
- 'message': 'A server error occurred.',
- }
- url_parts = self.urlsplit()
- redirect_url = '%s?%s' % (url_parts[2], url_parts[4])
-
- # Use error code if a HTTPException, or generic 500.
- if isinstance(exception, webapp2.HTTPException):
- status = exception.code
- resp_dict['message'] = exception.detail
- elif isinstance(exception, errors.FormValidationError):
- status = exception.code
- resp_dict['message'] = exception.msg
- resp_dict['errors'] = exception.errors
- self.session['form_errors'] = exception.errors
- # Redirect user to current view URL.
- return self.redirect(redirect_url)
- elif isinstance(exception, stripe.StripeError):
- status = exception.http_status
- resp_dict['errors'] = exception.json_body['error']['message']
- self.session['form_errors'] = [
- exception.json_body['error']['message']
- ]
- return self.redirect(redirect_url)
- elif isinstance(exception, (errors.Error, errors.AclError)):
- status = exception.code
- resp_dict['message'] = exception.msg
-
- resp_dict['status'] = status
-
- # Render output.
- self.response.status_int = status
- self.response.status_message = httplib.responses[status]
- # Render the exception response into the error template.
- self.response.write(self.jinja2.render_template(tpl, **resp_dict))
-
- # @Override
- def get(self, *args, **kwargs):
- self.abort(httplib.NOT_IMPLEMENTED)
-
- # @Override
- def post(self, *args, **kwargs):
- self.abort(httplib.NOT_IMPLEMENTED)
-
- # @Override
- def put(self, *args, **kwargs):
- self.abort(httplib.NOT_IMPLEMENTED)
-
- # @Override
- def delete(self, *args, **kwargs):
- self.abort(httplib.NOT_IMPLEMENTED)
-
- # @Override
- def head(self, *args, **kwargs):
- pass
-
- def urlsplit(self):
- """Return a tuple of the URL."""
- return urlparse.urlsplit(self.request.url)
-
- def path(self):
- """Returns the path of the current URL."""
- return self.urlsplit()[2]
-
- def forward_method(self):
- """Check for a method override param and change in the request."""
- valid = (None, 'get', 'post', 'put', 'delete', 'head', 'options')
- method = self.request.POST.get('__method__')
- if not method: # Backbone's _method parameter.
- method = self.request.POST.get('_method')
- if method not in valid:
- logging.debug('Invalid method %s requested!', method)
- method = None
- logging.debug('Method being changed from %s to %s by request',
- self.request.route.handler_method, method)
- self.request.route.handler_method = method
-
- def render(self, resp, status=httplib.OK):
- """Render the response as HTML."""
- user = users.get_current_user()
- if user:
- url = users.create_logout_url(self.request.uri)
- url_linktext = "Logout"
- else:
- url = users.create_login_url(self.request.uri)
- url_linktext = "Login"
-
- resp.update({
- # Defaults go here.
- 'now': datetime.datetime.now(),
- 'dest_url': str(self.request.get('dest_url', '')),
- 'form_errors': self.session.pop('form_errors', []),
- 'user': user,
- 'url': url,
- 'url_linktext': url_linktext,
- "convert_time": datetime_util.GetTimeWithTimezone
- })
-
- if 'preload' not in resp:
- resp['preload'] = {}
-
- self.response.status_int = status
- self.response.status_message = httplib.responses[status]
- self.response.write(self.jinja2.render_template(self.template, **resp))
-
- @webapp2.cached_property
- def jinja2(self):
- """Returns a Jinja2 renderer cached in the app registry."""
- jinja_config = {
- 'template_path':
- os.path.join(os.path.dirname(__file__), "../../static"),
- 'compiled_path':
- None,
- 'force_compiled':
- False,
- 'environment_args': {
- 'autoescape': True,
- 'extensions': [
- 'jinja2.ext.autoescape',
- 'jinja2.ext.with_',
- ],
- },
- 'globals':
- None,
- 'filters':
- None,
- }
- return wa2_jinja2.Jinja2(app=self.app, config=jinja_config)
diff --git a/gae/webapp/src/handlers/errors.py b/gae/webapp/src/handlers/errors.py
deleted file mode 100644
index fde95c0..0000000
--- a/gae/webapp/src/handlers/errors.py
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import httplib
-
-
-class Error(Exception):
- """Base Exception for handlers.
-
- Attributes:
- code: HTTP 1.1 status code
- msg: the W3C names for HTTP 1.1 status code
- """
-
- def __init__(self, code=None, msg=None):
- self.code = code or httplib.INTERNAL_SERVER_ERROR
- self.msg = msg or httplib.responses[self.code]
- super(Error, self).__init__(self.code, self.msg)
-
- def __str__(self):
- return repr([self.code, self.msg])
-
-
-class FormValidationError(Error):
- """Form Validtion Exception for handlers."""
-
- def __init__(self, code=None, msg=None, errors=None):
- self.code = code or httplib.BAD_REQUEST
- self.msg = msg or httplib.responses[self.code]
- self.errors = errors or []
- super(FormValidationError, self).__init__(self.code, self.msg)
-
- def __str__(self):
- return repr([self.code, self.msg, self.errors])
-
-
-class AclError(Error):
- """Base ACL error."""
-
- def __init__(self, code):
- self.code = code
- self.msg = httplib.responses[code]
- super(AclError, self).__init__(self.code, self.msg)
-
- def __str__(self):
- return repr([self.code, self.msg])
-
-
-class NotFoundError(AclError):
- """The item being access does not exist."""
-
- def __init__(self):
- super(NotFoundError, self).__init__(httplib.NOT_FOUND)
-
-
-class UnauthorizedError(AclError):
- """The current user is not authenticated."""
-
- def __init__(self):
- super(UnauthorizedError, self).__init__(httplib.UNAUTHORIZED)
-
-
-class ForbiddenError(AclError):
- """The current user does not have proper permission."""
-
- def __init__(self):
- super(ForbiddenError, self).__init__(httplib.FORBIDDEN)
diff --git a/gae/webapp/src/proto/__init__.py b/gae/webapp/src/proto/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/proto/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/proto/model.py b/gae/webapp/src/proto/model.py
deleted file mode 100644
index 1b24154..0000000
--- a/gae/webapp/src/proto/model.py
+++ /dev/null
@@ -1,449 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-from google.appengine.ext import ndb
-
-from protorpc import messages
-from protorpc import message_types
-
-
-class BuildModel(ndb.Model):
- """A model for representing an individual build entry."""
- manifest_branch = ndb.StringProperty()
- build_id = ndb.StringProperty()
- build_target = ndb.StringProperty()
- build_type = ndb.StringProperty()
- artifact_type = ndb.StringProperty()
- artifacts = ndb.StringProperty(repeated=True)
- timestamp = ndb.DateTimeProperty(auto_now=False)
- signed = ndb.BooleanProperty()
-
-
-class BuildInfoMessage(messages.Message):
- """A message for representing an individual build entry."""
- manifest_branch = messages.StringField(1)
- build_id = messages.StringField(2)
- build_target = messages.StringField(3)
- build_type = messages.StringField(4)
- artifact_type = messages.StringField(5)
- artifacts = messages.StringField(6, repeated=True)
- signed = messages.BooleanField(7)
- timestamp = message_types.DateTimeField(8)
-
-
-class ScheduleControlModel(ndb.Model):
- """A model for representing a schedule control data entry."""
- enabled = ndb.BooleanProperty()
- # "global" or empty string to enable/disable all schedules.
- schedule_name = ndb.StringProperty()
-
-
-class ScheduleModel(ndb.Model):
- """A model for representing an individual schedule entry."""
- # schedule name for green build schedule, optional.
- name = ndb.StringProperty()
- schedule_type = ndb.StringProperty()
-
- # device image information
- build_storage_type = ndb.IntegerProperty()
- manifest_branch = ndb.StringProperty()
- build_target = ndb.StringProperty() # type:name
- device_pab_account_id = ndb.StringProperty()
- require_signed_device_build = ndb.BooleanProperty()
- has_bootloader_img = ndb.BooleanProperty(default=True)
- has_radio_img = ndb.BooleanProperty(default=True)
-
- # GSI information
- gsi_storage_type = ndb.IntegerProperty()
- gsi_branch = ndb.StringProperty()
- gsi_build_target = ndb.StringProperty()
- gsi_pab_account_id = ndb.StringProperty()
- gsi_vendor_version = ndb.StringProperty()
-
- # test suite information
- test_storage_type = ndb.IntegerProperty()
- test_branch = ndb.StringProperty()
- test_build_target = ndb.StringProperty()
- test_pab_account_id = ndb.StringProperty()
-
- test_name = ndb.StringProperty()
- period = ndb.IntegerProperty()
- schedule = ndb.StringProperty()
- priority = ndb.StringProperty()
- priority_value = ndb.IntegerProperty()
- device = ndb.StringProperty(repeated=True)
- shards = ndb.IntegerProperty()
- param = ndb.StringProperty(repeated=True)
- timestamp = ndb.DateTimeProperty(auto_now=False)
- retry_count = ndb.IntegerProperty()
-
- children_jobs = ndb.KeyProperty(kind="JobModel", repeated=True)
- error_count = ndb.IntegerProperty()
- suspended = ndb.BooleanProperty()
- image_package_repo_base = ndb.StringProperty()
-
- required_host_equipment = ndb.StringProperty(repeated=True)
- required_device_equipment = ndb.StringProperty(repeated=True)
-
- report_bucket = ndb.StringProperty(repeated=True)
- report_spreadsheet_id = ndb.StringProperty(repeated=True)
- report_persistent_url = ndb.StringProperty(repeated=True)
- report_reference_url = ndb.StringProperty(repeated=True)
-
- owner = ndb.StringProperty(repeated=True)
-
-
-class ScheduleControlInfoMessage(messages.Message):
- """A message for representing a schedule control data entry."""
- enabled = messages.BooleanField(1)
- schedule_name = messages.StringField(2)
-
-
-class ScheduleInfoMessage(messages.Message):
- """A message for representing an individual schedule entry."""
- # Next ID = 39
- # schedule name for green build schedule, optional.
- name = messages.StringField(16)
- schedule_type = messages.StringField(19)
-
- # device image information
- build_storage_type = messages.IntegerField(21)
- manifest_branch = messages.StringField(1)
- build_target = messages.StringField(2)
- device_pab_account_id = messages.StringField(17)
- require_signed_device_build = messages.BooleanField(20)
- has_bootloader_img = messages.BooleanField(27)
- has_radio_img = messages.BooleanField(28)
-
- # GSI information
- gsi_storage_type = messages.IntegerField(22)
- gsi_branch = messages.StringField(9)
- gsi_build_target = messages.StringField(10)
- gsi_pab_account_id = messages.StringField(11)
- gsi_vendor_version = messages.StringField(24)
-
- # test suite information
- test_storage_type = messages.IntegerField(23)
- test_branch = messages.StringField(12)
- test_build_target = messages.StringField(13)
- test_pab_account_id = messages.StringField(14)
-
- test_name = messages.StringField(3)
- period = messages.IntegerField(4)
- schedule = messages.StringField(18)
- priority = messages.StringField(5)
- device = messages.StringField(6, repeated=True)
- shards = messages.IntegerField(7)
- param = messages.StringField(8, repeated=True)
- retry_count = messages.IntegerField(15)
-
- required_host_equipment = messages.StringField(25, repeated=True)
- required_device_equipment = messages.StringField(26, repeated=True)
-
- report_bucket = messages.StringField(29, repeated=True)
- report_spreadsheet_id = messages.StringField(30, repeated=True)
- report_persistent_url = messages.StringField(32, repeated=True)
- report_reference_url = messages.StringField(33, repeated=True)
-
- image_package_repo_base = messages.StringField(31)
- timestamp = message_types.DateTimeField(34)
- owner = messages.StringField(35, repeated=True)
-
- suspended = messages.BooleanField(36)
- urlsafe_key = messages.StringField(37)
- error_count = messages.IntegerField(38)
-
-
-class LabModel(ndb.Model):
- """A model for representing an individual lab entry."""
- name = ndb.StringProperty()
- owner = ndb.StringProperty()
- admin = ndb.StringProperty(repeated=True)
- hostname = ndb.StringProperty()
- ip = ndb.StringProperty()
- # devices is a comma-separated list of serial=product pairs
- devices = ndb.StringProperty()
- timestamp = ndb.DateTimeProperty(auto_now=False)
- vtslab_version = ndb.StringProperty()
- host_equipment = ndb.StringProperty(repeated=True)
-
-
-class LabDeviceInfoMessage(messages.Message):
- """A message for representing an individual lab host's device entry."""
- serial = messages.StringField(1, repeated=False)
- product = messages.StringField(2, repeated=False)
- device_equipment = messages.StringField(3, repeated=True)
-
-
-class LabHostInfoMessage(messages.Message):
- """A message for representing an individual lab's host entry."""
- hostname = messages.StringField(1, repeated=False)
- ip = messages.StringField(2, repeated=False)
- script = messages.StringField(3)
- device = messages.MessageField(LabDeviceInfoMessage, 4, repeated=True)
- vtslab_version = messages.StringField(5)
- host_equipment = messages.StringField(6, repeated=True)
-
-
-class LabInfoMessage(messages.Message):
- """A message for representing an individual lab entry."""
- name = messages.StringField(1)
- owner = messages.StringField(2)
- admin = messages.StringField(4, repeated=True)
- host = messages.MessageField(LabHostInfoMessage, 3, repeated=True)
-
-
-class LabMessage(messages.Message):
- """A model for representing a LabModel entity."""
- name = messages.StringField(1)
- owner = messages.StringField(2)
- admin = messages.StringField(3, repeated=True)
- hostname = messages.StringField(4)
- ip = messages.StringField(5)
- devices = messages.StringField(6)
- vtslab_version = messages.StringField(7)
- host_equipment = messages.StringField(8, repeated=True)
-
-
-class DeviceModel(ndb.Model):
- """A model for representing an individual device entry."""
- hostname = ndb.StringProperty()
- product = ndb.StringProperty()
- serial = ndb.StringProperty()
- status = ndb.IntegerProperty()
- scheduling_status = ndb.IntegerProperty()
- timestamp = ndb.DateTimeProperty(auto_now=False)
- device_equipment = ndb.StringProperty(repeated=True)
-
-
-class DeviceInfoMessage(messages.Message):
- """A message for representing an individual host's device entry."""
- serial = messages.StringField(1)
- product = messages.StringField(2)
- status = messages.IntegerField(3)
- scheduling_status = messages.IntegerField(4)
- hostname = messages.StringField(5)
- device_equipment = messages.StringField(6, repeated=True)
- timestamp = message_types.DateTimeField(7)
-
-
-class HostInfoMessage(messages.Message):
- """A message for representing an individual host entry."""
- hostname = messages.StringField(1)
- devices = messages.MessageField(DeviceInfoMessage, 2, repeated=True)
-
-
-class JobModel(ndb.Model):
- """A model for representing an individual job entry."""
- test_type = ndb.IntegerProperty()
-
- hostname = ndb.StringProperty()
- priority = ndb.StringProperty()
- test_name = ndb.StringProperty()
- require_signed_device_build = ndb.BooleanProperty()
- has_bootloader_img = ndb.BooleanProperty()
- has_radio_img = ndb.BooleanProperty()
- device = ndb.StringProperty()
- serial = ndb.StringProperty(repeated=True)
-
- # device image information
- build_storage_type = ndb.IntegerProperty()
- manifest_branch = ndb.StringProperty()
- build_target = ndb.StringProperty()
- build_id = ndb.StringProperty()
- pab_account_id = ndb.StringProperty()
-
- shards = ndb.IntegerProperty()
- param = ndb.StringProperty(repeated=True)
- status = ndb.IntegerProperty()
- period = ndb.IntegerProperty()
-
- # GSI information
- gsi_storage_type = ndb.IntegerProperty()
- gsi_branch = ndb.StringProperty()
- gsi_build_target = ndb.StringProperty()
- gsi_build_id = ndb.StringProperty()
- gsi_pab_account_id = ndb.StringProperty()
- gsi_vendor_version = ndb.StringProperty()
-
- # test suite information
- test_storage_type = ndb.IntegerProperty()
- test_branch = ndb.StringProperty()
- test_build_target = ndb.StringProperty()
- test_build_id = ndb.StringProperty()
- test_pab_account_id = ndb.StringProperty()
-
- timestamp = ndb.DateTimeProperty(auto_now=False)
- heartbeat_stamp = ndb.DateTimeProperty(auto_now=False)
- retry_count = ndb.IntegerProperty()
-
- infra_log_url = ndb.StringProperty()
-
- parent_schedule = ndb.KeyProperty(kind="ScheduleModel")
-
- image_package_repo_base = ndb.StringProperty()
-
- report_bucket = ndb.StringProperty(repeated=True)
- report_spreadsheet_id = ndb.StringProperty(repeated=True)
- report_persistent_url = ndb.StringProperty(repeated=True)
- report_reference_url = ndb.StringProperty(repeated=True)
-
-
-class JobMessage(messages.Message):
- """A message for representing an individual job entry."""
- # Next ID = 39
- test_type = messages.IntegerField(29)
-
- hostname = messages.StringField(1)
- priority = messages.StringField(2)
- test_name = messages.StringField(3)
- require_signed_device_build = messages.BooleanField(23)
- has_bootloader_img = messages.BooleanField(31)
- has_radio_img = messages.BooleanField(32)
- device = messages.StringField(4)
- serial = messages.StringField(5, repeated=True)
-
- # device image information
- build_storage_type = messages.IntegerField(25)
- manifest_branch = messages.StringField(6)
- build_target = messages.StringField(7)
- build_id = messages.StringField(10)
- pab_account_id = messages.StringField(20)
-
- shards = messages.IntegerField(8)
- param = messages.StringField(9, repeated=True)
- status = messages.IntegerField(11)
- period = messages.IntegerField(12)
-
- # GSI information
- gsi_storage_type = messages.IntegerField(26)
- gsi_branch = messages.StringField(13)
- gsi_build_target = messages.StringField(14)
- gsi_build_id = messages.StringField(21)
- gsi_pab_account_id = messages.StringField(15)
- gsi_vendor_version = messages.StringField(28)
-
- # test suite information
- test_storage_type = messages.IntegerField(27)
- test_branch = messages.StringField(16)
- test_build_target = messages.StringField(17)
- test_build_id = messages.StringField(22)
- test_pab_account_id = messages.StringField(18)
-
- retry_count = messages.IntegerField(19)
-
- infra_log_url = messages.StringField(24)
-
- image_package_repo_base = messages.StringField(30)
-
- report_bucket = messages.StringField(33, repeated=True)
- report_spreadsheet_id = messages.StringField(34, repeated=True)
- report_persistent_url = messages.StringField(35, repeated=True)
- report_reference_url = messages.StringField(36, repeated=True)
-
- timestamp = message_types.DateTimeField(37)
- heartbeat_stamp = message_types.DateTimeField(38)
-
-
-class ReturnCodeMessage(messages.Enum):
- """Enum for default return code."""
- SUCCESS = 0
- FAIL = 1
-
-
-class DefaultResponse(messages.Message):
- """A default response proto message."""
- return_code = messages.EnumField(ReturnCodeMessage, 1)
-
-
-class JobLeaseResponse(messages.Message):
- """A job lease response proto message."""
- return_code = messages.EnumField(ReturnCodeMessage, 1)
- jobs = messages.MessageField(JobMessage, 2, repeated=True)
-
-
-class KeyValueModel(ndb.Model):
- """A simple key-value model.
-
- This class uses name as key and store one value or more than one values
- to store values which require continuous monitoring such as counters,
- or flags.
- """
- name = ndb.StringProperty()
- string_value = ndb.StringProperty()
- integer_value = ndb.IntegerProperty()
- boolean_value = ndb.BooleanProperty()
-
-
-class GetRequestMessage(messages.Message):
- """A message to request entities through /get endpoints."""
- size = messages.IntegerField(1)
- offset = messages.IntegerField(2)
- filter = messages.StringField(3)
- sort = messages.StringField(4)
- direction = messages.StringField(5)
-
-
-class BuildResponseMessage(messages.Message):
- """A message containing build entities to respond to /get endpoints."""
- builds = messages.MessageField(BuildInfoMessage, 1, repeated=True)
- has_next = messages.BooleanField(2)
-
-
-class DeviceResponseMessage(messages.Message):
- """A message containing device entities to respond to /get endpoints."""
- devices = messages.MessageField(DeviceInfoMessage, 1, repeated=True)
- has_next = messages.BooleanField(2)
-
-
-class JobResponseMessage(messages.Message):
- """A message containing job entities to respond to /get endpoints."""
- jobs = messages.MessageField(JobMessage, 1, repeated=True)
- has_next = messages.BooleanField(2)
-
-
-class LabResponseMessage(messages.Message):
- """A message containing lab entities to respond to /get endpoints."""
- labs = messages.MessageField(LabMessage, 1, repeated=True)
- has_next = messages.BooleanField(2)
-
-
-class ScheduleResponseMessage(messages.Message):
- """A message containing schedule entities to respond to /get endpoints."""
- schedules = messages.MessageField(ScheduleInfoMessage, 1, repeated=True)
- has_next = messages.BooleanField(2)
-
-
-class CountRequestMessage(messages.Message):
- """A message to request a count of entities through /count endpoints."""
- filter = messages.StringField(1)
-
-
-class CountResponseMessage(messages.Message):
- """A message of a count of entities to respond to /count endpoints."""
- count = messages.IntegerField(1)
-
-
-class ScheduleSuspendMessage(messages.Message):
- """A response message to schedule endpoint API's /suspend method."""
-
- class SingleScheduleSuspendMessage(messages.Message):
- urlsafe_key = messages.StringField(1)
- suspend = messages.BooleanField(2)
-
- schedules = messages.MessageField(
- SingleScheduleSuspendMessage, 1, repeated=True)
diff --git a/gae/webapp/src/scheduler/__init__.py b/gae/webapp/src/scheduler/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/scheduler/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/scheduler/device_heartbeat.py b/gae/webapp/src/scheduler/device_heartbeat.py
deleted file mode 100644
index 730fc5f..0000000
--- a/gae/webapp/src/scheduler/device_heartbeat.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import logging
-import webapp2
-
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.utils import email_util
-from webapp.src.utils import logger
-
-DEVICE_RESPONSE_TIMEOUT_SECONDS = 300
-
-
-class PeriodicDeviceHeartBeat(webapp2.RequestHandler):
- """Main class for /tasks/device_heartbeat.
-
- Used to find lost devices and change their status properly.
-
- Attributes:
- logger: Logger class
- """
- logger = logger.Logger()
-
- def get(self):
- """Generates an HTML page based on the task schedules kept in DB."""
- self.logger.Clear()
-
- device_query = model.DeviceModel.query(
- model.DeviceModel.status !=
- Status.DEVICE_STATUS_DICT["no-response"])
- devices = device_query.fetch()
- lost_devices = [
- x for x in devices
- if (datetime.datetime.now() - x.timestamp
- ).seconds >= DEVICE_RESPONSE_TIMEOUT_SECONDS
- ]
- devices_to_put = []
- labs_to_alert = {}
- for device in lost_devices:
- self.logger.Println("Device[{}] is not responding.".format(
- device.serial))
- device.status = Status.DEVICE_STATUS_DICT["no-response"]
- devices_to_put.append(device)
-
- # sending notification
- lab_query = model.LabModel.query(
- model.LabModel.hostname == device.hostname)
- labs = lab_query.fetch()
- if labs:
- lab = labs[0]
- if lab.name not in labs_to_alert:
- labs_to_alert[lab.name] = {}
- labs_to_alert[lab.name]["_recipients"] = []
- if device.hostname not in labs_to_alert[lab.name]:
- labs_to_alert[lab.name][device.hostname] = []
- if lab.owner not in labs_to_alert[lab.name]["_recipients"]:
- labs_to_alert[lab.name]["_recipients"].append(lab.owner)
- labs_to_alert[lab.name]["_recipients"].extend([
- x for x in lab.admin
- if x not in labs_to_alert[lab.name]["_recipients"]
- ])
- labs_to_alert[lab.name][device.hostname].append(device.serial)
- else:
- logging.warning(
- "Could not find a lab model for hostname {}".format(
- device.hostname))
- continue
-
- if devices_to_put:
- ndb.put_multi(devices_to_put)
- if labs_to_alert:
- email_util.send_device_notification(labs_to_alert)
-
- self.response.write(
- "<pre>\n" + "\n".join(self.logger.Get()) + "\n</pre>")
diff --git a/gae/webapp/src/scheduler/job_heartbeat.py b/gae/webapp/src/scheduler/job_heartbeat.py
deleted file mode 100644
index af8994c..0000000
--- a/gae/webapp/src/scheduler/job_heartbeat.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import logging
-import webapp2
-
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.utils import email_util
-from webapp.src.utils import logger
-from webapp.src.utils import model_util
-
-JOB_RESPONSE_TIMEOUT_SECONDS = 60 * 60
-
-
-class PeriodicJobHeartBeat(webapp2.RequestHandler):
- """Main class for /tasks/job_heartbeat.
-
- Used to find lost jobs and change their status properly.
-
- Attributes:
- logger: Logger class
- """
- logger = logger.Logger()
-
- def get(self):
- """Generates an HTML page based on the jobs kept in DB."""
- self.logger.Clear()
-
- job_query = model.JobModel.query(
- model.JobModel.status == Status.JOB_STATUS_DICT["leased"])
- jobs = job_query.fetch()
-
- lost_jobs = []
- for job in jobs:
- if job.heartbeat_stamp:
- job_timestamp = job.heartbeat_stamp
- else:
- job_timestamp = job.timestamp
- if (datetime.datetime.now() -
- job_timestamp).seconds >= JOB_RESPONSE_TIMEOUT_SECONDS:
- lost_jobs.append(job)
-
- lost_jobs_to_put = []
- devices_to_put = []
- for job in lost_jobs:
- self.logger.Println("Lost job found")
- self.logger.Println("[hostname]{} [device]{} [test_name]{}".format(
- job.hostname, job.device, job.test_name))
- job.status = Status.JOB_STATUS_DICT["infra-err"]
- lost_jobs_to_put.append(job)
- model_util.UpdateParentSchedule(
- job, Status.JOB_STATUS_DICT["infra-err"])
-
- device_query = model.DeviceModel.query(
- model.DeviceModel.serial.IN(job.serial))
- devices = device_query.fetch()
- for device in devices:
- self.logger.Println("Device serial: {}".format(device.serial))
- device.scheduling_status = Status.DEVICE_SCHEDULING_STATUS_DICT[
- "free"]
- devices_to_put.append(device)
-
- if lost_jobs_to_put:
- ndb.put_multi(lost_jobs_to_put)
- email_util.send_job_notification(lost_jobs_to_put)
- self.logger.Println("{} jobs are updated.".format(
- len(lost_jobs_to_put)))
-
- if devices_to_put:
- ndb.put_multi(devices_to_put)
- self.logger.Println("{} devices are updated.".format(
- len(devices_to_put)))
-
- lines = self.logger.Get()
- logging.info("\n".join([line.strip() for line in lines]))
-
- self.response.write("<pre>\n" + "\n".join(lines) + "\n</pre>")
diff --git a/gae/webapp/src/scheduler/job_heartbeat_test.py b/gae/webapp/src/scheduler/job_heartbeat_test.py
deleted file mode 100644
index c9f56a5..0000000
--- a/gae/webapp/src/scheduler/job_heartbeat_test.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.scheduler import job_heartbeat
-from webapp.src.scheduler import schedule_worker
-from webapp.src.testing import unittest_base
-
-
-class JobHeartbeatTest(unittest_base.UnitTestBase):
- """Tests for PeriodicJobHeartBeat cron class.
-
- Attributes:
- testbed: A Testbed instance which provides local unit testing.
- job_heartbeat: A mock job_heartbeat.PeriodicJobHeartBeat instance.
- """
-
- def setUp(self):
- """Initializes test"""
- super(JobHeartbeatTest, self).setUp()
- # Mocking PeriodicJobHeartBeat and essential methods.
- self.job_heartbeat = job_heartbeat.PeriodicJobHeartBeat(mock.Mock())
- self.job_heartbeat.response = mock.Mock()
- self.job_heartbeat.response.write = mock.Mock()
-
- def testJobHearbeat(self):
- """Asserts job heartbeat detects unavailable jobs."""
- num_of_devices = 2
- shards = 2
-
- lab = self.GenerateLabModel()
- lab.put()
-
- devices = []
- for _ in range(num_of_devices):
- for i in range(shards):
- device = self.GenerateDeviceModel(
- hostname=lab.hostname, product="product{}".format(i))
- device.put()
- devices.append(device)
-
- schedules = []
- for device in devices:
- schedule = self.GenerateScheduleModel(
- lab_model=lab, device_model=device, shards=shards)
- schedule.put()
- schedules.append(schedule)
-
- for schedule in schedules:
- build_dict = self.GenerateBuildModel(schedule)
- for key in build_dict:
- build_dict[key].put()
-
- # Mocking ScheduleHandler and essential methods.
- scheduler = schedule_worker.ScheduleHandler(mock.Mock())
- scheduler.response = mock.Mock()
- scheduler.response.write = mock.Mock()
- scheduler.request.get = mock.MagicMock(return_value="")
-
- # Creating jobs.
- scheduler.post()
- jobs = model.JobModel.query().fetch()
- self.assertEqual(2, len(jobs))
-
- # jobs[0] will get old enough so it will be timed out.
- jobs[0].status = Status.JOB_STATUS_DICT["leased"]
- jobs[0].timestamp = (datetime.datetime.now() - datetime.timedelta(
- seconds=job_heartbeat.JOB_RESPONSE_TIMEOUT_SECONDS + 5))
- jobs[0].heartbeat_stamp = (
- datetime.datetime.now() - datetime.timedelta(
- seconds=job_heartbeat.JOB_RESPONSE_TIMEOUT_SECONDS + 5))
- jobs[0].put()
-
- # jobs[1] will not exceed the timeout time.
- jobs[1].status = Status.JOB_STATUS_DICT["leased"]
- jobs[1].timestamp = (datetime.datetime.now() - datetime.timedelta(
- seconds=job_heartbeat.JOB_RESPONSE_TIMEOUT_SECONDS - 5))
- jobs[1].heartbeat_stamp = (
- datetime.datetime.now() - datetime.timedelta(
- seconds=job_heartbeat.JOB_RESPONSE_TIMEOUT_SECONDS - 5))
- jobs[1].put()
-
- # Creating jobs.
- self.job_heartbeat.get()
-
- # One job(job[0]) should be changed to infra-err status.
- jobs = model.JobModel.query().fetch()
- infra_error_jobs = [
- x for x in jobs if x.status == Status.JOB_STATUS_DICT["infra-err"]
- ]
- self.assertEqual(len(infra_error_jobs), 1)
-
- # job[0]'s devices should be changed to free scheduling status.
- serials = infra_error_jobs[0].serial
- devices = model.DeviceModel.query(
- model.DeviceModel.serial.IN(serials)).fetch()
- for device in devices:
- self.assertEqual(device.scheduling_status,
- Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/gae/webapp/src/scheduler/periodic.py b/gae/webapp/src/scheduler/periodic.py
deleted file mode 100644
index 627ec14..0000000
--- a/gae/webapp/src/scheduler/periodic.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-import webapp2
-
-from webapp.src.proto import model
-
-from google.appengine.api import taskqueue
-
-
-class PeriodicScheduler(webapp2.RequestHandler):
- """Main class for /tasks/schedule servlet.
-
- This class creates a task, which creates schedules, in given period.
- """
-
- def get(self):
- """Enqueues a scheduling task if scheduler is enabled."""
- schedule_control = model.ScheduleControlModel.query()
- schedule_control_dataset = schedule_control.fetch()
- enabled = True
- if schedule_control_dataset:
- for schedule_control_data_tuple in schedule_control_dataset:
- if (not schedule_control_data_tuple.schedule_name or
- schedule_control_data_tuple.schedule_name == "global"):
- enabled = schedule_control_data_tuple.enabled
-
- if not enabled:
- self.response.write(
- "<pre>\nScheduler not enabled.\n</pre>")
- return
-
- task = taskqueue.add(
- url="/worker/schedule_handler",
- target="worker",
- queue_name="queue-schedule",
- transactional=False
- )
- self.response.write(
- "<pre>\nScheduling task is enqueued. ETA {}\n</pre>".format(
- task.eta))
diff --git a/gae/webapp/src/scheduler/schedule_worker.py b/gae/webapp/src/scheduler/schedule_worker.py
deleted file mode 100644
index 4c4b20f..0000000
--- a/gae/webapp/src/scheduler/schedule_worker.py
+++ /dev/null
@@ -1,549 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import itertools
-import logging
-import re
-
-from google.appengine.ext import ndb
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.utils import logger
-import webapp2
-
-MAX_LOG_CHARACTERS = 10000 # maximum number of characters per each log
-BOOTUP_ERROR_RETRY_INTERVAL_IN_MINS = 60 # retry minutes when boot-up error is occurred
-
-CREATE_JOB_SUCCESS = "success"
-CREATE_JOB_FAILED_NO_BUILD = "no_build"
-CREATE_JOB_FAILED_NO_DEVICE = "no_device"
-
-
-def GetTestVersionType(manifest_branch, gsi_branch, test_type=0):
- """Compares manifest branch and gsi branch to get test type.
-
- This function only completes two LSBs which represent version related
- test type.
-
- Args:
- manifest_branch: a string, manifest branch name.
- gsi_branch: a string, gsi branch name.
- test_type: an integer, previous test type value.
-
- Returns:
- An integer, test type value.
- """
- if not test_type:
- value = 0
- else:
- # clear two bits
- value = test_type & ~(1 | 1 << 1)
-
- if not manifest_branch:
- logging.debug("manifest branch cannot be empty or None.")
- return value | Status.TEST_TYPE_DICT[Status.TEST_TYPE_UNKNOWN]
-
- if not gsi_branch:
- logging.debug("gsi_branch is empty.")
- return value | Status.TEST_TYPE_DICT[Status.TEST_TYPE_TOT]
-
- gcs_pattern = "^gs://.*/v([0-9.]*)/.*"
- q_pattern = "(git_)?(aosp-)?q.*"
- p_pattern = "(git_)?(aosp-)?p.*"
- o_mr1_pattern = "(git_)?(aosp-)?o[^-]*-m.*"
- o_pattern = "(git_)?(aosp-)?o.*"
- master_pattern = "(git_)?(aosp-)?master"
-
- gcs_search = re.search(gcs_pattern, manifest_branch)
- if gcs_search:
- device_version = gcs_search.group(1)
- elif re.match(q_pattern, manifest_branch):
- device_version = "10.0"
- elif re.match(p_pattern, manifest_branch):
- device_version = "9.0"
- elif re.match(o_mr1_pattern, manifest_branch):
- device_version = "8.1"
- elif re.match(o_pattern, manifest_branch):
- device_version = "8.0"
- elif re.match(master_pattern, manifest_branch):
- device_version = "master"
- else:
- logging.debug("Unknown device version.")
- return value | Status.TEST_TYPE_DICT[Status.TEST_TYPE_UNKNOWN]
-
- gcs_search = re.search(gcs_pattern, gsi_branch)
- if gcs_search:
- gsi_version = gcs_search.group(1)
- elif re.match(q_pattern, gsi_branch):
- gsi_version = "10.0"
- elif re.match(p_pattern, gsi_branch):
- gsi_version = "9.0"
- elif re.match(o_mr1_pattern, gsi_branch):
- gsi_version = "8.1"
- elif re.match(o_pattern, gsi_branch):
- gsi_version = "8.0"
- elif re.match(master_pattern, gsi_branch):
- gsi_version = "master"
- else:
- logging.debug("Unknown gsi version.")
- return value | Status.TEST_TYPE_DICT[Status.TEST_TYPE_UNKNOWN]
-
- if device_version == gsi_version:
- return value | Status.TEST_TYPE_DICT[Status.TEST_TYPE_TOT]
- else:
- return value | Status.TEST_TYPE_DICT[Status.TEST_TYPE_OTA]
-
-
-class ScheduleHandler(webapp2.RequestHandler):
- """Background worker class for /worker/schedule_handler.
-
- This class pull tasks from 'queue-schedule' queue and processes in
- background service 'worker'.
-
- Attributes:
- logger: Logger class
- """
- logger = logger.Logger()
-
- def ReserveDevices(self, target_device_serials):
- """Reserves devices.
-
- Args:
- target_device_serials: a list of strings, containing target device
- serial numbers.
- """
- device_query = model.DeviceModel.query(
- model.DeviceModel.serial.IN(target_device_serials))
- devices = device_query.fetch()
- devices_to_put = []
- for device in devices:
- device.scheduling_status = Status.DEVICE_SCHEDULING_STATUS_DICT[
- "reserved"]
- devices_to_put.append(device)
- if devices_to_put:
- ndb.put_multi(devices_to_put)
-
- def FindBuildId(self, artifact_type, manifest_branch, target,
- signed=False):
- """Finds a designated build ID.
-
- Args:
- artifact_type: a string, build artifact type.
- manifest_branch: a string, build manifest branch.
- target: a string which build target and type are joined by '-'.
- signed: a boolean to get a signed build.
-
- Return:
- string, build ID found.
- """
- build_id = ""
- if "-" in target:
- build_target, build_type = target.split("-")
- else:
- build_target = target
- build_type = ""
- if not artifact_type or not manifest_branch or not build_target:
- self.logger.Println("The argument format is invalid.")
- return build_id
- build_query = model.BuildModel.query(
- model.BuildModel.artifact_type == artifact_type,
- model.BuildModel.manifest_branch == manifest_branch,
- model.BuildModel.build_target == build_target,
- model.BuildModel.build_type == build_type)
- builds = build_query.fetch()
-
- if builds:
- builds = [
- build for build in builds
- if (build.timestamp >
- datetime.datetime.now() - datetime.timedelta(hours=72))
- ]
-
- if builds:
- self.logger.Println("-- Found build ID")
- builds.sort(key=lambda x: x.build_id, reverse=True)
- for build in builds:
- if not signed or build.signed:
- build_id = build.build_id
- break
- return build_id
-
- def post(self):
- self.logger.Clear()
- manual_job = False
- schedule_key = self.request.get("schedule_key")
- if schedule_key:
- key = ndb.key.Key(urlsafe=schedule_key)
- manual_job = True
- schedules = [key.get()]
- else:
- schedule_query = model.ScheduleModel.query(
- model.ScheduleModel.suspended != True)
- schedules = schedule_query.fetch()
-
- if schedules:
- # filter out the schedules which are not updated within 72 hours.
- schedules = [
- schedule for schedule in schedules
- if (schedule.timestamp >
- datetime.datetime.now() - datetime.timedelta(hours=72))
- ]
- schedules = self.FilterWithPeriod(schedules)
-
- if schedules:
- schedules.sort(key=lambda x: self.GetProductName(x))
- group_by_product = [
- list(g)
- for _, g in itertools.groupby(schedules,
- lambda x: self.GetProductName(x))
- ]
- for group in group_by_product:
- group.sort(key=lambda x: x.priority_value if (
- x.priority_value) else Status.GetPriorityValue(x.priority))
- create_result = {
- CREATE_JOB_SUCCESS: [],
- CREATE_JOB_FAILED_NO_BUILD: [],
- CREATE_JOB_FAILED_NO_DEVICE: []
- }
- for schedule in group:
- self.logger.Println("")
- self.logger.Println("Schedule: %s (branch: %s)" %
- (schedule.test_name,
- schedule.manifest_branch))
- self.logger.Println(
- "Build Target: %s" % schedule.build_target)
- self.logger.Println("Device: %s" % schedule.device)
- self.logger.Indent()
- result, lab = self.CreateJob(schedule, manual_job)
- if result == CREATE_JOB_SUCCESS:
- create_result[result].append(lab)
- else:
- create_result[result].append(schedule)
- self.logger.Unindent()
- # if any schedule in group created a job, increase priority of
- # the schedules which couldn't create due to out of devices.
- schedules_to_put = []
- for lab in create_result[CREATE_JOB_SUCCESS]:
- for schedule in create_result[CREATE_JOB_FAILED_NO_DEVICE]:
- if any([lab in target for target in schedule.device
- ]) and schedule not in schedules_to_put:
- if schedule.priority_value is None:
- schedule.priority_value = (
- Status.GetPriorityValue(schedule.priority))
- if schedule.priority_value > 0:
- schedule.priority_value -= 1
- schedules_to_put.append(schedule)
- if schedules_to_put:
- ndb.put_multi(schedules_to_put)
-
- self.logger.Println("Scheduling completed.")
-
- lines = self.logger.Get()
- lines = [line.strip() for line in lines]
- outputs = []
- chars = 0
- for line in lines:
- chars += len(line)
- if chars > MAX_LOG_CHARACTERS:
- logging.info("\n".join(outputs))
- outputs = []
- chars = len(line)
- outputs.append(line)
- logging.info("\n".join(outputs))
-
- def CreateJob(self, schedule, manual_job=False):
- """Creates a job for given schedule.
-
- Args:
- schedule: model.ScheduleModel instance.
- manual_job: True if a job is created by a user, False otherwise.
-
- Returns:
- a string of job creation result message.
- a string of lab name if job is created, otherwise empty string.
- """
- target_host, target_device, target_device_serials = (
- self.SelectTargetLab(schedule))
- if not target_host:
- return CREATE_JOB_FAILED_NO_DEVICE, ""
-
- self.logger.Println("- Target host: %s" % target_host)
- self.logger.Println("- Target device: %s" % target_device)
- self.logger.Println("- Target serials: %s" % target_device_serials)
-
- # create job and add.
- new_job = model.JobModel()
- new_job.hostname = target_host
- new_job.priority = schedule.priority
- new_job.test_name = schedule.test_name
- new_job.require_signed_device_build = (
- schedule.require_signed_device_build)
- new_job.device = target_device
- new_job.period = schedule.period
- new_job.serial.extend(target_device_serials)
- new_job.build_storage_type = schedule.build_storage_type
- new_job.manifest_branch = schedule.manifest_branch
- new_job.build_target = schedule.build_target
- new_job.pab_account_id = schedule.device_pab_account_id
- new_job.shards = schedule.shards
- new_job.param = schedule.param
- new_job.retry_count = schedule.retry_count
- new_job.gsi_storage_type = schedule.gsi_storage_type
- new_job.gsi_branch = schedule.gsi_branch
- new_job.gsi_build_target = schedule.gsi_build_target
- new_job.gsi_pab_account_id = schedule.gsi_pab_account_id
- new_job.gsi_vendor_version = schedule.gsi_vendor_version
- new_job.test_storage_type = schedule.test_storage_type
- new_job.test_branch = schedule.test_branch
- new_job.test_build_target = schedule.test_build_target
- new_job.test_pab_account_id = schedule.test_pab_account_id
- new_job.parent_schedule = schedule.key
- new_job.image_package_repo_base = schedule.image_package_repo_base
- new_job.required_host_equipment = schedule.required_host_equipment
- new_job.required_device_equipment = schedule.required_device_equipment
- new_job.has_bootloader_img = schedule.has_bootloader_img
- new_job.has_radio_img = schedule.has_radio_img
- new_job.report_bucket = schedule.report_bucket
- new_job.report_spreadsheet_id = schedule.report_spreadsheet_id
- new_job.report_persistent_url = schedule.report_persistent_url
- new_job.report_reference_url = schedule.report_reference_url
-
- # uses bit 0-1 to indicate version.
- test_type = GetTestVersionType(schedule.manifest_branch,
- schedule.gsi_branch)
- # uses bit 2
- if schedule.require_signed_device_build:
- test_type |= Status.TEST_TYPE_DICT[Status.TEST_TYPE_SIGNED]
-
- if manual_job:
- test_type |= Status.TEST_TYPE_DICT[Status.TEST_TYPE_MANUAL]
-
- new_job.test_type = test_type
-
- new_job.build_id = ""
- new_job.gsi_build_id = ""
- new_job.test_build_id = ""
- for artifact_type in ["device", "gsi", "test"]:
- if artifact_type == "device":
- storage_type_text = "build_storage_type"
- manifest_branch_text = "manifest_branch"
- build_target_text = "build_target"
- build_id_text = "build_id"
- signed = new_job.require_signed_device_build
- else:
- storage_type_text = artifact_type + "_storage_type"
- manifest_branch_text = artifact_type + "_branch"
- build_target_text = artifact_type + "_build_target"
- build_id_text = artifact_type + "_build_id"
- signed = False
-
- manifest_branch = getattr(new_job, manifest_branch_text)
- build_target = getattr(new_job, build_target_text)
- storage_type = getattr(new_job, storage_type_text)
- if storage_type == Status.STORAGE_TYPE_DICT["PAB"]:
- build_id = self.FindBuildId(
- artifact_type=artifact_type,
- manifest_branch=manifest_branch,
- target=build_target,
- signed=signed)
- elif storage_type == Status.STORAGE_TYPE_DICT["GCS"]:
- # temp value to distinguish from empty values.
- build_id = "gcs"
- else:
- build_id = ""
- self.logger.Println(
- "Unexpected storage type (%s)." % storage_type)
- setattr(new_job, build_id_text, build_id)
-
- if ((not new_job.manifest_branch or new_job.build_id)
- and (not new_job.gsi_branch or new_job.gsi_build_id)
- and (not new_job.test_branch or new_job.test_build_id)):
- new_job.build_id = new_job.build_id.replace("gcs", "")
- new_job.gsi_build_id = (new_job.gsi_build_id.replace("gcs", ""))
- new_job.test_build_id = (new_job.test_build_id.replace("gcs", ""))
- self.ReserveDevices(target_device_serials)
- new_job.status = Status.JOB_STATUS_DICT["ready"]
- new_job.timestamp = datetime.datetime.now()
- new_job_key = new_job.put()
- schedule.children_jobs.append(new_job_key)
- schedule.priority_value = Status.GetPriorityValue(
- schedule.priority)
- schedule.put()
- self.logger.Println("A new job has been created.")
- labs = model.LabModel.query(
- model.LabModel.hostname == target_host).fetch()
- return CREATE_JOB_SUCCESS, labs[0].name
- else:
- self.logger.Println("Cannot find builds to create a job.")
- self.logger.Println("- Device branch / build - {} / {}".format(
- new_job.manifest_branch, new_job.build_id))
- self.logger.Println("- GSI branch / build - {} / {}".format(
- new_job.gsi_branch, new_job.gsi_build_id))
- self.logger.Println("- Test branch / build - {} / {}".format(
- new_job.test_branch, new_job.test_build_id))
- return CREATE_JOB_FAILED_NO_BUILD, ""
-
- def FilterWithPeriod(self, schedules):
- """Filters schedules with period.
-
- This method filters schedules if any children jobs are created within
- period time.
-
- Args:
- schedules: a list of model.ScheduleModel instances.
-
- Returns:
- a list of model.ScheduleModel instances which need to create a new
- job.
- """
- ret_list = []
- if not schedules:
- return ret_list
-
- if type(schedules) is not list:
- schedules = [schedules]
-
- for schedule in schedules:
- if not schedule.children_jobs:
- ret_list.append(schedule)
- continue
-
- latest_job_key = schedule.children_jobs[-1]
- latest_job = latest_job_key.get()
-
- if datetime.datetime.now() - latest_job.timestamp > (
- datetime.timedelta(
- minutes=self.GetCorrectedPeriod(schedule))):
- ret_list.append(schedule)
-
- return ret_list
-
- def SelectTargetLab(self, schedule):
- """Find target host and devices to schedule a new job.
-
- Args:
- schedule: a proto containing the information of a schedule.
-
- Returns:
- a string which represents hostname,
- a string containing target lab and product with '/' separator,
- a list of selected devices serial (see whether devices will be
- selected later when the job is picked up.)
- """
-
- available_devices = []
- for target_device in schedule.device:
- if "/" not in target_device:
- self.logger.Println(
- "Device malformed - {}".format(target_device))
- continue
-
- target_lab, target_product_type = target_device.split("/")
- self.logger.Println("- Lab %s" % target_lab)
- self.logger.Indent()
- host_query = model.LabModel.query(
- model.LabModel.name == target_lab)
- target_hosts = host_query.fetch()
-
- if target_hosts:
- for host in target_hosts:
- if not (set(schedule.required_host_equipment) <= set(
- host.host_equipment)):
- continue
- self.logger.Println("- Host: %s" % host.hostname)
- self.logger.Indent()
- device_query = model.DeviceModel.query(
- model.DeviceModel.hostname == host.hostname,
- model.DeviceModel.scheduling_status ==
- Status.DEVICE_SCHEDULING_STATUS_DICT["free"],
- model.DeviceModel.status.IN([
- Status.DEVICE_STATUS_DICT["fastboot"],
- Status.DEVICE_STATUS_DICT["online"],
- Status.DEVICE_STATUS_DICT["ready"]
- ]))
- host_devices = device_query.fetch()
- host_devices = [
- x for x in host_devices
- if x.product.lower() == target_product_type.lower() and
- (set(schedule.required_device_equipment) <= set(
- x.device_equipment))
- ]
- if len(host_devices) < schedule.shards:
- self.logger.Println(
- "A host {} does not have enough devices. "
- "# of devices = {}, shards = {}".format(
- host.hostname, len(host_devices),
- schedule.shards))
- self.logger.Unindent()
- continue
- host_devices.sort(
- key=lambda x: (len(x.device_equipment)
- if x.device_equipment else 0))
- available_devices.append((host_devices, target_device))
- self.logger.Unindent()
-
- self.logger.Unindent()
-
- if not available_devices:
- self.logger.Println("No hosts have enough devices for schedule!")
- return None, None, []
-
- available_devices.sort(key=lambda x: (
- sum([len(y.device_equipment) for y in x[0][:schedule.shards]])))
- selected_host_devices = available_devices[0]
- return selected_host_devices[0][0].hostname, selected_host_devices[
- 1], [x.serial for x in selected_host_devices[0][:schedule.shards]]
-
- def GetProductName(self, schedule):
- """Gets a product name from schedule instance.
-
- Args:
- schedule: a schedule instance.
-
- Returns:
- a string, product name in lowercase.
- """
- if not schedule or not schedule.device:
- return ""
-
- if "/" not in schedule.device[0]:
- return ""
-
- return schedule.device[0].split("/")[1].lower()
-
- def GetCorrectedPeriod(self, schedule):
- """Corrects and returns period value based on latest children jobs.
-
- Args:
- schedule: a model.ScheduleModel instance containing schedule
- information.
-
- Returns:
- an integer, corrected schedule period.
- """
- if not schedule.error_count or not schedule.children_jobs or (
- schedule.period <= BOOTUP_ERROR_RETRY_INTERVAL_IN_MINS):
- return schedule.period
-
- latest_job = schedule.children_jobs[-1].get()
-
- if latest_job.status == Status.JOB_STATUS_DICT["bootup-err"]:
- return BOOTUP_ERROR_RETRY_INTERVAL_IN_MINS
- else:
- return schedule.period
diff --git a/gae/webapp/src/scheduler/schedule_worker_test.py b/gae/webapp/src/scheduler/schedule_worker_test.py
deleted file mode 100644
index 2dcf1e9..0000000
--- a/gae/webapp/src/scheduler/schedule_worker_test.py
+++ /dev/null
@@ -1,581 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.scheduler import schedule_worker
-from webapp.src.testing import unittest_base
-from webapp.src.utils import model_util
-
-
-class ScheduleHandlerTest(unittest_base.UnitTestBase):
- """Tests for ScheduleHandler.
-
- Attributes:
- scheduler: A mock schedule_worker.ScheduleHandler.
- """
-
- def setUp(self):
- """Initializes test"""
- super(ScheduleHandlerTest, self).setUp()
- # Mocking ScheduleHandler and essential methods.
- self.scheduler = schedule_worker.ScheduleHandler(mock.Mock())
- self.scheduler.response = mock.Mock()
- self.scheduler.response.write = mock.Mock()
- self.scheduler.request.get = mock.MagicMock(return_value="")
-
- def testSimpleJobCreation(self):
- """Asserts a job is created.
-
- This test defines that each model only has a single entity, and asserts
- that a job is created.
- """
- lab = self.GenerateLabModel()
- lab.put()
-
- device = self.GenerateDeviceModel(hostname=lab.hostname)
- device.put()
-
- schedule = self.GenerateScheduleModel(
- device_model=device, lab_model=lab)
- schedule.put()
-
- build_dict = self.GenerateBuildModel(schedule)
- for key in build_dict:
- build_dict[key].put()
-
- self.scheduler.post()
- self.assertEqual(1, len(model.JobModel.query().fetch()))
- print("A job is created successfully.")
-
- device_query = model.DeviceModel.query(
- model.DeviceModel.serial == device.serial)
- device = device_query.fetch()[0]
- self.assertEqual(Status.DEVICE_SCHEDULING_STATUS_DICT["reserved"],
- device.scheduling_status)
- print("A device is reserved successfully.")
-
- def testPriorityScheduling(self):
- """Asserts job creation with priority scheduling."""
- product = "product"
- high_priority_schedule_test_name = "high_test"
- medium_priority_schedule_test_name = "medium_test"
-
- lab = self.GenerateLabModel()
- lab.put()
-
- device = self.GenerateDeviceModel(
- hostname=lab.hostname, product=product)
- device.put()
-
- schedule_high = self.GenerateScheduleModel(
- device_model=device,
- lab_model=lab,
- priority="high",
- test_name=high_priority_schedule_test_name)
- schedule_high.put()
-
- schedule_medium = self.GenerateScheduleModel(
- device_model=device,
- lab_model=lab,
- priority="medium",
- test_name=medium_priority_schedule_test_name)
- schedule_medium.put()
-
- build_dict = self.GenerateBuildModel(schedule_high)
- for key in build_dict:
- build_dict[key].put()
-
- self.scheduler.post()
- schedules = model.ScheduleModel.query().fetch()
- self.assertEqual(schedules[0].test_name,
- high_priority_schedule_test_name)
-
- def testPrioritySchedulingWithAging(self):
- """Asserts job creation with priority scheduling with aging."""
- product = "product"
- high_priority_schedule_test_name = "high_test"
- medium_priority_schedule_test_name = "medium_test"
- schedule_period_minute = 100
-
- lab = self.GenerateLabModel()
- lab.put()
-
- device = self.GenerateDeviceModel(
- hostname=lab.hostname, product=product)
- device.put()
-
- schedules = []
- schedule_high = self.GenerateScheduleModel(
- device_model=device,
- lab_model=lab,
- test_name=high_priority_schedule_test_name,
- period=schedule_period_minute,
- priority="high")
- schedule_high.put()
- schedules.append(schedule_high)
-
- schedule_medium = self.GenerateScheduleModel(
- device_model=device,
- lab_model=lab,
- test_name=medium_priority_schedule_test_name,
- period=schedule_period_minute,
- priority="medium")
- schedule_medium.put()
- schedules.append(schedule_medium)
-
- for schedule in schedules:
- build_dict = self.GenerateBuildModel(schedule)
- for key in build_dict:
- build_dict[key].put()
-
- high_original_priority_value = schedule_high.priority_value
- medium_original_priority_value = schedule_medium.priority_value
-
- # On first attempt, "high" priority will create a job.
- self.scheduler.post()
- jobs = model.JobModel.query().fetch()
- self.assertEqual(jobs[0].test_name, high_priority_schedule_test_name)
-
- # medium priority schedule's priority value will be decreased.
- self.assertEqual(medium_original_priority_value - 1,
- schedule_medium.priority_value)
-
- self.PassTime(minutes=schedule_period_minute + 1)
- self.ResetDevices()
-
- # On second attempt, "high" priority will create a job.
- self.scheduler.post()
- jobs = model.JobModel.query().fetch()
- jobs.sort(key=lambda x: x.timestamp, reverse=True) # latest first
- self.assertEqual(jobs[0].test_name, high_priority_schedule_test_name)
-
- # medium priority schedule's priority value will be decreased again.
- self.assertEqual(medium_original_priority_value - 2,
- schedule_medium.priority_value)
-
- while schedule_medium.priority_value >= high_original_priority_value:
- self.PassTime(minutes=schedule_period_minute + 1)
- self.ResetDevices()
- self.scheduler.post()
-
- # at last, medium priority schedule should be able to create a job.
- self.PassTime(minutes=schedule_period_minute + 1)
- self.ResetDevices()
- self.scheduler.post()
-
- jobs = model.JobModel.query().fetch()
- jobs.sort(key=lambda x: x.timestamp, reverse=True) # latest first
- self.assertEqual(jobs[0].test_name, medium_priority_schedule_test_name)
-
- # after a job is created, its priority value should be restored.
- self.assertEqual(schedule_medium.priority_value,
- medium_original_priority_value)
-
- def testPrioritySchedulingWithAgingForMultiDevices(self):
- """Asserts job creation with priority scheduling for multi devices."""
- product1 = "product1"
- product2 = "product2"
- schedule_period_minute = 360
-
- lab = self.GenerateLabModel()
- lab.put()
-
- device1 = self.GenerateDeviceModel(
- hostname=lab.hostname, product=product1)
- device1.put()
-
- device2 = self.GenerateDeviceModel(
- hostname=lab.hostname, product=product2)
- device2.put()
-
- schedule1_l = self.GenerateScheduleModel(
- device_model=device1,
- lab_model=lab,
- priority="low",
- period=schedule_period_minute)
- schedule1_l.put()
-
- schedule1_h = self.GenerateScheduleModel(
- device_model=device1,
- lab_model=lab,
- priority="high",
- period=schedule_period_minute)
- schedule1_h.put()
-
- schedule2_m = self.GenerateScheduleModel(
- device_model=device2,
- lab_model=lab,
- priority="medium",
- period=schedule_period_minute)
- schedule2_m.put()
-
- schedule2_h = self.GenerateScheduleModel(
- device_model=device2,
- lab_model=lab,
- priority="high",
- period=schedule_period_minute)
- schedule2_h.put()
-
- schedule1_l_original_priority_value = schedule1_l.priority_value
- schedule2_m_original_priority_value = schedule2_m.priority_value
-
- for schedule in [schedule2_m, schedule2_h]:
- build_dict = self.GenerateBuildModel(schedule)
- for key in build_dict:
- build_dict[key].put()
-
- # create jobs
- self.scheduler.post()
-
- # schedule2_m will not get a change to create a job.
- jobs = model.JobModel.query().fetch()
- self.assertTrue(
- any([job.test_name == schedule2_h.test_name for job in jobs]))
- self.assertFalse(
- any([job.test_name == schedule2_m.test_name for job in jobs]))
-
- # schedule2_m's priority value should be decreased.
- self.assertTrue(schedule2_m_original_priority_value - 1,
- schedule2_m.priority_value)
-
- # schedule1_l's priority value should not be changed because all other
- # schedules for device1 were also failed to created a job.
- self.assertTrue(schedule1_l_original_priority_value,
- schedule1_l.priority_value)
-
- for num in range(3):
- self.assertTrue(schedule2_m_original_priority_value - 1 - num,
- schedule2_m.priority_value)
- self.PassTime(minutes=schedule_period_minute + 1)
- self.ResetDevices()
- self.scheduler.post()
- self.assertFalse(
- any([job.test_name == schedule2_m.test_name for job in jobs]))
- self.assertTrue(schedule1_l_original_priority_value,
- schedule1_l.priority_value)
-
- # device1 is ready for scheduling.
- for schedule in [schedule1_l, schedule1_h]:
- build_dict = self.GenerateBuildModel(schedule)
- for key in build_dict:
- build_dict[key].put()
-
- # after 4 times of failure, now schedule2_m can create a job.
- self.PassTime(minutes=schedule_period_minute + 1)
- self.ResetDevices()
- self.scheduler.post()
-
- jobs = model.JobModel.query().fetch()
- self.assertTrue(
- any([job.test_name == schedule2_m.test_name for job in jobs]))
-
- # now schedule_1's priority value should be changed.
- self.assertEqual(schedule1_l_original_priority_value - 1,
- schedule1_l.priority_value)
-
- def testRetryAfterBootupError(self):
- """Asserts a schedule's period is shortened after boot-up error."""
- long_period = 5760
-
- lab = self.GenerateLabModel()
- lab.put()
-
- device = self.GenerateDeviceModel(hostname=lab.hostname)
- device.put()
-
- schedule = self.GenerateScheduleModel(
- device_model=device, lab_model=lab, period=long_period)
- schedule.put()
-
- build_dict = self.GenerateBuildModel(schedule)
- for key in build_dict:
- build_dict[key].put()
-
- # a job should be created.
- self.scheduler.post()
- jobs = model.JobModel.query().fetch()
- self.assertEqual(1, len(jobs))
-
- jobs[0].status = Status.JOB_STATUS_DICT["bootup-err"]
- jobs[0].put()
- model_util.UpdateParentSchedule(jobs[0],
- Status.JOB_STATUS_DICT["bootup-err"])
-
- self.PassTime(
- minutes=schedule_worker.BOOTUP_ERROR_RETRY_INTERVAL_IN_MINS + 1)
- self.ResetDevices()
-
- # new job should be created again.
- self.scheduler.post()
- jobs = model.JobModel.query().fetch()
- self.assertEqual(2, len(jobs))
-
- jobs.sort(key=lambda x: x.timestamp, reverse=True) # latest first
- jobs[0].status = Status.JOB_STATUS_DICT["bootup-err"]
- jobs[0].put()
- model_util.UpdateParentSchedule(jobs[0],
- Status.JOB_STATUS_DICT["bootup-err"])
-
- self.PassTime(
- minutes=schedule_worker.BOOTUP_ERROR_RETRY_INTERVAL_IN_MINS - 1)
- self.ResetDevices()
-
- # time is not passed enough so there would be no new job.
- self.scheduler.post()
- jobs = model.JobModel.query().fetch()
- self.assertEqual(2, len(jobs))
-
- # if latest job is completed successfully, period should be recovered.
- jobs[0].status = Status.JOB_STATUS_DICT["complete"]
- jobs[0].put()
- model_util.UpdateParentSchedule(jobs[0],
- Status.JOB_STATUS_DICT["complete"])
-
- # pass time to (period - 1)
- self.PassTime(minutes=long_period - 1 - (
- schedule_worker.BOOTUP_ERROR_RETRY_INTERVAL_IN_MINS - 1))
- self.ResetDevices()
-
- # then no job will be created.
- self.scheduler.post()
- jobs = model.JobModel.query().fetch()
- self.assertEqual(2, len(jobs))
-
- # pass time to (period + 1)
- self.PassTime(minutes=2)
-
- self.scheduler.post()
- jobs = model.JobModel.query().fetch()
- self.assertEqual(3, len(jobs))
-
- def testSimpleDevicePriorityWithEquipment(self):
- """Asserts a scheduler creates a job with minimum device equipment."""
- equipment_a = "equipment_a"
- equipment_b = "equipment_b"
-
- device_product = "device_product"
- lab = self.GenerateLabModel()
- lab.put()
-
- device_a = self.GenerateDeviceModel(
- product=device_product,
- hostname=lab.hostname,
- device_equipment=[equipment_a])
- device_a.put()
-
- device_b = self.GenerateDeviceModel(
- product=device_product,
- hostname=lab.hostname,
- device_equipment=[equipment_b])
- device_b.put()
-
- device_c = self.GenerateDeviceModel(
- product=device_product, hostname=lab.hostname)
- device_c.put()
-
- schedule = self.GenerateScheduleModel(
- device_target="{}-test".format(device_product),
- lab_model=lab,
- required_device_equipment=[equipment_b])
- schedule.put()
-
- build_dict = self.GenerateBuildModel(schedule)
- for key in build_dict:
- build_dict[key].put()
-
- # a job should be created and it should be created with equipment_b
- self.scheduler.post()
- jobs = model.JobModel.query().fetch()
- self.assertEqual(1, len(jobs))
- self.assertIn(device_b.serial, jobs[0].serial)
-
- def testDevicePriorityWithEquipment(self):
- """Asserts a scheduler creates a job with minimum device equipment."""
- lab_1 = "lab_1"
- lab_2 = "lab_2"
-
- host_a = "host_a"
- host_b = "host_b"
- host_c = "host_c"
- host_d = "host_d"
- host_e = "host_e"
-
- equipment_a = "equipment_a"
- equipment_b = "equipment_b"
- equipment_c = "equipment_c"
-
- correct_product = "correct"
- wrong_product = "wrong"
-
- self.GenerateLabModel(lab_name=lab_1, host_name=host_a).put()
- self.GenerateLabModel(lab_name=lab_1, host_name=host_b).put()
- self.GenerateLabModel(lab_name=lab_2, host_name=host_c).put()
- self.GenerateLabModel(lab_name=lab_2, host_name=host_d).put()
- self.GenerateLabModel(lab_name=lab_2, host_name=host_e).put()
-
- # setting devices through host a to e.
- equipments = [[equipment_a], [equipment_a], [equipment_b],
- [equipment_a, equipment_b]]
- for equipment in equipments:
- device = self.GenerateDeviceModel(
- product=correct_product, hostname=host_a)
- device.device_equipment = equipment
- device.put()
-
- equipments = [[], [equipment_a], [equipment_a, equipment_b],
- [equipment_a, equipment_b]]
- for equipment in equipments:
- device = self.GenerateDeviceModel(
- product=correct_product, hostname=host_b)
- device.device_equipment = equipment
- device.put()
-
- equipments = [[equipment_a], [equipment_a], [equipment_b],
- [equipment_b]]
- for equipment in equipments:
- device = self.GenerateDeviceModel(
- product=correct_product, hostname=host_c)
- device.device_equipment = equipment
- device.put()
-
- equipments = [[equipment_a], [equipment_a, equipment_b, equipment_c],
- [equipment_a, equipment_b]]
- for equipment in equipments:
- device = self.GenerateDeviceModel(
- product=correct_product, hostname=host_d)
- device.device_equipment = equipment
- device.put()
-
- products = [correct_product, correct_product, wrong_product]
- for product in products:
- device = self.GenerateDeviceModel(product=product, hostname=host_e)
- device.device_equipment = [equipment_a]
- device.put()
-
- schedule = self.GenerateScheduleModel(
- device_target="{}-test".format(correct_product), shards=3)
- schedule.required_device_equipment = [equipment_a]
- schedule.device = [
- "{}/{}".format(lab_1, correct_product), "{}/{}".format(
- lab_2, correct_product)
- ]
- schedule.put()
-
- build_dict = self.GenerateBuildModel(schedule)
- for key in build_dict:
- build_dict[key].put()
-
- # a job should be created on host_a
- self.scheduler.post()
- jobs = model.JobModel.query().fetch()
- self.assertEqual(1, len(jobs))
-
- host_a_devices = model.DeviceModel.query(
- model.DeviceModel.hostname == host_a).fetch()
- host_a_devices_serial = [x.serial for x in host_a_devices]
-
- for job_device in jobs[0].serial:
- self.assertIn(job_device, host_a_devices_serial)
-
- def testSelectTargetLab(self):
- """Asserts SelectTargetLab() method."""
- lab = self.GenerateLabModel()
- lab.put()
-
- device = self.GenerateDeviceModel(hostname=lab.hostname)
- device.put()
-
- schedule = self.GenerateScheduleModel(
- device_model=device, lab_model=lab)
- schedule.put()
-
- ret_host, ret_device, ret_serials = (
- self.scheduler.SelectTargetLab(schedule))
-
- self.assertEqual(lab.hostname, ret_host)
- self.assertEqual("{}/{}".format(lab.name, device.product), ret_device)
- self.assertEqual([device.serial], ret_serials)
-
- def testSimpleJobCreationWithOutdatedBuild(self):
- """Asserts an outdated build is filtered out."""
- lab = self.GenerateLabModel()
- lab.put()
-
- device = self.GenerateDeviceModel(hostname=lab.hostname)
- device.put()
-
- schedule = self.GenerateScheduleModel(
- device_model=device, lab_model=lab)
- schedule.put()
-
- build_dict = self.GenerateBuildModel(schedule)
- for key in build_dict:
- build_dict[key].timestamp = datetime.datetime.now(
- ) - datetime.timedelta(hours=73)
- build_dict[key].put()
-
- self.scheduler.post()
- self.assertEqual(0, len(model.JobModel.query().fetch()))
-
- builds = model.BuildModel().query().fetch()
- for build in builds:
- build.timestamp = datetime.datetime.now()
- build.put()
-
- self.scheduler.post()
- self.assertEqual(1, len(model.JobModel.query().fetch()))
-
- def testSimpleJobCreationWithOutdatedSchedule(self):
- """Asserts an outdated schedule is filtered out."""
- lab = self.GenerateLabModel()
- lab.put()
-
- device = self.GenerateDeviceModel(hostname=lab.hostname)
- device.put()
-
- schedule = self.GenerateScheduleModel(
- device_model=device, lab_model=lab)
- schedule.timestamp = datetime.datetime.now() - datetime.timedelta(
- hours=73)
- schedule.put()
-
- build_dict = self.GenerateBuildModel(schedule)
- for key in build_dict:
- build_dict[key].put()
-
- self.scheduler.post()
- self.assertEqual(0, len(model.JobModel.query().fetch()))
-
- schedule = model.ScheduleModel().query().fetch()[0]
- schedule.timestamp = datetime.datetime.now()
- schedule.put()
-
- self.scheduler.post()
- self.assertEqual(1, len(model.JobModel.query().fetch()))
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/gae/webapp/src/tasks/__init__.py b/gae/webapp/src/tasks/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/tasks/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/tasks/indexing.py b/gae/webapp/src/tasks/indexing.py
deleted file mode 100644
index 2ebe687..0000000
--- a/gae/webapp/src/tasks/indexing.py
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License") + "\n</pre>");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import logging
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.scheduler import schedule_worker
-
-import webapp2
-from google.appengine.api import taskqueue
-from google.appengine.ext import ndb
-
-PAGING_SIZE = 1000
-DICT_MODELS = {
- "build": model.BuildModel,
- "device": model.DeviceModel,
- "lab": model.LabModel,
- "job": model.JobModel,
- "schedule": model.ScheduleModel
-}
-
-
-class CreateIndex(webapp2.RequestHandler):
- """Cron class for /tasks/indexing/{model}."""
-
- def get(self, arg):
- """Creates a task to re-index, with given URL format."""
- index_list = []
- if arg:
- if arg.startswith("/") and arg[1:].lower() in DICT_MODELS.keys():
- index_list.append(arg[1:].lower())
- else:
- self.response.write("<pre>Access Denied. Please visit "
- "/tasks/indexing/{model}</pre>")
- return
- else:
- # accessed by /tasks/indexing
- index_list.extend(DICT_MODELS.keys())
- self.response.write(
- "<pre>Re-indexing task{} for {} {} going to be created.</pre>".
- format("s"
- if len(index_list) > 1 else "", ", ".join(index_list), "are"
- if len(index_list) > 1 else "is"))
-
- for model_type in index_list:
- task = taskqueue.add(
- url="/worker/indexing",
- target="worker",
- queue_name="queue-indexing",
- transactional=False,
- params={
- "model_type": model_type
- })
- self.response.write(
- "<pre>Re-indexing task for {} is created. ETA: {}</pre>".
- format(model_type, task.eta))
-
-
-class IndexingHandler(webapp2.RequestHandler):
- """Task queue handler class to re-index ndb model."""
-
- def post(self):
- """Fetch entities and process model specific jobs."""
- reload(model)
- model_type = self.request.get("model_type")
-
- num_updated = 0
- next_cursor = None
- more = True
-
- while more:
- query = DICT_MODELS[model_type].query()
- entities, next_cursor, more = query.fetch_page(
- PAGING_SIZE, start_cursor=next_cursor)
-
- to_put = []
- for entity in entities:
- if model_type == "build":
- pass
- elif model_type == "device":
- pass
- elif model_type == "lab":
- pass
- elif model_type == "job":
- # uses bits 0-1 to indicate version.
- test_type = schedule_worker.GetTestVersionType(
- entity.manifest_branch, entity.gsi_branch)
- # uses bit 2
- if entity.require_signed_device_build:
- test_type |= (
- Status.TEST_TYPE_DICT[Status.TEST_TYPE_SIGNED])
- entity.test_type = test_type
-
- if not entity.parent_schedule:
- # finds and links to a parent schedule.
- parent_schedule_query = model.ScheduleModel.query(
- model.ScheduleModel.priority == entity.priority,
- model.ScheduleModel.test_name == entity.test_name,
- model.ScheduleModel.period == entity.period,
- model.ScheduleModel.build_storage_type == (
- entity.build_storage_type),
- model.ScheduleModel.manifest_branch == (
- entity.manifest_branch),
- model.ScheduleModel.build_target == (
- entity.build_target),
- model.ScheduleModel.device_pab_account_id == (
- entity.pab_account_id),
- model.ScheduleModel.shards == entity.shards,
- model.ScheduleModel.retry_count == (
- entity.retry_count),
- model.ScheduleModel.gsi_storage_type == (
- entity.gsi_storage_type),
- model.ScheduleModel.gsi_branch == (
- entity.gsi_branch),
- model.ScheduleModel.gsi_build_target == (
- entity.gsi_build_target),
- model.ScheduleModel.gsi_pab_account_id == (
- entity.gsi_pab_account_id),
- model.ScheduleModel.gsi_vendor_version == (
- entity.gsi_vendor_version),
- model.ScheduleModel.test_storage_type == (
- entity.test_storage_type),
- model.ScheduleModel.test_branch == (
- entity.test_branch),
- model.ScheduleModel.test_build_target == (
- entity.test_build_target),
- model.ScheduleModel.test_pab_account_id == (
- entity.test_pab_account_id))
- parent_schedules = parent_schedule_query.fetch()
- if not parent_schedules:
- logging.error("Parent not found.")
- else:
- parent_schedule = parent_schedules[0]
- parent_schedule.children_jobs.append(entity.key)
- entity.parent_schedule = parent_schedule.key
- to_put.append(parent_schedule)
-
- elif model_type == "schedule":
- if entity.error_count is None:
- entity.error_count = 0
- if entity.suspended is None:
- entity.suspended = False
- if entity.build_storage_type is None:
- entity.build_storage_type = Status.STORAGE_TYPE_DICT[
- "PAB"]
- # remove None children jobs.
- if entity.children_jobs:
- entity.children_jobs = [
- x for x in entity.children_jobs if x]
- else:
- entity.children_jobs = []
-
- for attr in ["has_bootloader_img", "has_radio_img"]:
- if getattr(entity, attr, None) is None:
- setattr(entity, attr, True)
-
- # set priority_value for old schedules.
- if entity.priority_value is None:
- entity.priority_value = Status.GetPriorityValue(
- entity.priority)
- else:
- pass
- to_put.append(entity)
-
- if to_put:
- ndb.put_multi(to_put)
- num_updated += len(to_put)
-
- logging.info("{} indexing complete with {} updates!".format(
- model_type, num_updated))
diff --git a/gae/webapp/src/tasks/indexing_test.py b/gae/webapp/src/tasks/indexing_test.py
deleted file mode 100644
index 5d14a56..0000000
--- a/gae/webapp/src/tasks/indexing_test.py
+++ /dev/null
@@ -1,191 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from webapp.src.proto import model
-from webapp.src.tasks import indexing
-from webapp.src.testing import unittest_base
-
-
-class IndexingHandlerTest(unittest_base.UnitTestBase):
- """Tests for IndexingHandler.
-
- Attributes:
- testbed: A Testbed instance which provides local unit testing.
- indexing_handler: A mock IndexingHandler instance.
- """
-
- def setUp(self):
- """Initializes test"""
- super(IndexingHandlerTest, self).setUp()
- # Mocking IndexingHandler.
- self.indexing_handler = indexing.IndexingHandler(mock.Mock())
- self.indexing_handler.request = mock.Mock()
-
- def testSingleJobReindexing(self):
- """Asserts re-indexing links job and schedule successfully."""
-
- print("\nCreating a single schedule...")
- schedule = self.GenerateScheduleModel()
- schedule.put()
-
- schedules = model.ScheduleModel.query().fetch()
- self.assertEqual(1, len(schedules))
-
- print("Creating a job for stored schedule...")
- for schedule in schedules:
- job = model.JobModel()
- job.priority = schedule.priority
- job.test_name = schedule.test_name
- job.period = schedule.period
- job.build_storage_type = schedule.build_storage_type
- job.manifest_branch = schedule.manifest_branch
- job.build_target = schedule.build_target
- job.pab_account_id = schedule.device_pab_account_id
- job.shards = schedule.shards
- job.retry_count = schedule.retry_count
- job.gsi_storage_type = schedule.gsi_storage_type
- job.gsi_branch = schedule.gsi_branch
- job.gsi_build_target = schedule.gsi_build_target
- job.gsi_pab_account_id = schedule.gsi_pab_account_id
- job.gsi_vendor_version = schedule.gsi_vendor_version
- job.test_storage_type = schedule.test_storage_type
- job.test_branch = schedule.test_branch
- job.test_build_target = schedule.test_build_target
- job.test_pab_account_id = schedule.test_pab_account_id
- job.put()
-
- jobs = model.JobModel.query().fetch()
- self.assertEqual(1, len(jobs))
-
- print("Seeking children jobs before re-indexing...")
- jobs = model.JobModel.query().fetch()
- for job in jobs:
- parent_key = job.parent_schedule
- self.assertIsNone(parent_key)
-
- print("Seeking children jobs after re-indexing...")
- self.indexing_handler.request.get = mock.MagicMock(return_value="job")
- self.indexing_handler.post()
- jobs = model.JobModel.query().fetch()
- for job in jobs:
- parent_key = job.parent_schedule
- parent_schedule = parent_key.get()
- self.assertEqual(
- True,
- ((parent_schedule.priority == job.priority) and
- (parent_schedule.test_name == job.test_name) and
- (parent_schedule.period == job.period) and
- (parent_schedule.build_storage_type == job.build_storage_type)
- and (parent_schedule.manifest_branch == job.manifest_branch)
- and (parent_schedule.build_target == job.build_target) and
- (parent_schedule.device_pab_account_id == job.pab_account_id)
- and (parent_schedule.shards == job.shards) and
- (parent_schedule.retry_count == job.retry_count) and
- (parent_schedule.gsi_storage_type == job.gsi_storage_type) and
- (parent_schedule.gsi_branch == job.gsi_branch) and
- (parent_schedule.gsi_build_target == job.gsi_build_target) and
- (parent_schedule.gsi_pab_account_id == job.gsi_pab_account_id)
- and
- (parent_schedule.test_storage_type == job.test_storage_type)
- and (parent_schedule.test_branch == job.test_branch) and
- (parent_schedule.test_build_target == job.test_build_target)
- and (parent_schedule.test_pab_account_id ==
- job.test_pab_account_id)))
-
- def testMultiJobReindexing(self):
- """Asserts re-indexing links job and schedule successfully."""
- print("\nCreating four schedules...")
- for num in xrange(4):
- schedule = self.GenerateScheduleModel(test_name=str(num + 1))
- schedule.put()
- schedule.put()
-
- schedules = model.ScheduleModel.query().fetch()
- self.assertEqual(4, len(schedules))
-
- print("Creating jobs as number of test_name...")
- for schedule in schedules:
- for _ in xrange(int(schedule.test_name)):
- job = model.JobModel()
- job.priority = schedule.priority
- job.test_name = schedule.test_name
- job.period = schedule.period
- job.build_storage_type = schedule.build_storage_type
- job.manifest_branch = schedule.manifest_branch
- job.build_target = schedule.build_target
- job.pab_account_id = schedule.device_pab_account_id
- job.shards = schedule.shards
- job.retry_count = schedule.retry_count
- job.gsi_storage_type = schedule.gsi_storage_type
- job.gsi_branch = schedule.gsi_branch
- job.gsi_build_target = schedule.gsi_build_target
- job.gsi_pab_account_id = schedule.gsi_pab_account_id
- job.gsi_vendor_version = schedule.gsi_vendor_version
- job.test_storage_type = schedule.test_storage_type
- job.test_branch = schedule.test_branch
- job.test_build_target = schedule.test_build_target
- job.test_pab_account_id = schedule.test_pab_account_id
- job.put()
-
- jobs = model.JobModel.query().fetch()
- self.assertEqual(10, len(jobs))
-
- print("Seeking children jobs before re-indexing...")
- jobs = model.JobModel.query().fetch()
- for job in jobs:
- parent_key = job.parent_schedule
- self.assertIsNone(parent_key)
-
- print("Seeking children jobs after re-indexing...")
- self.indexing_handler.request.get = mock.MagicMock(return_value="job")
- self.indexing_handler.post()
- jobs = model.JobModel.query().fetch()
- for job in jobs:
- parent_key = job.parent_schedule
- parent_schedule = parent_key.get()
- self.assertEqual(
- True,
- ((parent_schedule.priority == job.priority) and
- (parent_schedule.test_name == job.test_name) and
- (parent_schedule.period == job.period) and
- (parent_schedule.build_storage_type == job.build_storage_type)
- and (parent_schedule.manifest_branch == job.manifest_branch)
- and (parent_schedule.build_target == job.build_target) and
- (parent_schedule.device_pab_account_id == job.pab_account_id)
- and (parent_schedule.shards == job.shards) and
- (parent_schedule.retry_count == job.retry_count) and
- (parent_schedule.gsi_storage_type == job.gsi_storage_type) and
- (parent_schedule.gsi_branch == job.gsi_branch) and
- (parent_schedule.gsi_build_target == job.gsi_build_target) and
- (parent_schedule.gsi_pab_account_id == job.gsi_pab_account_id)
- and
- (parent_schedule.test_storage_type == job.test_storage_type)
- and (parent_schedule.test_branch == job.test_branch) and
- (parent_schedule.test_build_target == job.test_build_target)
- and (parent_schedule.test_pab_account_id ==
- job.test_pab_account_id)))
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/gae/webapp/src/tasks/removing_outdated_devices.py b/gae/webapp/src/tasks/removing_outdated_devices.py
deleted file mode 100644
index 6a4eeab..0000000
--- a/gae/webapp/src/tasks/removing_outdated_devices.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-import datetime
-import webapp2
-
-from google.appengine.ext import ndb
-
-from webapp.src.proto import model
-
-OUTDATED_DEVICE_REMOVE_TIME_IN_HOURS = 48
-
-
-class RemoveOutdatedDevices(webapp2.RequestHandler):
- """Main class for /tasks/remove_outdated_devices.
-
- Used to find outdated devices and remove them.
- """
-
- def get(self):
- device_query = model.DeviceModel.query(
- model.DeviceModel.timestamp < datetime.datetime.now() -
- datetime.timedelta(hours=OUTDATED_DEVICE_REMOVE_TIME_IN_HOURS))
- outdated_devices = device_query.fetch(keys_only=True)
- ndb.delete_multi(outdated_devices)
diff --git a/gae/webapp/src/tasks/removing_outdated_devices_test.py b/gae/webapp/src/tasks/removing_outdated_devices_test.py
deleted file mode 100644
index 6ff57d4..0000000
--- a/gae/webapp/src/tasks/removing_outdated_devices_test.py
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from webapp.src.proto import model
-from webapp.src.tasks import removing_outdated_devices
-from webapp.src.testing import unittest_base
-
-
-class RemoveOutdatedDevicesTest(unittest_base.UnitTestBase):
- """Tests for RemoveOutdatedDevices cron class.
-
- Attributes:
- remove_outdated_device: A mock device_heartbeat.RemoveOutdatedDevices
- instance.
- """
-
- def setUp(self):
- """Initializes test"""
- super(RemoveOutdatedDevicesTest, self).setUp()
- # Mocking RemoveOutdatedDevices and essential methods.
- self.remove_outdated_device = (
- removing_outdated_devices.RemoveOutdatedDevices(mock.Mock()))
- self.remove_outdated_device.response = mock.Mock()
- self.remove_outdated_device.response.write = mock.Mock()
-
- def testRemoveOutdatedDevicesTest(self):
- """Asserts job heartbeat detects unavailable jobs."""
- device_a_serial = "a"
- device_b_serial = "b"
- device_c_serial = "c"
- device_d_serial = "c"
-
- # create a device A, which is outdated.
- device = self.GenerateDeviceModel(serial=device_a_serial)
- device.timestamp = datetime.datetime.now() - datetime.timedelta(
- hours=100)
- device.put()
-
- # create a device B, which is offline for a day.
- device = self.GenerateDeviceModel(serial=device_b_serial)
- device.timestamp = datetime.datetime.now() - datetime.timedelta(
- hours=24)
- device.put()
-
- # create a device C and D, which are alive.
- for serial in [device_c_serial, device_d_serial]:
- device = self.GenerateDeviceModel(serial=serial)
- device.timestamp = datetime.datetime.now()
- device.put()
-
- # Remove outdated devices.
- self.remove_outdated_device.get()
-
- devices = model.DeviceModel.query().fetch()
-
- # device A should not be included.
- self.assertEqual(len(devices), 3)
- self.assertTrue(device_a_serial not in [x.serial for x in devices])
-
- # change devices' timestamp
- for device in devices:
- device.timestamp = device.timestamp - datetime.timedelta(hours=25)
- device.put()
-
- # Remove outdated devices.
- self.remove_outdated_device.get()
-
- devices = model.DeviceModel.query().fetch()
-
- # Now device B should not be included also.
- self.assertEqual(len(devices), 2)
- self.assertTrue(device_b_serial not in [x.serial for x in devices])
-
- # change devices' timestamp
- for device in devices:
- device.timestamp = device.timestamp - datetime.timedelta(hours=25)
- device.put()
-
- # Remove outdated devices.
- self.remove_outdated_device.get()
-
- devices = model.DeviceModel.query().fetch()
-
- # Now there should not be no devices.
- self.assertEqual(len(devices), 0)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/gae/webapp/src/testing/__init__.py b/gae/webapp/src/testing/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/testing/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/testing/unittest_base.py b/gae/webapp/src/testing/unittest_base.py
deleted file mode 100644
index 0e47ee0..0000000
--- a/gae/webapp/src/testing/unittest_base.py
+++ /dev/null
@@ -1,347 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import random
-import string
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from google.appengine.ext import ndb
-from google.appengine.ext import testbed
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-
-
-class UnitTestBase(unittest.TestCase):
- """Base class for unittest.
-
- Attributes:
- testbed: A Testbed instance which provides local unit testing.
- random_strs: a list of strings generated by GetRandomString() method
- in order to avoid duplicates.
- """
- random_strs = []
-
- def setUp(self):
- """Initializes unittest."""
- # Create the Testbed class instance and initialize service stubs.
- self.testbed = testbed.Testbed()
- self.testbed.activate()
- self.testbed.init_datastore_v3_stub()
- self.testbed.init_memcache_stub()
- self.testbed.init_mail_stub()
- self.testbed.setup_env(app_id="vtslab-schedule-unittest")
- # Clear cache between tests.
- ndb.get_context().clear_cache()
-
- def tearDown(self):
- self.testbed.deactivate()
-
- def GetRandomString(self, length=7):
- """Generates and returns a random string.
-
- Args:
- length: an integer, string length.
-
- Returns:
- a random string.
- """
- new_str = ""
- while new_str == "" or new_str in self.random_strs:
- new_str = "".join(
- random.choice(string.ascii_letters + string.digits)
- for _ in range(length))
- return new_str
-
- def GenerateLabModel(self, lab_name=None, host_name=None):
- """Builds model.LabModel with given information.
-
- Args:
- lab_name: a string, lab name.
- host_name: a string, host name.
-
- Returns:
- model.LabModel instance.
- """
- lab = model.LabModel()
- lab.name = lab_name if lab_name else self.GetRandomString()
- lab.hostname = host_name if host_name else self.GetRandomString()
- lab.owner = "test@abc.com"
- lab.ip = "100.100.100.100"
- return lab
-
- def GenerateDeviceModel(
- self,
- status=Status.DEVICE_STATUS_DICT["fastboot"],
- scheduling_status=Status.DEVICE_SCHEDULING_STATUS_DICT["free"],
- **kwargs):
- """Builds model.DeviceModel with given information.
-
- Args:
- status: an integer, device's initial status.
- scheduling_status: an integer, device's initial scheduling status.
- **kwargs: the optional arguments.
-
- Returns:
- model.DeviceModel instance.
- """
- device = model.DeviceModel()
- device.status = status
- device.scheduling_status = scheduling_status
- device.timestamp = datetime.datetime.now()
-
- skip_list = ["status", "scheduling_status", "timestamp"]
- set_or_empty = []
- for arg in device._properties:
- if arg in skip_list or (arg in set_or_empty and arg not in kwargs):
- continue
- if arg in kwargs:
- value = kwargs[arg]
- elif isinstance(device._properties[arg], ndb.StringProperty):
- value = self.GetRandomString()
- elif isinstance(device._properties[arg], ndb.IntegerProperty):
- value = 0
- elif isinstance(device._properties[arg], ndb.BooleanProperty):
- value = False
- else:
- print("A type of property '{}' is not supported.".format(arg))
- continue
- if device._properties[arg]._repeated and type(value) is not list:
- value = [value]
- setattr(device, arg, value)
- return device
-
- def GenerateScheduleModel(
- self,
- device_model=None,
- lab_model=None,
- priority="medium",
- period=360,
- retry_count=1,
- shards=1,
- lab_name=None,
- device_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
- device_branch=None,
- device_target=None,
- gsi_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
- gsi_build_target=None,
- test_storage_type=Status.STORAGE_TYPE_DICT["PAB"],
- test_build_target=None,
- required_signed_device_build=False,
- **kwargs):
- """Builds model.ScheduleModel with given information.
-
- Args:
- device_model: a model.DeviceModel instance to refer device product.
- lab_model: a model.LabModel instance to refer host name.
- priority: a string, scheduling priority
- period: an integer, scheduling period.
- retry_count: an integer, scheduling retry count.
- shards: an integer, # ways of device shards.
- lab_name: a string, target lab name.
- device_storage_type: an integer, device storage type
- device_branch: a string, device build branch.
- device_target: a string, device build target.
- gsi_storage_type: an integer, GSI storage type
- gsi_build_target: a string, GSI build target.
- test_storage_type: an integer, test storage type
- test_build_target: a string, test build target.
- required_signed_device_build: a boolean, True to schedule for signed
- device build, False if not.
- **kwargs: the optional arguments.
-
- Returns:
- model.ScheduleModel instance.
- """
-
- if device_model:
- device_product = device_model.product
- device_target = self.GetRandomString(4)
- elif device_target:
- device_product, device_target = device_target.split("-")
- else:
- device_product = self.GetRandomString(7)
- device_target = self.GetRandomString(4)
-
- if lab_model:
- lab = lab_model.name
- elif lab_name:
- lab = lab_name
- else:
- lab = self.GetRandomString()
-
- schedule = model.ScheduleModel()
- schedule.priority = priority
- schedule.priority_value = Status.GetPriorityValue(schedule.priority)
- schedule.period = period
- schedule.shards = shards
- schedule.retry_count = retry_count
- schedule.required_signed_device_build = required_signed_device_build
- schedule.build_storage_type = device_storage_type
- schedule.manifest_branch = (device_branch if device_branch else
- self.GetRandomString())
- schedule.build_target = "-".join([device_product, device_target])
-
- schedule.gsi_storage_type = gsi_storage_type
- schedule.gsi_build_target = (gsi_build_target
- if gsi_build_target else "-".join([
- self.GetRandomString(),
- self.GetRandomString(4)
- ]))
- schedule.test_storage_type = test_storage_type
- schedule.test_build_target = (test_build_target
- if test_build_target else "-".join([
- self.GetRandomString(),
- self.GetRandomString(4)
- ]))
- schedule.device = []
- schedule.device.append("/".join([lab, device_product]))
-
- schedule.timestamp = datetime.datetime.now()
-
- skip_list = [
- "priority", "priority_value", "period", "shards",
- "retry_count", "required_signed_device_build",
- "build_storage_type", "manifest_branch", "build_target",
- "gsi_storage_type", "gsi_build_target",
- "test_storage_type", "test_build_target", "device",
- "children_jobs"]
- set_or_empty = ["required_host_equipment", "required_device_equipment"]
- for arg in schedule._properties:
- if arg in skip_list or (arg in set_or_empty and arg not in kwargs):
- continue
- if arg in kwargs:
- value = kwargs[arg]
- elif isinstance(schedule._properties[arg], ndb.StringProperty):
- value = self.GetRandomString()
- elif isinstance(schedule._properties[arg], ndb.IntegerProperty):
- value = 0
- elif isinstance(schedule._properties[arg], ndb.BooleanProperty):
- value = False
- else:
- print("A type of property '{}' is not supported.".format(arg))
- continue
- if schedule._properties[arg]._repeated and type(value) is not list:
- value = [value]
- setattr(schedule, arg, value)
-
- return schedule
-
- def GenerateBuildModel(self, schedule, targets=None):
- """Builds model.BuildModel with given information.
-
- Args:
- schedule: a model.ScheduleModel instance to look up build info.
- targets: a list of strings which indicates artifact type.
-
- Returns:
- model.BuildModel instance.
- """
- build_dict = {}
- if targets is None:
- targets = ["device", "gsi", "test"]
- for target in targets:
- build = model.BuildModel()
- build.artifact_type = target
- build.timestamp = datetime.datetime.now()
- if target == "device":
- build.signed = schedule.required_signed_device_build
- build.manifest_branch = schedule.manifest_branch
- build.build_target, build.build_type = (
- schedule.build_target.split("-"))
- elif target == "gsi":
- build.manifest_branch = schedule.gsi_branch
- build.build_target, build.build_type = (
- schedule.gsi_build_target.split("-"))
- elif target == "test":
- build.manifest_branch = schedule.test_branch
- build.build_target, build.build_type = (
- schedule.test_build_target.split("-"))
- build.build_id = self.GetNewBuildId(build)
- build_dict[target] = build
- return build_dict
-
- def GetNewBuildId(self, build):
- """Generates build ID.
-
- This method always generates newest (higher number) build ID than other
- builds stored in testbed datastore.
-
- Args:
- build: a model.BuildModel instance to look up build information
- from testbed datastore.
-
- Returns:
- a string, build ID.
- """
- format_string = "{0:07d}"
- build_query = model.BuildModel.query(
- model.BuildModel.artifact_type == build.artifact_type,
- model.BuildModel.build_target == build.build_target,
- model.BuildModel.signed == build.signed,
- model.BuildModel.manifest_branch == build.manifest_branch)
- exiting_builds = build_query.fetch()
- if exiting_builds:
- exiting_builds.sort(key=lambda x: x.build_id, reverse=True)
- latest_build_id = int(exiting_builds[0].build_id)
- return format_string.format(latest_build_id + 1)
- else:
- return format_string.format(1)
-
- def PassTime(self, hours=0, minutes=0, seconds=0):
- """Assumes that a certain amount of time has passed.
-
- This method changes does not change actual system time but changes all
- jobs timestamp to assume time has passed.
-
- Args:
- hours: an integer, number of hours to pass time.
- minutes: an integer, number of minutes to pass time.
- seconds: an integer, number of seconds to pass time.
- """
- if not hours and not minutes and not seconds:
- return
-
- jobs = model.JobModel.query().fetch()
- to_put = []
- for job in jobs:
- if job.timestamp:
- job.timestamp -= datetime.timedelta(
- hours=hours, minutes=minutes, seconds=seconds)
- if job.heartbeat_stamp:
- job.heartbeat_stamp -= datetime.timedelta(
- hours=hours, minutes=minutes, seconds=seconds)
- to_put.append(job)
- if to_put:
- ndb.put_multi(to_put)
-
- def ResetDevices(self):
- """Resets all devices to ready status."""
- devices = model.DeviceModel.query().fetch()
- to_put = []
- for device in devices:
- device.status = Status.DEVICE_STATUS_DICT["fastboot"]
- device.scheduling_status = Status.DEVICE_SCHEDULING_STATUS_DICT[
- "free"]
- to_put.append(device)
- if to_put:
- ndb.put_multi(to_put)
diff --git a/gae/webapp/src/utils/__init__.py b/gae/webapp/src/utils/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/gae/webapp/src/utils/__init__.py
+++ /dev/null
diff --git a/gae/webapp/src/utils/datetime_util.py b/gae/webapp/src/utils/datetime_util.py
deleted file mode 100644
index a1cff67..0000000
--- a/gae/webapp/src/utils/datetime_util.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import logging
-import pytz
-
-
-def GetTimeWithTimezone(dt, timezone="US/Pacific"):
- """Converts timezone of datetime.datetime() instance.
-
- Args:
- dt: datetime.datetime() instance.
- timezone: a string representing timezone listed in TZ database.
-
- Returns:
- datetime.datetime() instance with the given timezone.
- """
- if not dt:
- return None
- utc_time = dt.replace(tzinfo=pytz.utc)
- try:
- converted_time = utc_time.astimezone(pytz.timezone(timezone))
- except pytz.UnknownTimeZoneError as e:
- logging.exception(e)
- converted_time = dt
- return converted_time
diff --git a/gae/webapp/src/utils/email_util.py b/gae/webapp/src/utils/email_util.py
deleted file mode 100644
index 2ef795e..0000000
--- a/gae/webapp/src/utils/email_util.py
+++ /dev/null
@@ -1,295 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import logging
-import re
-
-from google.appengine.api import app_identity
-from google.appengine.api import mail
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.utils import datetime_util
-
-SENDER_ADDRESS = "noreply@{}.appspotmail.com"
-
-SEND_NOTIFICATION_FOOTER = (
- "You are receiving this email because you are "
- "listed as an owner, or an administrator of the "
- "lab {}.\nIf you received this email by mistake, "
- "please send an email to VTS Lab infra development "
- "team. Thank you.")
-
-SEND_DEVICE_NOTIFICATION_TITLE = ("[VTS lab] Devices not responding in lab {} "
- "({})")
-SEND_DEVICE_NOTIFICATION_HEADER = "Devices in lab {} are not responding."
-
-SEND_JOB_NOTIFICATION_TITLE = ("[VTS lab] Job error has been occurred in "
- "lab {} ({})")
-SEND_JOB_NOTIFICATION_HEADER = ("Jobs in lab {} have been completed "
- "unexpectedly.")
-SEND_SCHEDULE_SUSPENSION_NOTIFICATION_TITLE = (
- "[VTS lab] A job schedule has been {}. ({})")
-SEND_SCHEDULE_SUSPENSION_NOTIFICATION_HEADER = ("The below job schedule has "
- "been {}.")
-SEND_SCHEDULE_SUSPENSION_NOTIFICATION_FOOTER = (
- "You are receiving this email because one or more labs which you are "
- "listed as an owner or an administrator are affected.\nIf you received "
- "this email by mistake, please send an email to VTS Lab infra development "
- "team. Thank you.")
-
-
-def send_device_notification(devices):
- """Sends notification for not responding devices.
-
- Args:
- devices: a dict containing lab and host information of no-response
- devices.
- """
- for lab in devices:
- email_message = mail.EmailMessage()
- email_message.sender = SENDER_ADDRESS.format(
- app_identity.get_application_id())
- try:
- email_message.to = verify_recipient_address(
- devices[lab]["_recipients"])
- except ValueError as e:
- logging.error(e)
- continue
- email_message.subject = SEND_DEVICE_NOTIFICATION_TITLE.format(
- lab,
- datetime_util.GetTimeWithTimezone(
- datetime.datetime.now()).strftime("%Y-%m-%d"))
- message = ""
- message += SEND_DEVICE_NOTIFICATION_HEADER.format(lab)
- message += "\n\n"
- for host in devices[lab]:
- if host == "_recipients" or not devices[lab][host]:
- continue
- message += "hostname\n"
- message += host
- message += "\n\ndevices\n"
- message += "\n".join(devices[lab][host])
- message += "\n\n\n"
- message += "\n\n"
- message += SEND_NOTIFICATION_FOOTER.format(lab)
-
- try:
- email_message.body = message
- email_message.check_initialized()
- email_message.send()
- except mail.MissingRecipientError as e:
- logging.exception(e)
-
-
-def send_job_notification(jobs):
- """Sends notification for job error.
-
- Args:
- jobs: a JobModel entity, or a list of JobModel entities.
- """
- if not jobs:
- return
- if type(jobs) is not list:
- jobs = [jobs]
-
- # grouping jobs by lab to send to each lab owner and admins at once.
- labs_to_alert = {}
- for job in jobs:
- lab_query = model.LabModel.query(
- model.LabModel.hostname == job.hostname)
- labs = lab_query.fetch()
- if labs:
- lab = labs[0]
- if lab.name not in labs_to_alert:
- labs_to_alert[lab.name] = {}
- labs_to_alert[lab.name]["jobs"] = []
- labs_to_alert[lab.name]["_recipients"] = []
- if lab.owner not in labs_to_alert[lab.name]["_recipients"]:
- labs_to_alert[lab.name]["_recipients"].append(lab.owner)
- labs_to_alert[lab.name]["_recipients"].extend([
- x for x in lab.admin
- if x not in labs_to_alert[lab.name]["_recipients"]
- ])
- labs_to_alert[lab.name]["jobs"].append(job)
- else:
- logging.warning(
- "Could not find a lab model for hostname {}".format(
- job.hostname))
- continue
-
- for lab in labs_to_alert:
- email_message = mail.EmailMessage()
- email_message.sender = SENDER_ADDRESS.format(
- app_identity.get_application_id())
- try:
- email_message.to = verify_recipient_address(
- labs_to_alert[lab]["_recipients"])
- except ValueError as e:
- logging.error(e)
- continue
- email_message.subject = SEND_JOB_NOTIFICATION_TITLE.format(
- lab,
- datetime_util.GetTimeWithTimezone(
- datetime.datetime.now()).strftime("%Y-%m-%d"))
- message = ""
- message += SEND_JOB_NOTIFICATION_HEADER.format(lab)
- message += "\n\n"
- message += "http://{}.appspot.com/job".format(
- app_identity.get_application_id())
- message += "\n\n"
- for job in labs_to_alert[lab]["jobs"]:
- message += "hostname: {}\n\n".format(job.hostname)
- message += "device: {}\n".format(job.device.split("/")[1])
- message += "device serial: {}\n".format(", ".join(job.serial))
- message += (
- "device: branch - {}, target - {}, build_id - {}\n").format(
- job.manifest_branch, job.build_target, job.build_id)
- message += "gsi: branch - {}, target - {}, build_id - {}\n".format(
- job.gsi_branch, job.gsi_build_target, job.gsi_build_id)
- message += "test: branch - {}, target - {}, build_id - {}\n".format(
- job.test_branch, job.test_build_target, job.test_build_id)
- message += "job created: {}\n".format(
- datetime_util.GetTimeWithTimezone(
- job.timestamp).strftime("%Y-%m-%d %H:%M:%S %Z"))
- message += "job status: {}\n".format([
- key for key, value in Status.JOB_STATUS_DICT.items()
- if value == job.status
- ][0])
- message += "\n\n\n"
- message += "\n\n"
- message += SEND_NOTIFICATION_FOOTER.format(lab)
-
- try:
- email_message.body = message
- email_message.check_initialized()
- email_message.send()
- except mail.MissingRecipientError as e:
- logging.exception(e)
-
-
-def send_schedule_suspension_notification(schedule):
- """Sends notification when a schedule is suspended, or resumed.
-
- Args:
- schedule: a ScheduleModel entity.
- """
- if not schedule:
- return
-
- if not schedule.device:
- return
-
- email_message = mail.EmailMessage()
- email_message.sender = SENDER_ADDRESS.format(
- app_identity.get_application_id())
-
- lab_names = []
- for device in schedule.device:
- if not "/" in device:
- continue
- lab_name = device.split("/")[0]
- lab_names.append(lab_name)
-
- recipients = []
- for lab_name in lab_names:
- lab_query = model.LabModel.query(model.LabModel.name == lab_name)
- labs = lab_query.fetch()
- if labs:
- lab = labs[0]
- if lab.owner not in recipients:
- recipients.append(lab.owner)
- recipients.extend([x for x in lab.admin if x not in recipients])
- else:
- logging.warning(
- "Could not find a lab model for lab {}".format(lab_name))
-
- try:
- email_message.to = verify_recipient_address(recipients)
- except ValueError as e:
- logging.error(e)
- return
-
- status_text = "suspended" if schedule.suspended else "resumed"
- email_message.subject = SEND_SCHEDULE_SUSPENSION_NOTIFICATION_TITLE.format(
- status_text,
- datetime_util.GetTimeWithTimezone(
- datetime.datetime.now()).strftime("%Y-%m-%d"))
- message = ""
- message += SEND_SCHEDULE_SUSPENSION_NOTIFICATION_HEADER.format(status_text)
- message += "\n\n"
- message += "\n\ndevices\n"
- message += "\n".join(schedule.device)
- message += "\n\ndevice branch\n"
- message += schedule.manifest_branch
- message += "\n\ndevice build target\n"
- message += schedule.build_target
- message += "\n\ngsi branch\n"
- message += schedule.gsi_branch
- message += "\n\ngsi build target\n"
- message += schedule.gsi_build_target
- message += "\n\ntest branch\n"
- message += schedule.test_branch
- message += "\n\ntest build target\n"
- message += schedule.test_build_target
- message += "\n\n"
- message += ("Please see the details in the following link: "
- "http://{}.appspot.com/schedule".format(
- app_identity.get_application_id()))
- message += "\n\n\n\n"
- message += SEND_SCHEDULE_SUSPENSION_NOTIFICATION_FOOTER
-
- try:
- email_message.body = message
- email_message.check_initialized()
- email_message.send()
- except mail.MissingRecipientError as e:
- logging.exception(e)
-
-
-def verify_recipient_address(address):
- """Verifies recipients address.
-
- Args:
- address: a list of strings or a string, recipient(s) address.
-
- Returns:
- A list of verified addresses if list type argument is given, or
- a string of a verified address if str type argument is given.
-
- Raises:
- ValueError if type of address is neither list nor str.
- """
- # pattern for 'any@google.com', and 'any name <any@google.com>'
- verify_patterns = [
- re.compile(".*@google\.com$"),
- re.compile(".*<.*@google\.com>$")
- ]
- if not address:
- return None
- if type(address) is list:
- verified_address = [
- x for x in address
- if any(pattern.match(x) for pattern in verify_patterns)
- ]
- return verified_address
- elif type(address) is str:
- return address if any(
- pattern.match(address) for pattern in verify_patterns) else None
- else:
- raise ValueError("Wrong type - {}.".format(type(address)))
diff --git a/gae/webapp/src/utils/logger.py b/gae/webapp/src/utils/logger.py
deleted file mode 100644
index 20c03d2..0000000
--- a/gae/webapp/src/utils/logger.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-
-class Logger(object):
- """A class to log messages to a list of strings.
-
- Attributes:
- log_message: a list of strings, containing the log messages.
- log_indent: integer, representing the index level
- """
-
- def __init__(self):
- self.log_message = []
- self.log_indent = 0
-
- def Clear(self):
- """Clears the log buffer."""
- self.log_message = []
- self.log_indent = 0
-
- def Get(self):
- """Retruns a list of all log message strings."""
- return self.log_message
-
- def Println(self, msg):
- """Stores a new string `msg` to the log buffer."""
- indent = " " * self.log_indent
- if msg and type(msg) is not str:
- msg = str(msg)
- self.log_message.append(indent + msg)
-
- def Indent(self):
- """Increase indent of log message."""
- self.log_indent += 1
-
- def Unindent(self):
- """Decrease indent of log message."""
- if self.log_indent > 0:
- self.log_indent -= 1
diff --git a/gae/webapp/src/utils/model_util.py b/gae/webapp/src/utils/model_util.py
deleted file mode 100644
index aa07a63..0000000
--- a/gae/webapp/src/utils/model_util.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-from webapp.src import vtslab_status as Status
-from webapp.src.utils import email_util
-
-
-def UpdateParentSchedule(job, status):
- """Updates a parent schedule of the given job with status.
-
- Args:
- job: a JobModel entity.
- status: an integer, job status value.
- """
- if status not in [
- Status.JOB_STATUS_DICT["complete"],
- Status.JOB_STATUS_DICT["infra-err"],
- Status.JOB_STATUS_DICT["expired"],
- Status.JOB_STATUS_DICT["bootup-err"]
- ]:
- return
-
- if job.parent_schedule:
- schedule = job.parent_schedule.get()
- if schedule:
- previous_suspended = schedule.suspended
- if schedule.error_count is None:
- schedule.error_count = 0
- if status == Status.JOB_STATUS_DICT["complete"]:
- schedule.error_count = 0
- schedule.suspended = False
- elif status in [
- Status.JOB_STATUS_DICT["infra-err"],
- Status.JOB_STATUS_DICT["expired"],
- Status.JOB_STATUS_DICT["bootup-err"]
- ]:
- schedule.error_count += 1
- if schedule.error_count >= Status.NUM_ERRORS_FOR_SUSPENSION:
- schedule.suspended = True
- schedule.put()
- if previous_suspended != schedule.suspended:
- email_util.send_schedule_suspension_notification(schedule)
diff --git a/gae/webapp/src/utils/model_util_test.py b/gae/webapp/src/utils/model_util_test.py
deleted file mode 100644
index 4be54b1..0000000
--- a/gae/webapp/src/utils/model_util_test.py
+++ /dev/null
@@ -1,170 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import datetime
-import unittest
-
-try:
- from unittest import mock
-except ImportError:
- import mock
-
-from webapp.src import vtslab_status as Status
-from webapp.src.proto import model
-from webapp.src.scheduler import schedule_worker
-from webapp.src.testing import unittest_base
-from webapp.src.utils import model_util
-
-
-class ModelTest(unittest_base.UnitTestBase):
- """Tests for PeriodicJobHeartBeat cron class."""
-
- def testJobAndScheduleModel(self):
- """Asserts JobModel and ScheduleModel.
-
- When JobModel's status is changed, ScheduleModel's error_count is
- changed based on the status. This should not be applied before JobModel
- entity is updated to Datastore.
- """
- period = 360
-
- lab = self.GenerateLabModel()
- lab.put()
-
- device = self.GenerateDeviceModel(hostname=lab.hostname)
- device.put()
-
- schedule = self.GenerateScheduleModel(
- device_model=device, lab_model=lab, period=period)
- schedule.put()
-
- build_dict = self.GenerateBuildModel(schedule)
- for key in build_dict:
- build_dict[key].put()
-
- # Mocking ScheduleHandler and essential methods.
- scheduler = schedule_worker.ScheduleHandler(mock.Mock())
- scheduler.response = mock.Mock()
- scheduler.response.write = mock.Mock()
- scheduler.request.get = mock.MagicMock(return_value="")
-
- print("\nCreating a job...")
- scheduler.post()
- jobs = model.JobModel.query().fetch()
- self.assertEqual(1, len(jobs))
-
- print("Occurring infra error...")
- job = jobs[0]
- job.status = Status.JOB_STATUS_DICT["infra-err"]
- parent_schedule = job.parent_schedule.get()
- parent_from_db = model.ScheduleModel.query().fetch()[0]
-
- # in test error_count could be None but in real there will be no None.
- self.assertNotEqual(1, parent_schedule.error_count)
- self.assertNotEqual(1, parent_from_db.error_count)
-
- # error count should be changed after put
- job.put()
- model_util.UpdateParentSchedule(job, job.status)
- self.assertEqual(1, parent_schedule.error_count)
- self.assertEqual(1, parent_from_db.error_count)
-
- print("Suspending a job...")
- for num in xrange(2):
- jobs = model.JobModel.query().fetch()
- for job in jobs:
- job.timestamp = datetime.datetime.now() - datetime.timedelta(
- minutes=(period + 10))
- job.put()
-
- parent_from_db = model.ScheduleModel.query().fetch()[0]
- self.assertEqual(1 + num, parent_schedule.error_count)
- self.assertEqual(1 + num, parent_from_db.error_count)
-
- # reset a device manually to re-schedule
- device = model.DeviceModel.query().fetch()[0]
- device.status = Status.DEVICE_STATUS_DICT["fastboot"]
- device.scheduling_status = (
- Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
- device.timestamp = datetime.datetime.now()
- device.put()
-
- scheduler.post()
- jobs = model.JobModel.query().fetch()
- self.assertEqual(2 + num, len(jobs))
-
- ready_jobs = model.JobModel.query(
- model.JobModel.status == Status.JOB_STATUS_DICT[
- "ready"]).fetch()
- self.assertEqual(1, len(ready_jobs))
-
- ready_job = ready_jobs[0]
- ready_job.status = Status.JOB_STATUS_DICT["infra-err"]
- parent_schedule = ready_job.parent_schedule.get()
- parent_from_db = model.ScheduleModel.query().fetch()[0]
- self.assertEqual(1 + num, parent_schedule.error_count)
- self.assertEqual(1 + num, parent_from_db.error_count)
-
- # # error count should be changed after put
- ready_job.put()
- model_util.UpdateParentSchedule(ready_job, ready_job.status)
- self.assertEqual(2 + num, parent_schedule.error_count)
- self.assertEqual(2 + num, parent_from_db.error_count)
-
- print("Asserting a schedule's suspend status...")
- # after three errors the schedule should be suspended.
- schedule_from_db = model.ScheduleModel.query().fetch()[0]
- schedule_from_db.put()
- self.assertEqual(3, schedule_from_db.error_count)
- self.assertEqual(True, schedule_from_db.suspended)
-
- # reset a device manually to re-schedule
- device = model.DeviceModel.query().fetch()[0]
- device.status = Status.DEVICE_STATUS_DICT["fastboot"]
- device.scheduling_status = (
- Status.DEVICE_SCHEDULING_STATUS_DICT["free"])
- device.timestamp = datetime.datetime.now()
- device.put()
-
- print("Asserting that job creation is blocked...")
- jobs = model.JobModel.query().fetch()
- self.assertEqual(3, len(jobs))
-
- for job in jobs:
- job.timestamp = datetime.datetime.now() - datetime.timedelta(
- minutes=(period + 10))
- job.put()
-
- scheduler.post()
-
- # a job should not be created.
- jobs = model.JobModel.query().fetch()
- self.assertEqual(3, len(jobs))
-
- print("Asserting that job creation is allowed after resuming...")
- schedule_from_db = model.ScheduleModel.query().fetch()[0]
- schedule_from_db.suspended = False
- schedule_from_db.put()
-
- scheduler.post()
-
- jobs = model.JobModel.query().fetch()
- self.assertEqual(4, len(jobs))
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/gae/webapp/src/vtslab_status.py b/gae/webapp/src/vtslab_status.py
deleted file mode 100644
index c1d1363..0000000
--- a/gae/webapp/src/vtslab_status.py
+++ /dev/null
@@ -1,137 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# Status dict updated from HC.
-DEVICE_STATUS_DICT = {
- # default state, currently not in use.
- "unknown": 0,
- # for devices detected via "fastboot devices" shell command.
- "fastboot": 1,
- # for devices detected via "adb devices" shell command.
- "online": 2,
- # currently not in use.
- "ready": 3,
- # currently not in use.
- "use": 4,
- # for devices in error state.
- "error": 5,
- # for devices which timed out (not detected either via fastboot or adb).
- "no-response": 6
-}
-
-# Scheduling status dict based on the status of each jobs in job queue.
-DEVICE_SCHEDULING_STATUS_DICT = {
- # for devices detected but not scheduled.
- "free": 0,
- # for devices scheduled but not running.
- "reserved": 1,
- # for devices scheduled for currently leased job(s).
- "use": 2
-}
-
-# Job status dict
-JOB_STATUS_DICT = {
- # scheduled but not leased yet
- "ready": 0,
- # scheduled and in running
- "leased": 1,
- # completed job
- "complete": 2,
- # unexpected error during running
- "infra-err": 3,
- # never leased within schedule period
- "expired": 4,
- # device boot error after flashing the given img sets
- "bootup-err": 5
-}
-
-JOB_PRIORITY_DICT = {
- "top": 3,
- "high": 6,
- "medium": 9,
- "low": 12,
- "other": 15
-}
-
-
-STORAGE_TYPE_DICT = {
- "unknown": 0,
- "PAB": 1,
- "GCS": 2
-}
-
-
-TEST_TYPE_UNKNOWN = "unknown"
-TEST_TYPE_TOT = "ToT"
-TEST_TYPE_OTA = "OTA"
-TEST_TYPE_SIGNED = "signed"
-TEST_TYPE_PRESUBMIT = "presubmit"
-TEST_TYPE_MANUAL = "manual"
-
-# a dict, where keys indicate test type and values have bitwise values.
-# bit 0-1 : version related test type
-# 00 - Unknown
-# 01 - ToT
-# 10 - OTA
-# bit 2 : device signed build
-# bit 3-4 : reserved for gerrit related test type
-# 01 - pre-submit
-# bit 5 : manually created test job
-TEST_TYPE_DICT = {
- TEST_TYPE_UNKNOWN: 0,
- TEST_TYPE_TOT: 1,
- TEST_TYPE_OTA: 1 << 1,
- TEST_TYPE_SIGNED: 1 << 2,
- TEST_TYPE_PRESUBMIT: 1 << 3,
- TEST_TYPE_MANUAL: 1 << 5
-}
-
-# # of errors in a row to suspend a schedule
-NUM_ERRORS_FOR_SUSPENSION = 3
-
-# filter methods
-FILTER_EqualTo = "EqualTo"
-FILTER_LessThan = "LessThan"
-FILTER_GreaterThan = "GreaterThan"
-FILTER_LessThanOrEqualTo = "LessThanOrEqualTo"
-FILTER_GreaterThanOrEqualTo = "GreaterThanOrEqualTo"
-FILTER_NotEqualTo = "NotEqualTo"
-FILTER_Has = "Has"
-
-FILTER_METHOD = {
- FILTER_EqualTo: 1,
- FILTER_LessThan: 2,
- FILTER_GreaterThan: 3,
- FILTER_LessThanOrEqualTo: 4,
- FILTER_GreaterThanOrEqualTo: 5,
- FILTER_NotEqualTo: 6,
- FILTER_Has: 7,
-}
-
-
-def GetPriorityValue(priority):
- """Helper function to sort jobs based on priority.
-
- Args:
- priority: string, the job priority.
-
- Returns:
- int, priority order (the lower, the higher)
- """
- if priority:
- priority = priority.lower()
- if priority in JOB_PRIORITY_DICT:
- return JOB_PRIORITY_DICT[priority]
- return JOB_PRIORITY_DICT["other"]
diff --git a/gae/webapp/src/webapp_main.py b/gae/webapp/src/webapp_main.py
deleted file mode 100644
index 2587f4b..0000000
--- a/gae/webapp/src/webapp_main.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import os
-
-import webapp2
-
-from webapp.src.handlers import base
-from webapp.src.scheduler import device_heartbeat
-from webapp.src.scheduler import job_heartbeat
-from webapp.src.scheduler import periodic
-from webapp.src.tasks import indexing
-from webapp.src.tasks import removing_outdated_devices
-
-
-class RedirectHandler(base.BaseHandler):
- """Redirect handler to redirect to specific appspot version."""
- def get(self, arg):
- if arg:
- return self.redirect("https://{}.appspot.com/".format(arg))
-
-
-class MainPage(base.BaseHandler):
- """Main web page request handler."""
-
- def get(self):
- """Generates an HTML page."""
- self.template = "index.html"
-
- template_values = {}
-
- self.render(template_values)
-
-
-config = {}
-config['webapp2_extras.sessions'] = {
- 'secret_key': os.environ.get('SESSION_SECRET_KEY'),
-}
-
-app = webapp2.WSGIApplication(
- [
- ("/tasks/schedule", periodic.PeriodicScheduler),
- ("/tasks/device_heartbeat", device_heartbeat.PeriodicDeviceHeartBeat),
- ("/tasks/job_heartbeat", job_heartbeat.PeriodicJobHeartBeat),
- ("/tasks/remove_outdated_devices",
- removing_outdated_devices.RemoveOutdatedDevices),
- ("/tasks/indexing([/]?.*)", indexing.CreateIndex),
- ("/redirect/(.*)", RedirectHandler),
- ],
- config=config,
- debug=False)
diff --git a/gae/webapp/src/worker_main.py b/gae/webapp/src/worker_main.py
deleted file mode 100644
index 40afdf9..0000000
--- a/gae/webapp/src/worker_main.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-from webapp.src.tasks import indexing
-from webapp.src.scheduler import schedule_worker
-import webapp2
-
-
-app = webapp2.WSGIApplication([
- ("/worker/schedule_handler", schedule_worker.ScheduleHandler),
- ("/worker/indexing", indexing.IndexingHandler)
- ], debug=True)
diff --git a/gae/worker.yaml b/gae/worker.yaml
deleted file mode 100644
index 7d6b859..0000000
--- a/gae/worker.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-runtime: python27
-api_version: 1
-threadsafe: true
-service: worker
-
-handlers:
-- url: /.*
- script: webapp.src.worker_main.app
- login: admin
-
-# [START exclude]
-skip_files:
-- ^(.*/)?#.*#$
-- ^(.*/)?.*~$
-- ^(.*/)?.*\.py[co]$
-- ^(.*/)?.*/RCS/.*$
-- ^(.*/)?\..*$
-- ^script/*$
-- .*_test.py$
-- ^(.*/)?frontend/(.*)
-- ^(.*/)?\.idea/(.*)
-# [END exclude]
diff --git a/proto/GreenBuildScheduleConfigMessage.proto b/proto/GreenBuildScheduleConfigMessage.proto
deleted file mode 100644
index 3ca5679..0000000
--- a/proto/GreenBuildScheduleConfigMessage.proto
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto2";
-
-package android.test.lab;
-
-// To specify a green build scheduling policy.
-message GreenBuildScheduleConfigMessage {
- // Schedule name.
- optional bytes name = 1;
-
- // Schedule description (e.g., daily/HH:MM)
- optional bytes schedule = 2;
-
- // Scheduling priority (e.g., top, high, medium, low)
- optional bytes priority = 3;
-
- // if GSI (General System Image) is used, GSI manifest branch name.
- optional bytes gsi_branch = 11;
-
- // if GSI (General System Image) is used, GSI PAB account ID.
- optional bytes gsi_pab_account_id = 12;
-
- // Test package's manifest branch name.
- optional bytes test_branch = 21;
-
- // PAB account ID for test package.
- optional bytes test_pab_account_id = 22;
-
- repeated GreenBuildTestScheduleConfigMessage test = 31;
-}
-
-// To specify a test plan scheduling policy.
-message GreenBuildTestScheduleConfigMessage {
- // Test name (e.g., test_group/test_plan)
- optional bytes test_name = 1;
-
- // Test package's build target name.
- optional bytes test_build_target = 11;
-
- // Device manifest branch name.
- optional bytes device_branch = 21;
-
- // Device PAB account ID.
- optional bytes device_pab_account_id = 22;
-
- repeated GreenBuildDeviceScheduleConfigMessage device = 31;
-}
-
-// To specify a device scheduling policy.
-message GreenBuildDeviceScheduleConfigMessage {
- // Device type (format: <lab>/<device type>)
- optional bytes device = 1;
-
- // Number of shards (0 for auto selection)
- optional int32 shards = 11;
-
- // Device manifest branch name if different.
- optional bytes device_branch = 21;
-
- // Device build target if different.
- optional bytes device_build_target = 22;
-
- // Device PAB account ID if different.
- optional bytes device_pab_account_id = 23;
-
- // GSI's build target name.
- optional bytes gsi_build_target = 31;
-}
diff --git a/proto/GreenBuildScheduleConfigMessage_pb2.py b/proto/GreenBuildScheduleConfigMessage_pb2.py
deleted file mode 100644
index a001a7a..0000000
--- a/proto/GreenBuildScheduleConfigMessage_pb2.py
+++ /dev/null
@@ -1,261 +0,0 @@
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: GreenBuildScheduleConfigMessage.proto
-
-import sys
-_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-from google.protobuf import descriptor_pb2
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name='GreenBuildScheduleConfigMessage.proto',
- package='android.test.lab',
- syntax='proto2',
- serialized_pb=_b('\n%GreenBuildScheduleConfigMessage.proto\x12\x10\x61ndroid.test.lab\"\xfa\x01\n\x1fGreenBuildScheduleConfigMessage\x12\x0c\n\x04name\x18\x01 \x01(\x0c\x12\x10\n\x08schedule\x18\x02 \x01(\x0c\x12\x10\n\x08priority\x18\x03 \x01(\x0c\x12\x12\n\ngsi_branch\x18\x0b \x01(\x0c\x12\x1a\n\x12gsi_pab_account_id\x18\x0c \x01(\x0c\x12\x13\n\x0btest_branch\x18\x15 \x01(\x0c\x12\x1b\n\x13test_pab_account_id\x18\x16 \x01(\x0c\x12\x43\n\x04test\x18\x1f \x03(\x0b\x32\x35.android.test.lab.GreenBuildTestScheduleConfigMessage\"\xd2\x01\n#GreenBuildTestScheduleConfigMessage\x12\x11\n\ttest_name\x18\x01 \x01(\x0c\x12\x19\n\x11test_build_target\x18\x0b \x01(\x0c\x12\x15\n\rdevice_branch\x18\x15 \x01(\x0c\x12\x1d\n\x15\x64\x65vice_pab_account_id\x18\x16 \x01(\x0c\x12G\n\x06\x64\x65vice\x18\x1f \x03(\x0b\x32\x37.android.test.lab.GreenBuildDeviceScheduleConfigMessage\"\xb4\x01\n%GreenBuildDeviceScheduleConfigMessage\x12\x0e\n\x06\x64\x65vice\x18\x01 \x01(\x0c\x12\x0e\n\x06shards\x18\x0b \x01(\x05\x12\x15\n\rdevice_branch\x18\x15 \x01(\x0c\x12\x1b\n\x13\x64\x65vice_build_target\x18\x16 \x01(\x0c\x12\x1d\n\x15\x64\x65vice_pab_account_id\x18\x17 \x01(\x0c\x12\x18\n\x10gsi_build_target\x18\x1f \x01(\x0c')
-)
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-
-
-
-_GREENBUILDSCHEDULECONFIGMESSAGE = _descriptor.Descriptor(
- name='GreenBuildScheduleConfigMessage',
- full_name='android.test.lab.GreenBuildScheduleConfigMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='name', full_name='android.test.lab.GreenBuildScheduleConfigMessage.name', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='schedule', full_name='android.test.lab.GreenBuildScheduleConfigMessage.schedule', index=1,
- number=2, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='priority', full_name='android.test.lab.GreenBuildScheduleConfigMessage.priority', index=2,
- number=3, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='gsi_branch', full_name='android.test.lab.GreenBuildScheduleConfigMessage.gsi_branch', index=3,
- number=11, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='gsi_pab_account_id', full_name='android.test.lab.GreenBuildScheduleConfigMessage.gsi_pab_account_id', index=4,
- number=12, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='test_branch', full_name='android.test.lab.GreenBuildScheduleConfigMessage.test_branch', index=5,
- number=21, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='test_pab_account_id', full_name='android.test.lab.GreenBuildScheduleConfigMessage.test_pab_account_id', index=6,
- number=22, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='test', full_name='android.test.lab.GreenBuildScheduleConfigMessage.test', index=7,
- number=31, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=60,
- serialized_end=310,
-)
-
-
-_GREENBUILDTESTSCHEDULECONFIGMESSAGE = _descriptor.Descriptor(
- name='GreenBuildTestScheduleConfigMessage',
- full_name='android.test.lab.GreenBuildTestScheduleConfigMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='test_name', full_name='android.test.lab.GreenBuildTestScheduleConfigMessage.test_name', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='test_build_target', full_name='android.test.lab.GreenBuildTestScheduleConfigMessage.test_build_target', index=1,
- number=11, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='device_branch', full_name='android.test.lab.GreenBuildTestScheduleConfigMessage.device_branch', index=2,
- number=21, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='device_pab_account_id', full_name='android.test.lab.GreenBuildTestScheduleConfigMessage.device_pab_account_id', index=3,
- number=22, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='device', full_name='android.test.lab.GreenBuildTestScheduleConfigMessage.device', index=4,
- number=31, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=313,
- serialized_end=523,
-)
-
-
-_GREENBUILDDEVICESCHEDULECONFIGMESSAGE = _descriptor.Descriptor(
- name='GreenBuildDeviceScheduleConfigMessage',
- full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='device', full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage.device', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='shards', full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage.shards', index=1,
- number=11, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='device_branch', full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage.device_branch', index=2,
- number=21, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='device_build_target', full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage.device_build_target', index=3,
- number=22, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='device_pab_account_id', full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage.device_pab_account_id', index=4,
- number=23, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='gsi_build_target', full_name='android.test.lab.GreenBuildDeviceScheduleConfigMessage.gsi_build_target', index=5,
- number=31, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=526,
- serialized_end=706,
-)
-
-_GREENBUILDSCHEDULECONFIGMESSAGE.fields_by_name['test'].message_type = _GREENBUILDTESTSCHEDULECONFIGMESSAGE
-_GREENBUILDTESTSCHEDULECONFIGMESSAGE.fields_by_name['device'].message_type = _GREENBUILDDEVICESCHEDULECONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['GreenBuildScheduleConfigMessage'] = _GREENBUILDSCHEDULECONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['GreenBuildTestScheduleConfigMessage'] = _GREENBUILDTESTSCHEDULECONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['GreenBuildDeviceScheduleConfigMessage'] = _GREENBUILDDEVICESCHEDULECONFIGMESSAGE
-
-GreenBuildScheduleConfigMessage = _reflection.GeneratedProtocolMessageType('GreenBuildScheduleConfigMessage', (_message.Message,), dict(
- DESCRIPTOR = _GREENBUILDSCHEDULECONFIGMESSAGE,
- __module__ = 'GreenBuildScheduleConfigMessage_pb2'
- # @@protoc_insertion_point(class_scope:android.test.lab.GreenBuildScheduleConfigMessage)
- ))
-_sym_db.RegisterMessage(GreenBuildScheduleConfigMessage)
-
-GreenBuildTestScheduleConfigMessage = _reflection.GeneratedProtocolMessageType('GreenBuildTestScheduleConfigMessage', (_message.Message,), dict(
- DESCRIPTOR = _GREENBUILDTESTSCHEDULECONFIGMESSAGE,
- __module__ = 'GreenBuildScheduleConfigMessage_pb2'
- # @@protoc_insertion_point(class_scope:android.test.lab.GreenBuildTestScheduleConfigMessage)
- ))
-_sym_db.RegisterMessage(GreenBuildTestScheduleConfigMessage)
-
-GreenBuildDeviceScheduleConfigMessage = _reflection.GeneratedProtocolMessageType('GreenBuildDeviceScheduleConfigMessage', (_message.Message,), dict(
- DESCRIPTOR = _GREENBUILDDEVICESCHEDULECONFIGMESSAGE,
- __module__ = 'GreenBuildScheduleConfigMessage_pb2'
- # @@protoc_insertion_point(class_scope:android.test.lab.GreenBuildDeviceScheduleConfigMessage)
- ))
-_sym_db.RegisterMessage(GreenBuildDeviceScheduleConfigMessage)
-
-
-# @@protoc_insertion_point(module_scope)
diff --git a/proto/TestLabConfigMessage.proto b/proto/TestLabConfigMessage.proto
deleted file mode 100644
index 2324ead..0000000
--- a/proto/TestLabConfigMessage.proto
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto2";
-
-package android.test.lab;
-
-// To specify the whole test execution schedule of a manifest branch.
-message LabConfigMessage {
- // Lab name where format is labtype-location-instance (e.g., vtslab-mtv32-main).
- optional bytes name = 1;
- optional bytes owner = 2;
- repeated bytes admin = 3;
-
- // For the IP address.
- repeated HostConfigMessage host = 11;
-}
-
-// To specify the basic information about a host computer.
-message HostConfigMessage {
- optional bytes hostname = 1;
- optional bytes ip = 2;
-
- // host management scripts
- optional bytes script = 3;
- optional bytes setup_script = 4;
-
- // list of equipment installed on this host.
- repeated bytes host_equipment = 5;
-
- repeated DeviceConfigMessage device = 11;
-}
-
-// To specify information about a DUT (Device Under Test).
-message DeviceConfigMessage {
- // device serial number (retrieved by fastboot or adb).
- optional bytes serial = 1;
-
- // optional - device index for a host starting from 0 to 13 (max).
- optional int32 index = 2;
-
- // device product type (e.g., taimen or walleye).
- optional bytes product = 11;
-
- // list of equipment installed on this device.
- repeated bytes device_equipment = 21;
-}
-
diff --git a/proto/TestLabConfigMessage_pb2.py b/proto/TestLabConfigMessage_pb2.py
deleted file mode 100644
index eb1799c..0000000
--- a/proto/TestLabConfigMessage_pb2.py
+++ /dev/null
@@ -1,226 +0,0 @@
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: TestLabConfigMessage.proto
-
-import sys
-_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-from google.protobuf import descriptor_pb2
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name='TestLabConfigMessage.proto',
- package='android.test.lab',
- syntax='proto2',
- serialized_pb=_b('\n\x1aTestLabConfigMessage.proto\x12\x10\x61ndroid.test.lab\"q\n\x10LabConfigMessage\x12\x0c\n\x04name\x18\x01 \x01(\x0c\x12\r\n\x05owner\x18\x02 \x01(\x0c\x12\r\n\x05\x61\x64min\x18\x03 \x03(\x0c\x12\x31\n\x04host\x18\x0b \x03(\x0b\x32#.android.test.lab.HostConfigMessage\"\xa6\x01\n\x11HostConfigMessage\x12\x10\n\x08hostname\x18\x01 \x01(\x0c\x12\n\n\x02ip\x18\x02 \x01(\x0c\x12\x0e\n\x06script\x18\x03 \x01(\x0c\x12\x14\n\x0csetup_script\x18\x04 \x01(\x0c\x12\x16\n\x0ehost_equipment\x18\x05 \x03(\x0c\x12\x35\n\x06\x64\x65vice\x18\x0b \x03(\x0b\x32%.android.test.lab.DeviceConfigMessage\"_\n\x13\x44\x65viceConfigMessage\x12\x0e\n\x06serial\x18\x01 \x01(\x0c\x12\r\n\x05index\x18\x02 \x01(\x05\x12\x0f\n\x07product\x18\x0b \x01(\x0c\x12\x18\n\x10\x64\x65vice_equipment\x18\x15 \x03(\x0c')
-)
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-
-
-
-_LABCONFIGMESSAGE = _descriptor.Descriptor(
- name='LabConfigMessage',
- full_name='android.test.lab.LabConfigMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='name', full_name='android.test.lab.LabConfigMessage.name', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='owner', full_name='android.test.lab.LabConfigMessage.owner', index=1,
- number=2, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='admin', full_name='android.test.lab.LabConfigMessage.admin', index=2,
- number=3, type=12, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='host', full_name='android.test.lab.LabConfigMessage.host', index=3,
- number=11, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=48,
- serialized_end=161,
-)
-
-
-_HOSTCONFIGMESSAGE = _descriptor.Descriptor(
- name='HostConfigMessage',
- full_name='android.test.lab.HostConfigMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='hostname', full_name='android.test.lab.HostConfigMessage.hostname', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='ip', full_name='android.test.lab.HostConfigMessage.ip', index=1,
- number=2, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='script', full_name='android.test.lab.HostConfigMessage.script', index=2,
- number=3, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='setup_script', full_name='android.test.lab.HostConfigMessage.setup_script', index=3,
- number=4, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='host_equipment', full_name='android.test.lab.HostConfigMessage.host_equipment', index=4,
- number=5, type=12, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='device', full_name='android.test.lab.HostConfigMessage.device', index=5,
- number=11, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=164,
- serialized_end=330,
-)
-
-
-_DEVICECONFIGMESSAGE = _descriptor.Descriptor(
- name='DeviceConfigMessage',
- full_name='android.test.lab.DeviceConfigMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='serial', full_name='android.test.lab.DeviceConfigMessage.serial', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='index', full_name='android.test.lab.DeviceConfigMessage.index', index=1,
- number=2, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='product', full_name='android.test.lab.DeviceConfigMessage.product', index=2,
- number=11, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='device_equipment', full_name='android.test.lab.DeviceConfigMessage.device_equipment', index=3,
- number=21, type=12, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=332,
- serialized_end=427,
-)
-
-_LABCONFIGMESSAGE.fields_by_name['host'].message_type = _HOSTCONFIGMESSAGE
-_HOSTCONFIGMESSAGE.fields_by_name['device'].message_type = _DEVICECONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['LabConfigMessage'] = _LABCONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['HostConfigMessage'] = _HOSTCONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['DeviceConfigMessage'] = _DEVICECONFIGMESSAGE
-
-LabConfigMessage = _reflection.GeneratedProtocolMessageType('LabConfigMessage', (_message.Message,), dict(
- DESCRIPTOR = _LABCONFIGMESSAGE,
- __module__ = 'TestLabConfigMessage_pb2'
- # @@protoc_insertion_point(class_scope:android.test.lab.LabConfigMessage)
- ))
-_sym_db.RegisterMessage(LabConfigMessage)
-
-HostConfigMessage = _reflection.GeneratedProtocolMessageType('HostConfigMessage', (_message.Message,), dict(
- DESCRIPTOR = _HOSTCONFIGMESSAGE,
- __module__ = 'TestLabConfigMessage_pb2'
- # @@protoc_insertion_point(class_scope:android.test.lab.HostConfigMessage)
- ))
-_sym_db.RegisterMessage(HostConfigMessage)
-
-DeviceConfigMessage = _reflection.GeneratedProtocolMessageType('DeviceConfigMessage', (_message.Message,), dict(
- DESCRIPTOR = _DEVICECONFIGMESSAGE,
- __module__ = 'TestLabConfigMessage_pb2'
- # @@protoc_insertion_point(class_scope:android.test.lab.DeviceConfigMessage)
- ))
-_sym_db.RegisterMessage(DeviceConfigMessage)
-
-
-# @@protoc_insertion_point(module_scope)
diff --git a/proto/TestScheduleConfigMessage.proto b/proto/TestScheduleConfigMessage.proto
deleted file mode 100644
index c2f7991..0000000
--- a/proto/TestScheduleConfigMessage.proto
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto2";
-
-package android.test.lab;
-
-// Type of a command.
-enum BuildStorageType {
- UNKNOWN_BUILD_STORAGE_TYPE = 0;
- // For Partner Android Build (PAB)
- BUILD_STORAGE_TYPE_PAB = 1;
- // For a Google Cloud Storage (GCS) bucket
- BUILD_STORAGE_TYPE_GCS = 2;
-}
-
-// To specify the whole test execution schedule of a manifest branch.
-message ScheduleConfigMessage {
- // Manifest branch name.
- optional bytes manifest_branch = 1;
-
- // PAB account ID.
- optional bytes pab_account_id = 2;
-
- // Device image storage type (e.g., PAB or GCS)
- optional BuildStorageType build_storage_type = 3 [default = BUILD_STORAGE_TYPE_PAB];
-
- // For the IP address.
- repeated BuildScheduleConfigMessage build_target = 11;
-}
-
-message BuildScheduleConfigMessage {
- // build target name (e.g., aosp_taimen-userdebug)
- optional bytes name = 1;
-
- // whether to use signed build.
- optional bool require_signed_device_build = 2;
-
- // whether the build target has bootloader.img
- optional bool has_bootloader_img = 3 [default = true];
-
- // whether the build target has radio.img
- optional bool has_radio_img = 4 [default = true];
-
- repeated TestScheduleConfigMessage test_schedule = 11;
-}
-
-message TestScheduleConfigMessage {
- // Test name (e.g., test_group/test_plan)
- optional bytes test_name = 1;
-
- // Scheduling period in minutes
- optional int32 period = 2;
-
- // Priority such as high, low, or medium
- optional bytes priority = 3;
-
- // such as <lab>/<device type>
- repeated bytes device = 4;
-
- // number of shards (-1 for auto selection?)
- optional int32 shards = 5;
-
- // required host-side equipment.
- repeated bytes required_host_equipment = 6;
-
- // required device-side equipment such as a SIM card.
- repeated bytes required_device_equipment = 7;
-
- optional bytes param = 11;
-
- // GSI storage type (e.g., PAB or GCS)
- optional BuildStorageType gsi_storage_type = 24 [default = BUILD_STORAGE_TYPE_PAB];
-
- // if GSI (General System Image) is used, GSI manifest branch name.
- optional bytes gsi_branch = 21;
-
- // if GSI (General System Image) is used, GSI build target name.
- optional bytes gsi_build_target = 22;
-
- // if GSI (General System Image) is used, GSI PAB account ID.
- optional bytes gsi_pab_account_id = 23;
-
- // if GSI (General System Image) is used, the version of a vendor.img
- // to use GSI with (e.g., 8.1.0).
- optional bytes gsi_vendor_version = 25;
-
- // Test package's storage type (e.g., PAB or GCS)
- optional BuildStorageType test_storage_type = 34 [default = BUILD_STORAGE_TYPE_PAB];
-
- // Test package's manifest branch name.
- optional bytes test_branch = 31;
-
- // Test package's build target name.
- optional bytes test_build_target = 32;
-
- // PAB account ID for test package.
- optional bytes test_pab_account_id = 33;
-
- // number of retry count.
- optional int32 retry_count = 41;
-
- // whether to disable this schedule.
- optional bool disable = 51 [default = false];
-
- // Base GCS url for the repack command.
- optional bytes image_package_repo_base = 61;
-
- // the GCS url where test results are uploaded
- repeated bytes report_bucket = 71;
-
- // the ID of the spreadsheet where test results are uploaded
- repeated bytes report_spreadsheet_id = 72;
-
- // the GCS url where the latest test result is uploaded
- repeated bytes report_persistent_url = 73;
-
- // the GCS url where the reference result is.
- repeated bytes report_reference_url = 74;
-}
diff --git a/proto/TestScheduleConfigMessage_pb2.py b/proto/TestScheduleConfigMessage_pb2.py
deleted file mode 100644
index 46dafac..0000000
--- a/proto/TestScheduleConfigMessage_pb2.py
+++ /dev/null
@@ -1,394 +0,0 @@
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: vti/test_serving/proto/TestScheduleConfigMessage.proto
-
-import sys
-_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
-from google.protobuf.internal import enum_type_wrapper
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-from google.protobuf import descriptor_pb2
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name='vti/test_serving/proto/TestScheduleConfigMessage.proto',
- package='android.test.lab',
- syntax='proto2',
- serialized_pb=_b('\n6vti/test_serving/proto/TestScheduleConfigMessage.proto\x12\x10\x61ndroid.test.lab\"\xe4\x01\n\x15ScheduleConfigMessage\x12\x17\n\x0fmanifest_branch\x18\x01 \x01(\x0c\x12\x16\n\x0epab_account_id\x18\x02 \x01(\x0c\x12V\n\x12\x62uild_storage_type\x18\x03 \x01(\x0e\x32\".android.test.lab.BuildStorageType:\x16\x42UILD_STORAGE_TYPE_PAB\x12\x42\n\x0c\x62uild_target\x18\x0b \x03(\x0b\x32,.android.test.lab.BuildScheduleConfigMessage\"\xd2\x01\n\x1a\x42uildScheduleConfigMessage\x12\x0c\n\x04name\x18\x01 \x01(\x0c\x12#\n\x1brequire_signed_device_build\x18\x02 \x01(\x08\x12 \n\x12has_bootloader_img\x18\x03 \x01(\x08:\x04true\x12\x1b\n\rhas_radio_img\x18\x04 \x01(\x08:\x04true\x12\x42\n\rtest_schedule\x18\x0b \x03(\x0b\x32+.android.test.lab.TestScheduleConfigMessage\"\xe4\x05\n\x19TestScheduleConfigMessage\x12\x11\n\ttest_name\x18\x01 \x01(\x0c\x12\x0e\n\x06period\x18\x02 \x01(\x05\x12\x10\n\x08priority\x18\x03 \x01(\x0c\x12\x0e\n\x06\x64\x65vice\x18\x04 \x03(\x0c\x12\x0e\n\x06shards\x18\x05 \x01(\x05\x12\x1f\n\x17required_host_equipment\x18\x06 \x03(\x0c\x12!\n\x19required_device_equipment\x18\x07 \x03(\x0c\x12\r\n\x05param\x18\x0b \x01(\x0c\x12T\n\x10gsi_storage_type\x18\x18 \x01(\x0e\x32\".android.test.lab.BuildStorageType:\x16\x42UILD_STORAGE_TYPE_PAB\x12\x12\n\ngsi_branch\x18\x15 \x01(\x0c\x12\x18\n\x10gsi_build_target\x18\x16 \x01(\x0c\x12\x1a\n\x12gsi_pab_account_id\x18\x17 \x01(\x0c\x12\x1a\n\x12gsi_vendor_version\x18\x19 \x01(\x0c\x12U\n\x11test_storage_type\x18\" \x01(\x0e\x32\".android.test.lab.BuildStorageType:\x16\x42UILD_STORAGE_TYPE_PAB\x12\x13\n\x0btest_branch\x18\x1f \x01(\x0c\x12\x19\n\x11test_build_target\x18 \x01(\x0c\x12\x1b\n\x13test_pab_account_id\x18! \x01(\x0c\x12\x13\n\x0bretry_count\x18) \x01(\x05\x12\x16\n\x07\x64isable\x18\x33 \x01(\x08:\x05\x66\x61lse\x12\x1f\n\x17image_package_repo_base\x18= \x01(\x0c\x12\x15\n\rreport_bucket\x18G \x03(\x0c\x12\x1d\n\x15report_spreadsheet_id\x18H \x03(\x0c\x12\x1d\n\x15report_persistent_url\x18I \x03(\x0c\x12\x1c\n\x14report_reference_url\x18J \x03(\x0c*j\n\x10\x42uildStorageType\x12\x1e\n\x1aUNKNOWN_BUILD_STORAGE_TYPE\x10\x00\x12\x1a\n\x16\x42UILD_STORAGE_TYPE_PAB\x10\x01\x12\x1a\n\x16\x42UILD_STORAGE_TYPE_GCS\x10\x02')
-)
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-_BUILDSTORAGETYPE = _descriptor.EnumDescriptor(
- name='BuildStorageType',
- full_name='android.test.lab.BuildStorageType',
- filename=None,
- file=DESCRIPTOR,
- values=[
- _descriptor.EnumValueDescriptor(
- name='UNKNOWN_BUILD_STORAGE_TYPE', index=0, number=0,
- options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='BUILD_STORAGE_TYPE_PAB', index=1, number=1,
- options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='BUILD_STORAGE_TYPE_GCS', index=2, number=2,
- options=None,
- type=None),
- ],
- containing_type=None,
- options=None,
- serialized_start=1263,
- serialized_end=1369,
-)
-_sym_db.RegisterEnumDescriptor(_BUILDSTORAGETYPE)
-
-BuildStorageType = enum_type_wrapper.EnumTypeWrapper(_BUILDSTORAGETYPE)
-UNKNOWN_BUILD_STORAGE_TYPE = 0
-BUILD_STORAGE_TYPE_PAB = 1
-BUILD_STORAGE_TYPE_GCS = 2
-
-
-
-_SCHEDULECONFIGMESSAGE = _descriptor.Descriptor(
- name='ScheduleConfigMessage',
- full_name='android.test.lab.ScheduleConfigMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='manifest_branch', full_name='android.test.lab.ScheduleConfigMessage.manifest_branch', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='pab_account_id', full_name='android.test.lab.ScheduleConfigMessage.pab_account_id', index=1,
- number=2, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='build_storage_type', full_name='android.test.lab.ScheduleConfigMessage.build_storage_type', index=2,
- number=3, type=14, cpp_type=8, label=1,
- has_default_value=True, default_value=1,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='build_target', full_name='android.test.lab.ScheduleConfigMessage.build_target', index=3,
- number=11, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=77,
- serialized_end=305,
-)
-
-
-_BUILDSCHEDULECONFIGMESSAGE = _descriptor.Descriptor(
- name='BuildScheduleConfigMessage',
- full_name='android.test.lab.BuildScheduleConfigMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='name', full_name='android.test.lab.BuildScheduleConfigMessage.name', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='require_signed_device_build', full_name='android.test.lab.BuildScheduleConfigMessage.require_signed_device_build', index=1,
- number=2, type=8, cpp_type=7, label=1,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='has_bootloader_img', full_name='android.test.lab.BuildScheduleConfigMessage.has_bootloader_img', index=2,
- number=3, type=8, cpp_type=7, label=1,
- has_default_value=True, default_value=True,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='has_radio_img', full_name='android.test.lab.BuildScheduleConfigMessage.has_radio_img', index=3,
- number=4, type=8, cpp_type=7, label=1,
- has_default_value=True, default_value=True,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='test_schedule', full_name='android.test.lab.BuildScheduleConfigMessage.test_schedule', index=4,
- number=11, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=308,
- serialized_end=518,
-)
-
-
-_TESTSCHEDULECONFIGMESSAGE = _descriptor.Descriptor(
- name='TestScheduleConfigMessage',
- full_name='android.test.lab.TestScheduleConfigMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='test_name', full_name='android.test.lab.TestScheduleConfigMessage.test_name', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='period', full_name='android.test.lab.TestScheduleConfigMessage.period', index=1,
- number=2, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='priority', full_name='android.test.lab.TestScheduleConfigMessage.priority', index=2,
- number=3, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='device', full_name='android.test.lab.TestScheduleConfigMessage.device', index=3,
- number=4, type=12, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='shards', full_name='android.test.lab.TestScheduleConfigMessage.shards', index=4,
- number=5, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='required_host_equipment', full_name='android.test.lab.TestScheduleConfigMessage.required_host_equipment', index=5,
- number=6, type=12, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='required_device_equipment', full_name='android.test.lab.TestScheduleConfigMessage.required_device_equipment', index=6,
- number=7, type=12, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='param', full_name='android.test.lab.TestScheduleConfigMessage.param', index=7,
- number=11, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='gsi_storage_type', full_name='android.test.lab.TestScheduleConfigMessage.gsi_storage_type', index=8,
- number=24, type=14, cpp_type=8, label=1,
- has_default_value=True, default_value=1,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='gsi_branch', full_name='android.test.lab.TestScheduleConfigMessage.gsi_branch', index=9,
- number=21, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='gsi_build_target', full_name='android.test.lab.TestScheduleConfigMessage.gsi_build_target', index=10,
- number=22, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='gsi_pab_account_id', full_name='android.test.lab.TestScheduleConfigMessage.gsi_pab_account_id', index=11,
- number=23, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='gsi_vendor_version', full_name='android.test.lab.TestScheduleConfigMessage.gsi_vendor_version', index=12,
- number=25, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='test_storage_type', full_name='android.test.lab.TestScheduleConfigMessage.test_storage_type', index=13,
- number=34, type=14, cpp_type=8, label=1,
- has_default_value=True, default_value=1,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='test_branch', full_name='android.test.lab.TestScheduleConfigMessage.test_branch', index=14,
- number=31, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='test_build_target', full_name='android.test.lab.TestScheduleConfigMessage.test_build_target', index=15,
- number=32, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='test_pab_account_id', full_name='android.test.lab.TestScheduleConfigMessage.test_pab_account_id', index=16,
- number=33, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='retry_count', full_name='android.test.lab.TestScheduleConfigMessage.retry_count', index=17,
- number=41, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='disable', full_name='android.test.lab.TestScheduleConfigMessage.disable', index=18,
- number=51, type=8, cpp_type=7, label=1,
- has_default_value=True, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='image_package_repo_base', full_name='android.test.lab.TestScheduleConfigMessage.image_package_repo_base', index=19,
- number=61, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='report_bucket', full_name='android.test.lab.TestScheduleConfigMessage.report_bucket', index=20,
- number=71, type=12, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='report_spreadsheet_id', full_name='android.test.lab.TestScheduleConfigMessage.report_spreadsheet_id', index=21,
- number=72, type=12, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='report_persistent_url', full_name='android.test.lab.TestScheduleConfigMessage.report_persistent_url', index=22,
- number=73, type=12, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='report_reference_url', full_name='android.test.lab.TestScheduleConfigMessage.report_reference_url', index=23,
- number=74, type=12, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=521,
- serialized_end=1261,
-)
-
-_SCHEDULECONFIGMESSAGE.fields_by_name['build_storage_type'].enum_type = _BUILDSTORAGETYPE
-_SCHEDULECONFIGMESSAGE.fields_by_name['build_target'].message_type = _BUILDSCHEDULECONFIGMESSAGE
-_BUILDSCHEDULECONFIGMESSAGE.fields_by_name['test_schedule'].message_type = _TESTSCHEDULECONFIGMESSAGE
-_TESTSCHEDULECONFIGMESSAGE.fields_by_name['gsi_storage_type'].enum_type = _BUILDSTORAGETYPE
-_TESTSCHEDULECONFIGMESSAGE.fields_by_name['test_storage_type'].enum_type = _BUILDSTORAGETYPE
-DESCRIPTOR.message_types_by_name['ScheduleConfigMessage'] = _SCHEDULECONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['BuildScheduleConfigMessage'] = _BUILDSCHEDULECONFIGMESSAGE
-DESCRIPTOR.message_types_by_name['TestScheduleConfigMessage'] = _TESTSCHEDULECONFIGMESSAGE
-DESCRIPTOR.enum_types_by_name['BuildStorageType'] = _BUILDSTORAGETYPE
-
-ScheduleConfigMessage = _reflection.GeneratedProtocolMessageType('ScheduleConfigMessage', (_message.Message,), dict(
- DESCRIPTOR = _SCHEDULECONFIGMESSAGE,
- __module__ = 'vti.test_serving.proto.TestScheduleConfigMessage_pb2'
- # @@protoc_insertion_point(class_scope:android.test.lab.ScheduleConfigMessage)
- ))
-_sym_db.RegisterMessage(ScheduleConfigMessage)
-
-BuildScheduleConfigMessage = _reflection.GeneratedProtocolMessageType('BuildScheduleConfigMessage', (_message.Message,), dict(
- DESCRIPTOR = _BUILDSCHEDULECONFIGMESSAGE,
- __module__ = 'vti.test_serving.proto.TestScheduleConfigMessage_pb2'
- # @@protoc_insertion_point(class_scope:android.test.lab.BuildScheduleConfigMessage)
- ))
-_sym_db.RegisterMessage(BuildScheduleConfigMessage)
-
-TestScheduleConfigMessage = _reflection.GeneratedProtocolMessageType('TestScheduleConfigMessage', (_message.Message,), dict(
- DESCRIPTOR = _TESTSCHEDULECONFIGMESSAGE,
- __module__ = 'vti.test_serving.proto.TestScheduleConfigMessage_pb2'
- # @@protoc_insertion_point(class_scope:android.test.lab.TestScheduleConfigMessage)
- ))
-_sym_db.RegisterMessage(TestScheduleConfigMessage)
-
-
-# @@protoc_insertion_point(module_scope)
diff --git a/proto/__init__.py b/proto/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/proto/__init__.py
+++ /dev/null
diff --git a/script/build-python.sh b/script/build-python.sh
deleted file mode 100755
index f8d2fb0..0000000
--- a/script/build-python.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Modifies any import statements (to remove subdir path)
-pushd ${ANDROID_BUILD_TOP}/test
-
-protoc -I=. --python_out=. ./vti/test_serving/proto/TestLabConfigMessage.proto
-protoc -I=. --python_out=. ./vti/test_serving/proto/TestScheduleConfigMessage.proto
-protoc -I=. --python_out=. ./vti/test_serving/proto/GreenBuildScheduleConfigMessage.proto
-
-# Compiles all the python source codes.
-python -m compileall .
-
-popd
diff --git a/script/pack-gae.sh b/script/pack-gae.sh
deleted file mode 100755
index 9917aef..0000000
--- a/script/pack-gae.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [ -d "$ANDROID_BUILD_TOP" ]; then
- TEST_SERVING_DIR="$ANDROID_BUILD_TOP/test/vti/test_serving"
-else
- CURRENT_DIR_NAME="${PWD##*/}"
- if [ "${CURRENT_DIR_NAME}" = "test_serving" ]; then
- TEST_SERVING_DIR="${PWD}"
- elif [ "${CURRENT_DIR_NAME}" = "script" ]; then
- TEST_SERVING_DIR="${PWD}/.."
- else
- echo "Missing ANDROID_BUILD_TOP env variable. Run 'lunch' first."
- exit 1
- fi
-fi
-
-if [ ! -d "${TEST_SERVING_DIR}/gae" ]; then
- echo "Please run this script in 'test_serving' directory."
- exit 1
-fi
-
-pushd $TEST_SERVING_DIR/gae
-echo "Removing unnecessary files in ${TEST_SERVING_DIR}/gae directory..."
-git clean -f
-
-echo "Updating python libraries..."
-rm -rf lib/
-./script/install-pip.sh
-popd
-
-pushd $TEST_SERVING_DIR/
-zip vtslab-scheduler-$(git log -s -n 1 --format="%cd" --date=format:"%Y%m%d_%H%M%S")-$(git rev-parse --short HEAD).zip -r gae -x *.pyc "*/\.*" *.DS_Store* gae/frontend/node_modules**\*
-popd
diff --git a/script/run-unittest.sh b/script/run-unittest.sh
deleted file mode 100755
index 6ce6949..0000000
--- a/script/run-unittest.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [ -z "$ANDROID_BUILD_TOP" ]; then
- echo "Missing ANDROID_BUILD_TOP env variable. Run 'lunch' first."
- exit 1
-fi
-
-# Runs all unit tests under test/vti/test_serving/gae using an e2e_test framework.
-pushd $ANDROID_BUILD_TOP/test/vti/test_serving/gae
-python testing/e2e_test.py
-popd
-