chore: remove legacy code

This commit is contained in:
Sérgio Ramos 2017-06-06 12:00:37 +01:00
parent 87b3d8e9f5
commit ea27c18202
1386 changed files with 0 additions and 976293 deletions

View File

@ -1 +0,0 @@
*.sketch filter=lfs diff=lfs merge=lfs -text

156
legacy/.gitignore vendored
View File

@ -1,156 +0,0 @@
### Bower ###
bower_components
.bower-cache
.bower-registry
.bower-tmp
### Git ###
*.orig
### macOS ###
*.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Node ###
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
### SublimeText ###
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# workspace files are user-specific
*.sublime-workspace
# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project
# sftp configuration file
sftp-config.json
# Package control specific files
Package Control.last-run
Package Control.ca-list
Package Control.ca-bundle
Package Control.system-ca-bundle
Package Control.cache/
Package Control.ca-certs/
bh_unicode_properties.cache
# Sublime-github package stores a github token in this file
# https://packagecontrol.io/packages/sublime-github
GitHub.sublime-settings
### Vim ###
# swap
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags
### Windows ###
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
### Application Specific ###
.env
# PostCSS
*.postcss.js
/cloudapi-graphql/credentials.json
/docker-graphql/config.json
tap-xunit
/ui/dist

View File

@ -1,33 +0,0 @@
## Development Workflow
### Small Feature Development
Contributors who have write access to the repository will practise continuous
delivery (CD as known from now on in this document).
We will define CD in this document as a method of developing a feature per commit
with an encapsulating test that proves that the functionality is working, the
contributor will test their code locally and if all is passing will push to *master*.
For contributors that do not have write access, follow the same conventions but
open a Pull Request instead.
### Large changesets
When larger changes need to be made, or the work that is carried out spans multiple
components / services of the application at the same time a single commit will
not suffice.
In this scenario, the contributor should open a pull request instead.
## Commit messages
Follow [Git blessed](http://chris.beams.io/posts/git-commit/)
1. Separate subject from body with a blank line
2. Limit the subject line to 50 characters
3. Capitalize the subject line
4. Do not end the subject line with a period
5. Use the imperative mood in the subject line
6. Wrap the body at 72 characters
7. Use the body to explain what and why vs. how

View File

@ -1,362 +0,0 @@
Mozilla Public License, version 2.0
1. Definitions
1.1. "Contributor"
means each individual or legal entity that creates, contributes to the
creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used by a
Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached the
notice in Exhibit A, the Executable Form of such Source Code Form, and
Modifications of such Source Code Form, in each case including portions
thereof.
1.5. "Incompatible With Secondary Licenses"
means
a. that the initial Contributor has attached the notice described in
Exhibit B to the Covered Software; or
b. that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the terms of
a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in a
separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible, whether
at the time of the initial grant or subsequently, any and all of the
rights conveyed by this License.
1.10. "Modifications"
means any of the following:
a. any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered Software; or
b. any new file in Source Code Form that contains any Covered Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the License,
by the making, using, selling, offering for sale, having made, import,
or transfer of either its Contributions or its Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU Lesser
General Public License, Version 2.1, the GNU Affero General Public
License, Version 3.0, or any later versions of those licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that controls, is
controlled by, or is under common control with You. For purposes of this
definition, "control" means (a) the power, direct or indirect, to cause
the direction or management of such entity, whether by contract or
otherwise, or (b) ownership of more than fifty percent (50%) of the
outstanding shares or beneficial ownership of such entity.
2. License Grants and Conditions
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
a. under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
b. under Patent Claims of such Contributor to make, use, sell, offer for
sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
a. for any code that a Contributor has removed from Covered Software; or
b. for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
c. under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights to
grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
Section 2.1.
3. Responsibilities
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
a. such Covered Software must also be made available in Source Code Form,
as described in Section 3.1, and You must inform recipients of the
Executable Form how they can obtain a copy of such Source Code Form by
reasonable means in a timely manner, at a charge no more than the cost
of distribution to the recipient; and
b. You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter the
recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty, or
limitations of liability) contained within the Source Code Form of the
Covered Software, except that You may alter any license notices to the
extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
If it is impossible for You to comply with any of the terms of this License
with respect to some or all of the Covered Software due to statute,
judicial order, or regulation then You must: (a) comply with the terms of
this License to the maximum extent possible; and (b) describe the
limitations and the code they affect. Such description must be placed in a
text file included with all distributions of the Covered Software under
this License. Except to the extent prohibited by statute or regulation,
such description must be sufficiently detailed for a recipient of ordinary
skill to be able to understand it.
5. Termination
5.1. The rights granted under this License will terminate automatically if You
fail to comply with any of its terms. However, if You become compliant,
then the rights granted under this License from a particular Contributor
are reinstated (a) provisionally, unless and until such Contributor
explicitly and finally terminates Your grants, and (b) on an ongoing
basis, if such Contributor fails to notify You of the non-compliance by
some reasonable means prior to 60 days after You have come back into
compliance. Moreover, Your grants from a particular Contributor are
reinstated on an ongoing basis if such Contributor notifies You of the
non-compliance by some reasonable means, this is the first time You have
received notice of non-compliance with this License from such
Contributor, and You become compliant prior to 30 days after Your receipt
of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
license agreements (excluding distributors and resellers) which have been
validly granted by You or Your distributors under this License prior to
termination shall survive termination.
6. Disclaimer of Warranty
Covered Software is provided under this License on an "as is" basis,
without warranty of any kind, either expressed, implied, or statutory,
including, without limitation, warranties that the Covered Software is free
of defects, merchantable, fit for a particular purpose or non-infringing.
The entire risk as to the quality and performance of the Covered Software
is with You. Should any Covered Software prove defective in any respect,
You (not any Contributor) assume the cost of any necessary servicing,
repair, or correction. This disclaimer of warranty constitutes an essential
part of this License. No use of any Covered Software is authorized under
this License except under this disclaimer.
7. Limitation of Liability
Under no circumstances and under no legal theory, whether tort (including
negligence), contract, or otherwise, shall any Contributor, or anyone who
distributes Covered Software as permitted above, be liable to You for any
direct, indirect, special, incidental, or consequential damages of any
character including, without limitation, damages for lost profits, loss of
goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses, even if such party shall have been
informed of the possibility of such damages. This limitation of liability
shall not apply to liability for death or personal injury resulting from
such party's negligence to the extent applicable law prohibits such
limitation. Some jurisdictions do not allow the exclusion or limitation of
incidental or consequential damages, so this exclusion and limitation may
not apply to You.
8. Litigation
Any litigation relating to this License may be brought only in the courts
of a jurisdiction where the defendant maintains its principal place of
business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions. Nothing
in this Section shall prevent a party's ability to bring cross-claims or
counter-claims.
9. Miscellaneous
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides that
the language of a contract shall be construed against the drafter shall not
be used to construe this License against a Contributor.
10. Versions of the License
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses If You choose to distribute Source Code Form that is
Incompatible With Secondary Licenses under the terms of this version of
the License, the notice described in Exhibit B of this License must be
attached.
Exhibit A - Source Code Form License Notice
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular file,
then You may include the notice in a location (such as a LICENSE file in a
relevant directory) where a recipient would be likely to look for such a
notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
This Source Code Form is "Incompatible
With Secondary Licenses", as defined by
the Mozilla Public License, v. 2.0.

View File

@ -1,57 +0,0 @@
.PHONY: check
check:
@yarn install --prefer-offline
-@./bin/setup
.PHONE: licence
licence:
./node_modules/.bin/license-to-fail ./licence.js
make licence-check
SUBDIRS := $(dir $(wildcard */Makefile))
TARGETS := install clean test test-ci lint lint-ci licence-check# whatever else, but must not contain '/'
# foo/.all bar/.all foo/.clean bar/.clean
SUBDIRS_TARGETS := \
$(foreach t,$(TARGETS),$(addsuffix $t,$(SUBDIRS)))
.PHONY: $(TARGETS) $(SUBDIRS_TARGETS)
# static pattern rule, expands into:
# all clean: %: foo/.% bar/.%
$(TARGETS): %: $(addsuffix %,$(SUBDIRS))
@echo 'Done "$*" target'
# here, for foo/.all:
# $(@D) is foo
# $(@F) is .all, with leading period
# $(@F:.%=%) is just all
$(SUBDIRS_TARGETS):
$(MAKE) --no-print-directory -C $(@D) $(@F:.%=%)
DIFF := $(lastword $(subst /, ,${CIRCLE_COMPARE_URL}))
CHANGED_FILES := $(subst /, , $(dir $(shell git diff --name-only $(DIFF))))
CHANGES := $(patsubst %, %/, $(sort $(filter $(subst /, ,$(SUBDIRS)), $(CHANGED_FILES))))
.PHONY: diff
diff:
echo $(CHANGES)
BUILDS := build push
# foo/.all bar/.all foo/.clean bar/.clean
BUILDS_TARGETS := \
$(foreach t,$(BUILDS),$(addsuffix $t,$(CHANGES)))
.PHONY: $(BUILDS) $(BUILDS_TARGETS)
# static pattern rule, expands into:
# all clean: %: foo/.% bar/.%
$(BUILDS): %: $(addsuffix %,$(CHANGES))
@echo 'Done "$*" target'
# here, for foo/.all:
# $(@D) is foo
# $(@F) is .all, with leading period
# $(@F:.%=%) is just all
$(BUILDS_TARGETS):
$(MAKE) --no-print-directory -C $(@D) $(@F:.%=%)

View File

@ -1,120 +0,0 @@
[![CircleCI](https://circleci.com/gh/yldio/joyent-portal.svg?style=shield&circle-token=0bbeaaafc4868c707ca0ed0568f5193a04daddb4)](https://circleci.com/gh/yldio/joyent-portal)
[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0)
# Prototype Triton Portal
This is a prototype project intended to explore some ideas that might contribute to new capabilities and a new user experience for managing applications on [Joyent's Triton](https://www.joyent.com/triton).
**This is not intended for general use and is completely unsupported.**
## Our Principles
We have designed this product with these principles in mind (to be completed).
## Our Design Library
We use inVision craft for our design components, you can downoad this library [here](https://drive.google.com/open?id=0Bw56g3tFwIuWOXNHUDZmRmQ3ZlE) and submit proposed changes to our Sketch wireframes [here](https://drive.google.com/open?id=0B1oWObk56wa5cE5iY2JWNmI2djg).
## Documentation
Our workshop meeting notes are kept in this [Google Drive folder](https://drive.google.com/open?id=0B1oWObk56wa5eklBNGFlWFRFOHM). Our meeting notes are kept in this [Google Drive folder](https://drive.google.com/open?id=0B1oWObk56wa5N1VzZjhZWWpDTTQ).
## Development
If you would like to contribute to the project, the recommended way to setup is to
insure that you have docker installed, and optionally have a triton account and profile
setup using the triton tool.
Currently requires [yarn](https://yarnpkg.com/en/docs/install) for installing dependencies,
as well as `docker` and `docker-compose` are installed correctly, this can be done by
running `make`, make continues without any errors, then you are good to go. [node-triton](https://github.com/joyent/node-triton)
is also needed if deployment to Triton is required.
```
make && make install
```
Then to run each individual component locally (subject to change).
## Setup
```sh
make
```
## Run services
To run the stack locally:
```sh
docker-compose -f local-compose.yml up -d
```
This will run the front-end at [http://127.0.0.1:8000](http://127.0.0.1:8000),
the UI framework at [http://127.0.0.1:8001](http://127.0.0.1:8001),
## Project Management
This project is using [Github Projects](https://www.youtube.com/watch?v=C6MGKHkNtxU) for organisation and development of the Joyent Dashboard.
## Repository Layout
Currently we are using this repository as a monolithic catch-all for all project communication, development and designs.
We will also include multiple PoC's of various bits of functionality from UI's prototypes to API development.
```
.
├── cloudapi-graphql
├── docs
├── frontend
├── nginx
├── ui
└── spikes
```
### cloudapi-graphql
An implementation of the [Joyent CloudAPI](https://apidocs.joyent.com/cloudapi/) in GraphQL.
### Docs
Documentation about the project, mainly focused on information for the technical runnings of this project.
Can be view online at the [documentation website](http://docs.svc.f4b20699-b323-4452-9091-977895896da6.eu-ams-1.triton.zone/)
### frontend
The client side code with a dev-server, this also includes the production server for the meantime, however we are looking at moving towards a deployment of the build artifacts to manta, and another server to host these assets.
### nginx
Nginx will be sitting in-front of the `ui` service, allowing the `ui` to scale out.
### ui
Code for the reusable UI framework.
### spikes
Implementation examples from spikes, this directory is experimental and is likely broken.
### Git LFS
- We are using Git LFS to track large files, such as design files in Sketch.
- Make sure you have this downloaded locally
`brew install git-lfs`
#### Helpful tips
- If there is an error cloning to a new machine, or there is an error cloning in the Circle CI process run `git lfs push origin master --all` from a machine that has it already checked out.
### Sketch Pre Commit
A pre-commit hook has been added to generate a PNG shot of each .sketch file "page".
To use, make sure the following are installed:
- [Sketch Toolbox](http://sketchtoolbox.com/)
- [Sketch Measure Plugin](https://github.com/utom/sketch-measure)
Then add following to your `.git/config`
```
[diff "sketchtool"]
textconv = "sketchtool dump"
cachetextconv = true
```

View File

@ -1,30 +0,0 @@
#! /usr/bin/env bash
#
# Prelude - make bash behave sanely
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
#
set -euo pipefail
# Beware of CDPATH gotchas causing cd not to work correctly when a user
# has set this in their environment
# https://bosker.wordpress.com/2012/02/12/bash-scripters-beware-of-the-cdpath/
unset CDPATH
readonly INCLUDE="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# shellcheck source=bin/setup-tools
. "${INCLUDE}"/setup-tools
echo ">> running triton deploy with docker-compose"
ensure_command triton
ensure_triton_cns_is_enabled
get_triton_details
write_env_file
export DOCKER_HOST=$_DOCKER_HOST
export DOCKER_CERT_PATH=$_DOCKER_CERT_PATH
# Do not TLS verify for now, incompatibilities between circleci and joyent
export DOCKER_TLS_VERIFY=
docker-compose pull
COMPOSE_PROJECT_NAME=${CIRCLE_BRANCH} docker-compose up -d

View File

@ -1,10 +0,0 @@
#! /usr/bin/env bash
#
# Prelude - make bash behave sanely
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
#
set -euo pipefail
echo ">> Logging into $_DOCKER_REGISTRY"
docker login -e="." -u="$_DOCKER_LOGIN_USERNAME" -p="$_DOCKER_LOGIN_PASSWORD" "$_DOCKER_REGISTRY"

View File

@ -1,203 +0,0 @@
#! /usr/bin/env bash
#
# Prelude - make bash behave sanely
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
#
set -euo pipefail
IFS=$'\n\t'
#
# Globals
#
remember_git_start_and_end() {
HEAD="$(git rev-parse HEAD)"
ROOT="$(git log --pretty=format:%H | tail -n 1)"
}
#
# Utilities
#
die() {
local msg="$@"
[[ -z "${msg}" ]] || {
tput setaf 1 # red
tput bold
echo "${msg}"
tput sgr0 # reset
}
exit 1
}
error() {
local msg="$@"
echo -n '| '
tput setaf 1 # red
echo -n ' ✖'
tput sgr0 # reset
echo " ${msg}"
}
success() {
local msg="$@"
echo -n '| '
tput setaf 2 # green
echo -n ' ✓'
tput sgr0 # reset
echo " ${msg}"
}
log_commit() {
echo "○ $@"
}
# Check a command is present
ensure_command() {
local cmd="$1"
command -v "${cmd}" > /dev/null 2>&1 || {
die "Couldn't find required command: ${cmd}"
}
}
#
# Signal handling
#
cleanup() {
git reset --hard "${HEAD}" > /dev/null 2>&1
rm -f $$_commit_message
}
trap cleanup SIGHUP SIGINT SIGTERM
#
# Git helpers
#
# Go back one commit in history (first parent for merges)
step_back_one_commit() {
git reset --hard HEAD^ > /dev/null
log_commit "$(git rev-parse HEAD)"
}
current_commit_message() {
GIT_PAGER= git log --format=%B -n 1
}
current_commit_sha() {
git rev-parse HEAD
}
exit_if_not_git_repo() {
local gitroot="$(git rev-parse --show-toplevel 2> /dev/null)"
[[ "${gitroot}" == "" ]] && die 'Current directory is not in a repository'
return 0
}
#
# Checks
#
check_commit_message() {
local lineno=0
local length=0
local succeded=1
while read -r line ; do
let succeded=1
let lineno+=1
length=${#line}
[[ "${lineno}" -eq "1" ]] && {
[[ "${length}" -gt 50 ]] && {
error "Commit message: Subject line longer than 50 characters";
succeded=0
};
[[ ! "${line}" =~ ^[A-Z].*$ ]] && {
error "Commit message: Subject line not capitalised";
succeded=0
};
[[ "${line}" == *. ]] && {
error "Commit message: Subject line ended with a full stop";
succeded=0
};
}
[[ "${lineno}" -eq "2" ]] && [[ -n "${line}" ]] && {
error "Commit message: Subject line not separated by a blank line";
succeded=0;
};
[[ "${lineno}" -gt "1" ]] && [[ "${length}" -gt "72" ]] && {
error "Commit message: Body not wrapped at 72 characters";
succeded=0
};
done < $$_commit_message
[[ "${succeded}" -eq "1" ]] && success "Commit message"
return 0
}
run_checks() {
current_commit_message > $$_commit_message
check_commit_message
rm -f $$_commit_message
set +e
npm run lint > /dev/null 2>&1
if [[ "$?" -eq 0 ]]; then
success 'Lint'
else
error 'Lint: script did not exit successfully'
fi
npm test > /dev/null 2>&1
if [[ "$?" -eq 0 ]]; then
success 'Test'
else
error 'Test: script did not exit successfully'
fi
set -e
}
check_project() {
exit_if_not_git_repo
[[ -f './package.json' ]] || {
die 'This does not appear to be a node project'
}
[[ -z "$(json -f package.json 'scripts.lint')" ]] && {
die 'There is no lint script in the package.json'
}
[[ -z "$(json -f package.json 'scripts.test')" ]] && {
die 'There is no test script in the package.json'
}
return 0
}
traverse_history() {
while [[ "${ROOT}" != "$(current_commit_sha)" ]] ; do
run_checks
step_back_one_commit
done
}
#
# Main
#
ensure_command git
ensure_command tail
ensure_command npm
ensure_command json
check_project
remember_git_start_and_end
log_commit "HEAD: $(current_commit_sha)"
traverse_history
run_checks
log_commit "ROOT: $(current_commit_sha)"
cleanup
# vim: syntax=sh et ts=2 sts=2 sw=2

View File

@ -1,16 +0,0 @@
#! /usr/bin/env bash
#
# Prelude
#
set -euo pipefail
set -x
# Set internal field seperator to `/` to split up urls
IFS='/'
read -ra ADDR <<< "$CIRCLE_COMPARE_URL"
if [[ "$(git diff --name-only """${ADDR[-1]}""")" == *"ui/"* ]]
then
make -C ui publish | sed '/NPM_TOKEN/d'
fi

View File

@ -1,60 +0,0 @@
#! /usr/bin/env bash
#
# Prelude - make bash behave sanely
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
#
set -euo pipefail
# Make pushd & popd silent
pushd () {
command pushd "$@" > /dev/null
}
popd () {
command popd "$@" > /dev/null
}
export EXIT_CODE=0
function lint_changed() {
# Allow lint to be ran from outside of the root directory
local git_root
git_root=$(git rev-parse --show-cdup)
git_root=${git_root:-./}
local subdirs
subdirs=$(find "$git_root" -maxdepth 2 -mindepth 2 -name 'Makefile' -printf '%h\n')
for directory in $subdirs
do
pushd "$directory"
local npm_bin="node_modules/.bin"
local eslint="$npm_bin/eslint"
function lint() {
local to_lint
to_lint=$(git diff --staged --diff-filter=ACMTUXB --name-only -- '*.j'{s,sx})
echo $to_lint
echo $eslint
if [ "$to_lint" ]; then
$eslint "$to_lint" -c ".eslintrc" || EXIT_CODE=$?
fi
}
lint
popd
done
}
lint_changed
if [[ "$EXIT_CODE" -gt "0" ]]; then
exit $EXIT_CODE
fi
make test
echo "⚡️ changed files pass eslint! ⚡️"

View File

@ -1,23 +0,0 @@
#! /usr/bin/env bash
#
# Prelude
#
set -euo pipefail
IFS=$'\n\t'
# Beware of CDPATH gotchas causing cd not to work correctly when a user
# has set this in their environment
# https://bosker.wordpress.com/2012/02/12/bash-scripters-beware-of-the-cdpath/
unset CDPATH
readonly INCLUDE="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# shellcheck source=bin/setup-tools
. "${INCLUDE}"/setup-tools
#
# Main
#
ensure_prerequisites
get_triton_details
check_docker_config
write_env_file

View File

@ -1,105 +0,0 @@
#! /usr/bin/env bash
# setup.sh - Checks that all the required tools are present and that they are
# appropriately configured for deploying to Triton.
#
# Adapted from https://github.com/autopilotpattern/mysql/blob/master/setup.sh
#
#
# Prelude
#
set -euo pipefail
IFS=$'\n\t'
#
# Utilities
#
die() {
local msg="$*"
[[ -z "${msg}" ]] || {
echo
tput setaf 1 # red
tput bold
echo "${msg}"
tput sgr0 # reset
}
exit 1
}
#
# Check functions
#
ensure_command() {
local cmd="$1"
command -v "${cmd}" > /dev/null 2>&1 || {
die "Couldn't find required command: ${cmd}"
}
}
get_triton_details() {
TRITON_USER=$(triton profile get | awk -F": " '/account:/{print $2}')
TRITON_DC=$(triton profile get | awk -F"/" '/url:/{print $3}' | awk -F'.' '{print $1}')
TRITON_URL=$(triton profile get | awk -F' ' '/url:/{print $2}')
TRITON_ACCOUNT=$(triton account get | awk -F": " '/id:/{print $2}')
TRITON_KEY=$(triton profile get | awk -F' ' '/keyId:/{print $2}')
}
check_docker_config() {
[[ "${DOCKER_HOST:=unset}" == "unset" ]] && {
echo "Run \"docker-compose -f local-compose.yml up\" to run locally"
return 0
}
return 0
}
ensure_docker_config_matches_triton_config_and_capture_triton_details() {
local docker_user
docker_user=$(docker info 2>&1 | awk -F": " '/SDCAccount:/{print $2}')
local docker_dc
docker_dc="$(echo "${DOCKER_HOST}" | awk -F"/" '{print $3}' | awk -F'.' '{print $1}')"
get_triton_details
[[ ! "$docker_user" = "$TRITON_USER" ]] || [[ ! "$docker_dc" = "$TRITON_DC" ]] && {
echo "Docker user: ${docker_user}"
echo "Triton user: ${TRITON_USER}"
echo "Docker data center: ${docker_dc}"
echo "Triton data center: ${TRITON_DC}"
die "Your Triton config does not match your Docker configuration."
}
return 0;
}
ensure_triton_cns_is_enabled() {
local triton_cns_enabled
triton_cns_enabled=$(triton account get | awk -F": " '/cns/{print $2}')
[[ "$triton_cns_enabled" == "true" ]] || {
die "Triton CNS is required and not enabled."
}
}
write_env_file() {
if [[ -f .env ]] ; then
echo "Env file already exists, not overwriting"
else
echo '# Consul discovery via Triton CNS' >> .env
[[ "${DOCKER_HOST:=unset}" == "*docker.joyent.com*" ]] || {
echo CONSUL="consul.svc.${TRITON_ACCOUNT}.${TRITON_DC}.cns.joyent.com" \
>> .env
}
echo SDC_KEY_ID=${TRITON_KEY} >> .env
echo SDC_ACCOUNT=${TRITON_ACCOUNT} >> .env
echo SDC_URL=${TRITON_URL} >> .env
echo >> .env
fi
}
ensure_prerequisites() {
ensure_command docker
ensure_command docker-compose
ensure_command triton
}
# vim: syntax=sh et ts=2 sts=2 sw=2

View File

@ -1,57 +0,0 @@
#!/usr/bin/env ruby
require 'fileutils'
PROGNAME = 'pre-commit (auto-generate sketch previews)'
def main
progress "Installing sketchtool"
system!(%W[/Applications/Sketch.app/Contents/Resources/sketchtool/install.sh])
progress "Looking for changed or added .sketch files"
diff_output = capture!(%W[git diff --name-only --cached --pretty=format:])
sketch_files = diff_output.split("\n").grep(/\.sketch\z/)
if sketch_files.empty?
progress "No sketch files to create preview images for in this commit!"
end
puts sketch_files
sketch_files.each do |f|
unless File.exist?(f)
progress "#{f} does not exist (anymore?)"
next
end
png_output_dir = f.sub(/\.sketch\z/, '') + '-sketch-previews'
progress "deleting old previews"
FileUtils.rm_rf(png_output_dir)
progress "exporting pages"
cmd = %W[sketchtool --overwriting=YES --output=#{png_output_dir} export pages #{f}]
system!(cmd)
progress "adding to git"
system!(%W[git add #{png_output_dir}])
end
end
def system!(cmd)
puts "running: #{cmd.join(' ')}"
abort failure_message(cmd) unless system(*cmd)
end
def capture!(cmd)
puts "capturing: #{cmd.join(' ')}"
result = IO.popen(cmd) { |io| io.read }
abort failure_message(cmd) unless $?.success?
result
end
def failure_message(cmd)
"#{PROGNAME}: command failed: #{cmd.join(' ')}"
end
def progress(msg)
puts "#{PROGNAME}: #{msg}"
end
main

View File

@ -1,51 +0,0 @@
## Customize the test machine
machine:
pre:
- git config --global user.email "circleci@joyent.zone"
- git config --global user.name "circlebot"
- curl -sSL https://s3.amazonaws.com/circle-downloads/install-circleci-docker.sh | bash -s -- 1.10.0
services:
- docker
node:
version: 7.7.3
dependencies:
pre:
- sudo curl -L https://github.com/docker/compose/releases/download/1.8.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
- sudo chmod +x /usr/local/bin/docker-compose
- yarn global add triton@4.15.0 || cat /home/ubuntu/.yarn-config/global/yarn-error.log
- echo '{"url":"https://eu-ams-1.api.joyent.com","account":"'$SDC_ACCOUNT'","keyId":"c3:30:35:9b:85:48:73:44:31:cc:4b:2e:6a:00:16:e2","name":"eu-ams-1","curr":true}' | triton profile create -f -
- triton env --docker eu-ams-1
- mkdir -p ${CIRCLE_TEST_REPORTS}/tap-xunit/
- echo -e "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
override:
- make && make install
# Install git-lfs - TODO: Move to make task
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
- sudo apt-get install git-lfs
- ssh git@github.com git-lfs-authenticate yldio/joyent-portal.git download
- git config credential.helper manager
- git lfs pull
test:
override:
- make -j2 lint-ci test-ci
deployment:
development:
branch: master
commands:
- ./bin/docker-login
- ./bin/on-changes-publish-ui
- make -j2 build
- make -j2 push
- ./bin/deploy
staging:
tag: /release.*/
commands:
- CIRCLE_BRANCH=staging ./bin/docker-login
- CIRCLE_BRANCH=staging ./bin/on-changes-publish-ui
- CIRCLE_BRANCH=staging make -j2 build
- CIRCLE_BRANCH=staging make -j2 push
- CIRCLE_BRANCH=staging ./bin/deploy

View File

@ -1,27 +0,0 @@
{
"extends": [
"eslint:recommended",
"prettier"
],
"plugins": [
"prettier"
],
"rules": {
"no-console": 0,
"prettier/prettier": ["error", {
"useTabs": false,
"printWidth": 80,
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"parser": "flow",
"semi": true
}]
},
"env": {
"es6": true,
"node": true
}
}

View File

@ -1,50 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Vim files:
*.sw*
# Mac OS dirty files
.DS_Store

View File

@ -1 +0,0 @@
FROM quay.io/yldio/alpine-node-containerpilot:6.9.4-3

View File

@ -1,54 +0,0 @@
NAME := $(lastword $(subst /, ,$(CURDIR)))
bindir := $(shell yarn bin)
AVA := $(bindir)/ava
NYC := $(bindir)/nyc
.PHONY: install
install:
yarn install --prefer-offline
.PHONY: install-production
install-production:
yarn install --production --pure-lockfile --prefer-offline
.PHONY: clean
clean:
@rm -rf node_modules
.PHONY: test
test:
$(AVA) $(TEST_ARGS)
XUNIT_DIR := ${CIRCLE_TEST_REPORTS}/tap-xunit
XUNIT := $(bindir)/tap-xunit
XUNIT_OUTPUT := >> ${CIRCLE_TEST_REPORTS}/tap-xunit/xunit-$(NAME)
.PHONY: test-ci
test-ci:
mkdir -p $(XUNIT_DIR)
$(NYC) $(AVA) -t | $(XUNIT) $(XUNIT_OUTPUT).xml
.PHONY: start
start:
yarn run start
.PHONY: build
build:
docker build -t quay.io/yldio/joyent-dashboard-$(NAME):$(CIRCLE_BRANCH) .
.PHONY: push
push:
docker push quay.io/yldio/joyent-dashboard-$(NAME)
.PHONY: lint
lint:
$(bindir)/eslint .
.PHONY: lint-ci
lint-ci:
mkdir -p $(XUNIT_DIR)
-$(bindir)/eslint . --format tap | $(XUNIT) $(XUNIT_OUTPUT)-lint.xml
.PHONY: licence-check
licence-check:
../node_modules/.bin/license-to-fail ../licence.js

View File

@ -1,166 +0,0 @@
[![Docker Repository on Quay](https://quay.io/repository/yldio/joyent-dashboard-cloudapi-graphql/status?token=bddd694a-a913-4b66-b7bc-fb71992672c4 "Docker Repository on Quay")](https://quay.io/repository/yldio/joyent-dashboard-cloudapi-graphql)
# cloudapi-graphql
Proof-of-Concept of the [Joyent Cloud API](https://apidocs.joyent.com/cloudapi/) running on GraphQL.
## Setup
### Setup Credentials
Create `credentials.json`:
```json5
{
"url": "https://us-sw-1.api.joyentcloud.com",
"keyId": "", //public key fingerprint ex: 35:jh:42:56...
"account": "", // account ex: raoulmillais
"user": "" // sub-account ex: ramitos
}
```
Alternatively you can just use ENV variables:
```
SDC_URL
SDC_ACCOUNT
SDC_USER
SDC_KEY_ID
```
As a third option you can use a `.env` file.
### Install Dependencies and run
```bash
yarn install
yarn start
```
### Visit GraphiQL
Go-to http://0.0.0.0:4000/graphql to use the REPL with interactive documentation.
![GraphiQL](https://cloud.githubusercontent.com/assets/524382/19242455/1e371978-8f0b-11e6-9563-d6f5b93fa63c.png)
## API
- [x] Account
- [x] GetAccount
- [x] UpdateAccount
- [x] Keys
- [x] ListKeys
- [x] GetKey
- [x] CreateKey
- [x] DeleteKey
- [x] Users
- [x] ListUsers
- [x] GetUser
- [x] CreateUser
- [x] UpdateUser
- [ ] ChangeUserPassword
- [x] DeleteUser
- [x] Roles
- [x] ListRoles
- [x] GetRole
- [x] CreateRole
- [x] UpdateRole
- [x] DeleteRole
- [x] Role Tags
- [x] SetRoleTags
- [x] Policies
- [x] ListPolicies
- [x] GetPolicy
- [x] CreatePolicy
- [x] UpdatePolicy
- [x] DeletePolicy
- [x] User SSH Keys
- [x] ListUserKeys
- [x] GetUserKey
- [x] CreateUserKey
- [x] DeleteUserKey
- [ ] Config
- [ ] GetConfig
- [ ] UpdateConfig
- [x] Datacenters
- [x] ListDatacenters
- [x] GetDatacenter
- [x] Services
- [x] ListServices
- [x] Images
- [x] ListImages
- [x] GetImage
- [x] DeleteImage
- [x] ExportImage
- [x] CreateImageFromMachine
- [ ] UpdateImage
- [x] Packages
- [x] ListPackages
- [x] GetPackage
- [x] Instances
- [x] ListMachines
- [x] GetMachine
- [x] CreateMachine
- [x] StopMachine
- [x] StartMachine
- [x] RebootMachine
- [ ] ResizeMachine
- [ ] RenameMachine
- [x] EnableMachineFirewall
- [x] DisableMachineFirewall
- [x] CreateMachineSnapshot
- [x] StartMachineFromSnapshot
- [x] ListMachineSnapshots
- [x] GetMachineSnapshot
- [x] DeleteMachineSnapshot
- [ ] UpdateMachineMetadata
- [ ] ListMachineMetadata
- [ ] GetMachineMetadata
- [ ] DeleteMachineMetadata
- [ ] DeleteAllMachineMetadata
- [x] AddMachineTags
- [x] ReplaceMachineTags
- [ ] ListMachineTags
- [x] GetMachineTag
- [x] DeleteMachineTag
- [x] DeleteMachineTags
- [x] DeleteMachine
- [x] MachineAudit
- [ ] Analytics
- [ ] DescribeAnalytics
- [ ] ListInstrumentations
- [ ] GetInstrumentation
- [ ] GetInstrumentationValue
- [ ] GetInstrumentationHeatmap
- [ ] GetInstrumentationHeatmapDetails
- [ ] CreateInstrumentation
- [ ] DeleteInstrumentation
- [x] FirewallRules
- [x] Firewall Rule Syntax
- [x] ListFirewallRules
- [x] GetFirewallRule
- [x] CreateFirewallRule
- [x] UpdateFirewallRule
- [x] EnableFirewallRule
- [x] DisableFirewallRule
- [x] DeleteFirewallRule
- [x] ListMachineFirewallRules
- [x] ListFirewallRuleMachines
- [ ] Fabrics
- [ ] ListFabricVLANs
- [ ] CreateFabricVLAN
- [ ] GetFabricVLAN
- [ ] UpdateFabricVLAN
- [ ] DeleteFabricVLAN
- [ ] ListFabricNetworks
- [ ] CreateFabricNetwork
- [ ] GetFabricNetwork
- [ ] DeleteFabricNetwork
- [x] Networks
- [x] ListNetworks
- [x] GetNetwork
- [ ] Nics
- [ ] ListNics
- [ ] GetNic
- [ ] AddNic
- [ ] RemoveNic

View File

@ -1,38 +0,0 @@
{
"consul": "{{ .CONSUL }}:8500",
"services": [{
"name": "joyent-portal-cloudapi-graphql",
"port": 4000,
"health": "/usr/bin/curl -o /dev/null --fail -s http://localhost:4000/graphql",
"poll": 3,
"ttl": 10
}],
"telemetry": {
"port": 9090,
"sensors": [{
"name": "graphql_memory_percent",
"help": "percentage of memory used",
"type": "gauge",
"poll": 5,
"check": ["/bin/sensors", "memory"]
}, {
"name": "graphql_cpu_load",
"help": "cpu load",
"type": "gauge",
"poll": 5,
"check": ["/bin/sensors", "cpu"]
}, {
"name": "graphql_disk_capacity",
"help": "disk capacity",
"type": "gauge",
"poll": 60,
"check": ["/bin/sensors", "diskcapacity"]
}, {
"name": "graphql_disk_usage",
"help": "disk usage",
"type": "gauge",
"poll": 60,
"check": ["/bin/sensors", "diskusage"]
}]
}
}

View File

@ -1,31 +0,0 @@
{
"name": "cloudapi-graphql",
"private": true,
"license": "MPL-2.0",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"lint": "eslint src --fix",
"start": "node src/index.js",
"test": "make test"
},
"dependencies": {
"bunyan": "^1.8.10",
"dotenv": "^4.0.0",
"express": "^4.15.2",
"express-graphql": "^0.6.4",
"got": "^6.7.1",
"graphql": "^0.9.3",
"smartdc-auth": "^2.5.2",
"triton": "^5.2.0"
},
"devDependencies": {
"ava": "^0.19.1",
"eslint": "^3.19.0",
"eslint-config-prettier": "^1.7.0",
"eslint-plugin-prettier": "^2.0.1",
"nyc": "^10.2.0",
"prettier": "^1.2.2",
"tap-xunit": "^1.7.0"
}
}

View File

@ -1,9 +0,0 @@
const request = require('./request');
module.exports.get = () => {
return request('getAccount');
};
module.exports.update = ctx => {
return request('updateAccount', ctx);
};

View File

@ -1,5 +0,0 @@
// const request = require('./request');
module.exports.get = () => {
// return request('', ctx);
};

View File

@ -1,5 +0,0 @@
const request = require('./request');
module.exports = () => {
return request('listDatacenters');
};

View File

@ -1,9 +0,0 @@
const request = require('./request');
module.exports.list = () => {
return request('listFirewallRules', {});
};
module.exports.get = ctx => {
return request('getFirewallRule', ctx);
};

View File

@ -1,37 +0,0 @@
const request = require('./request');
module.exports.list = () => {
return request('listFirewallRules', {});
};
module.exports.listByMachine = ctx => {
return request('listMachineFirewallRules', ctx);
};
module.exports.listMachines = ctx => {
return request('listFirewallRuleMachines', ctx);
};
module.exports.get = ctx => {
return request('getFirewallRule', ctx);
};
module.exports.create = ctx => {
return request('createFirewallRule', ctx);
};
module.exports.update = ctx => {
return request('updateFirewallRule', ctx);
};
module.exports.enable = ctx => {
return request('enableFirewallRule', ctx);
};
module.exports.disable = ctx => {
return request('disableFirewallRule', ctx);
};
module.exports.destroy = ctx => {
return request('deleteFirewallRule', ctx);
};

View File

@ -1,25 +0,0 @@
const request = require('./request');
module.exports.list = ctx => {
return request('listImages', ctx);
};
module.exports.get = ctx => {
return request('getImage', ctx);
};
module.exports.create = ctx => {
return request('createImageFromMachine', ctx);
};
// module.exports.update = (ctx) => {
// return request('UpdateImage', ctx);
// };
module.exports.destroy = uuid => {
return request('deleteImage', uuid);
};
// module.exports.xport = (uuid) => {
// return request('deleteImage', uuid);
// };

View File

@ -1,16 +0,0 @@
module.exports = {
account: require('./account'),
users: require('./users'),
policies: require('./policies'),
roles: require('./roles'),
keys: require('./keys'),
datacenters: require('./datacenters'),
services: require('./services'),
images: require('./images'),
packages: require('./packages'),
machines: require('./machines'),
firewallRules: require('./firewall-rules'),
// fabrics: require('./fabrics'),
networks: require('./networks'),
nics: require('./nics')
};

View File

@ -1,35 +0,0 @@
const request = require('./request');
module.exports = {
user: {
list: ctx => {
return request('listUserKeys', ctx);
},
get: ctx => {
return request('getUserKey', ctx);
},
create: ctx => {
return request('createUserKey', ctx);
},
destroy: ctx => {
return request('deleteUserKey', ctx);
}
},
account: {
list: () => {
return request('listKeys', {});
},
get: ctx => {
return request('getKey', ctx);
},
create: ctx => {
return request('createKey', ctx);
},
destroy: ctx => {
return request('deleteKey', ctx);
}
}
};

View File

@ -1,108 +0,0 @@
const request = require('./request');
const snapshots = {
list: ctx => {
return request('listMachineSnapshots', ctx);
},
get: ctx => {
return request('getMachineSnapshot', ctx);
},
create: ctx => {
return request('createMachineSnapshot', ctx);
},
destroy: ctx => {
return request('deleteMachineSnapshot', ctx);
}
};
const metadata = {
list: ctx => {
return request('', ctx);
},
get: ctx => {
return request('', ctx);
},
update: ctx => {
return request('', ctx);
},
destroy: ctx => {
return request('', ctx);
}
};
const firewall = {
enable: ctx => {
return request('enableMachineFirewall', ctx);
},
disable: ctx => {
return request('disableMachineFirewall', ctx);
}
};
const tags = {
list: ctx => {
return request('listMachineTags', ctx);
},
get: ctx => {
return request('getMachineTag', ctx);
},
add: ctx => {
return request('addMachineTags', ctx);
},
replace: ctx => {
return request('replaceMachineTags', ctx);
},
destroy: ctx => {
const method = ctx.tag ? 'deleteMachineTag' : 'deleteMachineTags';
return request(method, ctx);
}
};
module.exports.list = ctx => {
return request('listMachines', ctx);
};
module.exports.get = ctx => {
return request('getMachine', ctx);
};
module.exports.create = ctx => {
return request('createMachine', ctx);
};
module.exports.stop = ctx => {
return request('stopMachine', ctx);
};
module.exports.start = uuid => {
return request('startMachine', uuid);
};
module.exports.startFromSnapshot = ctx => {
return request('startMachineFromSnapshot', ctx);
};
module.exports.reboot = ctx => {
return request('rebootMachine', ctx);
};
module.exports.resize = ctx => {
return request('', ctx);
};
module.exports.rename = ctx => {
return request('', ctx);
};
module.exports.destroy = ctx => {
return request('deleteMachine', ctx);
};
module.exports.audit = ctx => {
return request('machineAudit', ctx);
};
module.exports.snapshots = snapshots;
module.exports.metadata = metadata;
module.exports.firewall = firewall;
module.exports.tags = tags;

View File

@ -1,9 +0,0 @@
const request = require('./request');
module.exports.list = () => {
return request('listNetworks');
};
module.exports.get = ctx => {
return request('getNetwork', ctx);
};

View File

@ -1,9 +0,0 @@
const request = require('./request');
module.exports.list = () => {
return request('listNics');
};
module.exports.get = ctx => {
return request('getNic', ctx);
};

View File

@ -1,9 +0,0 @@
const request = require('./request');
module.exports.list = ctx => {
return request('listPackages', ctx);
};
module.exports.get = ctx => {
return request('getPackage', ctx);
};

View File

@ -1,21 +0,0 @@
const request = require('./request');
module.exports.list = () => {
return request('listPolicies');
};
module.exports.get = ctx => {
return request('getPolicy', ctx);
};
module.exports.create = ctx => {
return request('createPolicy', ctx);
};
module.exports.update = ctx => {
return request('updatePolicy', ctx);
};
module.exports.destroy = ctx => {
return request('deletePolicy', ctx);
};

View File

@ -1,40 +0,0 @@
const credentials = require('../credentials');
const auth = require('smartdc-auth');
const cloudapi = require('triton/lib/cloudapi2');
const bunyan = require('bunyan');
const pkg = require('../../package.json');
var log = bunyan.createLogger({
name: pkg.name
});
var client = cloudapi.createClient({
log: log,
url: credentials.url,
account: credentials.account,
user: credentials.user,
sign: auth.cliSigner({
log: log,
keyId: credentials.keyId,
user: credentials.account,
subuser: credentials.user
})
});
module.exports = (method, args) => {
return new Promise((resolve, reject) => {
const fn = client[method].bind(client);
const cb = (err, res) => {
if (err) {
return reject(err);
}
resolve(res);
};
return args ? fn(args, cb) : fn(cb);
});
};
module.exports.client = client;

View File

@ -1,31 +0,0 @@
const request = require('./request');
module.exports.list = () => {
return request('listRoles');
};
module.exports.get = ctx => {
return request('getRole', ctx);
};
module.exports.create = ctx => {
return request('createRole', ctx);
};
module.exports.set = ctx => {
const id = ctx.id ? `/${ctx.id}` : '';
const resource = `/${request.client.account}/${ctx.resource}${id}`;
return request('setRoleTags', {
roleTags: ctx.role,
resource
});
};
module.exports.update = ctx => {
return request('updateRole', ctx);
};
module.exports.destroy = ctx => {
return request('deleteRole', ctx);
};

View File

@ -1,5 +0,0 @@
const request = require('./request');
module.exports = () => {
return request('listServices');
};

View File

@ -1,21 +0,0 @@
const request = require('./request');
module.exports.list = () => {
return request('listUsers');
};
module.exports.get = ctx => {
return request('getUser', ctx);
};
module.exports.create = ctx => {
return request('createUser', ctx);
};
module.exports.destroy = ctx => {
return request('deleteUser', ctx);
};
module.exports.update = ctx => {
return request('updateUser', ctx);
};

View File

@ -1,27 +0,0 @@
const json = (() => {
try {
const res = require('dotenv').config({
path: '../.env',
silent: true
});
if (res.error) {
throw res.error;
}
} catch (err) {
try {
return require('../credentials.json');
} catch (err) {
return {};
}
}
return {};
})();
module.exports = {
url: process.env.SDC_URL || json.SDC_URL || json.url || '',
account: process.env.SDC_ACCOUNT || json.SDC_ACCOUNT || json.account || '',
user: process.env.SDC_USER || json.SDC_USER || json.user || '',
keyId: process.env.SDC_KEY_ID || json.SDC_KEY_ID || json.keyId || ''
};

View File

@ -1,8 +0,0 @@
const graphqlHTTP = require('express-graphql');
const schema = require('./schema');
module.exports = graphqlHTTP(() => ({
schema: schema,
graphiql: true,
pretty: true
}));

View File

@ -1,14 +0,0 @@
const express = require('express');
const app = express();
app.use('/graphql', require('./endpoint'));
const server = app.listen(4000, err => {
if (err) {
console.error(err);
throw err;
}
console.log(`Listening at http://0.0.0.0:${server.address().port}/graphql`);
});

View File

@ -1,10 +0,0 @@
const graphql = require('graphql');
const mutation = require('./mutations');
const query = require('./queries');
const { GraphQLSchema } = graphql;
module.exports = new GraphQLSchema({
query,
mutation
});

View File

@ -1,56 +0,0 @@
const AccountType = require('../types/login');
const api = require('../../api');
const { GraphQLBoolean, GraphQLString } = require('graphql');
module.exports.updateAccount = {
type: AccountType,
description: 'Update your account details',
args: {
email: {
type: GraphQLString
},
company_name: {
type: GraphQLString
},
first_name: {
type: GraphQLString
},
last_name: {
type: GraphQLString
},
address: {
type: GraphQLString
},
postal_code: {
type: GraphQLString
},
city: {
type: GraphQLString
},
state: {
type: GraphQLString
},
country: {
type: GraphQLString
},
phone: {
type: GraphQLString
},
cns_enabled: {
type: GraphQLBoolean
}
},
resolve: (root, args) => {
return api.account.get().then(account => {
return api.account.update(
Object.assign(account, args, {
firstName: args.first_name || account.firstName,
lastName: args.first_name || account.lastName,
companyName: args.company_name || account.companyName,
postalCode: args.postal_code || account.postalCode
})
);
});
}
};

View File

@ -1,98 +0,0 @@
const FirewallRuleType = require('../types/firewall-rule');
const api = require('../../api');
const { GraphQLID, GraphQLBoolean, GraphQLString } = require('graphql');
module.exports.createFirewallRule = {
type: FirewallRuleType,
description: "Adds a new firewall rule for the specified account. This rule will be added to all the account's instances where it may be necessary",
args: {
enabled: {
type: GraphQLBoolean,
description: 'Indicates if the rule is enabled (optional, false by default)'
},
rule: {
type: GraphQLString,
description: 'Firewall rule text'
},
description: {
type: GraphQLString,
description: 'Human-readable description for the rule (optional)'
}
},
resolve: (root, args) => {
return api.firewallRules.create({
rule: args.rule,
description: args.description,
enabled: !!args.enabled
});
}
};
module.exports.updateFirewallRule = {
type: FirewallRuleType,
description: 'Updates the given rule record and -- depending on rule contents -- adds/removes/updates the rule on all the required instances',
args: {
id: {
type: GraphQLID,
description: 'Firewall rule id'
},
enabled: {
type: GraphQLBoolean,
description: 'Indicates if the rule is enabled (optional, false by default)'
},
rule: {
type: GraphQLString,
description: 'Firewall rule text'
},
description: {
type: GraphQLString,
description: 'Human-readable description for the rule (optional)'
}
},
resolve: (root, args) => {
return api.firewallRules.update(args);
}
};
module.exports.enableFirewallRule = {
type: FirewallRuleType,
description: 'Enables the given firewall rule if it is disabled',
args: {
id: {
type: GraphQLID,
description: 'Firewall rule id'
}
},
resolve: (root, args) => {
return api.firewallRules.enable(args);
}
};
module.exports.disableFirewallRule = {
type: FirewallRuleType,
description: 'Disables the given firewall rule if it is enabled',
args: {
id: {
type: GraphQLID,
description: 'Firewall rule id'
}
},
resolve: (root, args) => {
return api.firewallRules.disable(args);
}
};
module.exports.deleteFirewallRule = {
type: FirewallRuleType,
description: 'Removes the given firewall rule from all the required instances',
args: {
id: {
type: GraphQLID,
description: 'Firewall rule id'
}
},
resolve: (root, args) => {
return api.firewallRules.destroy(args);
}
};

View File

@ -1,54 +0,0 @@
const AccountType = require('../types/login');
const DynamicObjectType = require('../types/dynamic-object');
const api = require('../../api');
const {
GraphQLString,
GraphQLList,
GraphQLNonNull,
GraphQLID
} = require('graphql');
module.exports.createImage = {
type: AccountType,
description: 'Create a new custom image from an instance',
args: {
machine: {
type: new GraphQLNonNull(GraphQLID),
description: 'The prepared and stopped instance UUID from which the image is to be created'
},
name: {
type: new GraphQLNonNull(GraphQLString),
description: 'The name of the custom image, e.g. "my-image". Maximum 512 characters. However, typical names should be much shorter, e.g. 5-20 characters'
},
version: {
type: new GraphQLNonNull(GraphQLString),
description: 'The version of the custom image, e.g. "1.0.0". Maximum 128 characters'
},
description: {
type: GraphQLString,
description: 'A short prose description of this image. Maximum 512 characters'
},
homepage: {
type: GraphQLString,
description: 'Homepage URL where users can find more information about the image. Maximum 128 characters'
},
eula: {
type: GraphQLString,
description: 'URL of the End User License Agreement (EULA) for the image. Maximum 128 characters'
},
acl: {
type: new GraphQLList(GraphQLID),
description: 'An array of user/account UUIDs to which to give read access to a private image. I.e. this is only relevant for images with public === false'
},
tags: {
type: DynamicObjectType,
description: 'An object of key/value pairs that allows clients to categorize images by any given criteria'
}
},
resolve: (root, args) => {
const { create } = api.images;
return create(args);
}
};

View File

@ -1,16 +0,0 @@
const { GraphQLObjectType } = require('graphql');
module.exports = new GraphQLObjectType({
name: 'RootMutationType',
fields: Object.assign(
require('./account'),
require('./keys'),
require('./users'),
require('./roles'),
require('./policies'),
require('./machines'),
require('./images'),
require('./firewall-rules'),
require('./snapshots')
)
});

View File

@ -1,49 +0,0 @@
const KeyType = require('../types/key');
const api = require('../../api');
const { GraphQLNonNull, GraphQLString, GraphQLID } = require('graphql');
module.exports.createKey = {
type: KeyType,
description: 'Uploads a new OpenSSH key to Triton for use in HTTP signing and SSH',
args: {
name: {
type: new GraphQLNonNull(GraphQLString)
},
key: {
type: new GraphQLNonNull(GraphQLString)
},
userId: {
type: GraphQLID,
description: 'UserId to add this key to. Leaving this in blank will add the key to the account'
}
},
resolve: (root, args) => {
const _api = args.userId ? api.keys.user : api.keys.account;
return _api.create(args);
}
};
module.exports.deleteKey = {
type: GraphQLID,
description: 'Deletes a single SSH key, by name or fingerprint',
args: {
name: {
type: GraphQLString
},
fingerprint: {
type: GraphQLString
},
userId: {
type: GraphQLID,
description: 'UserId who this key belongs to. Leaving this in blank will delete an account key'
}
},
resolve: (root, args) => {
const _api = args.userId ? api.keys.user : api.keys.account;
return _api.destroy(args).then(() => {
return args.name || args.fingerprint;
});
}
};

View File

@ -1,320 +0,0 @@
const MachineType = require('../types/machine');
const DynamicObjectType = require('../types/dynamic-object');
const api = require('../../api');
const {
GraphQLNonNull,
GraphQLString,
GraphQLBoolean,
GraphQLID,
GraphQLList
} = require('graphql');
module.exports.createMachine = {
type: MachineType,
description: 'Allows you to provision an instance',
args: {
name: {
type: GraphQLString,
description: 'Friendly name for this instance; default is the first 8 characters of the machine id'
},
package: {
type: new GraphQLNonNull(GraphQLString),
description: 'Id of the package to use on provisioning, obtained from ListPackages'
},
image: {
type: new GraphQLNonNull(GraphQLString),
description: 'The image UUID (from images { id })'
},
networks: {
type: new GraphQLList(GraphQLString),
description: 'Desired networks ids (from networks { id })'
},
locality: {
type: MachineType.locality,
description: 'Optionally specify which instances the new instance should be near or far from'
},
metadata: {
type: DynamicObjectType,
description: 'An arbitrary set of metadata key/value pairs can be set at provision time'
},
tags: {
type: DynamicObjectType,
description: 'An arbitrary set of tags can be set at provision time'
},
firewall_enabled: {
type: GraphQLBoolean,
description: 'Completely enable or disable firewall for this instance. Default is false'
}
},
resolve: (root, args) => {
const resolveNames = (obj = {}, namespace) => {
return Object.keys(obj).reduce((all, name) => {
return Object.assign(all, {
[`${namespace}.${name}`]: obj[name]
});
}, {});
};
const tags = resolveNames(args.tags, 'tag');
const metadata = resolveNames(args.tags, 'metadata');
const machine = Object.assign(
{
name: args.name,
package: args['package'],
image: args.image,
networks: args.networks,
locality: args.locality,
firewall_enabled: args.firewall_enabled
},
tags,
metadata
);
return api.machines.create(machine);
}
};
module.exports.startMachine = {
type: MachineType,
description: 'Allows you to boot up an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
return api.machines.start(args.id).then(machine => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.startMachineFromSnapshot = {
type: MachineType,
description: 'If an instance is in the "stopped" state, you can choose to start the instance from the referenced snapshot',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
name: {
type: new GraphQLNonNull(GraphQLID),
description: 'The snapshot id'
}
},
resolve: (root, args) => {
return api.machines.startFromSnapshot(args).then(machine => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.stopMachine = {
type: MachineType,
description: 'Allows you to shut down an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
return api.machines.stop(args.id).then(machine => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.rebootMachine = {
type: MachineType,
description: 'Allows you to reboot an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
return api.machines.reboot(args.id).then(machine => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.deleteMachine = {
type: DynamicObjectType,
description: 'Allows you to completely destroy an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
return api.machines.destroy(args.id);
}
};
module.exports.auditMachine = {
type: new GraphQLList(DynamicObjectType),
description: "Provides a list of an instance's accomplished actions. Results are sorted from newest to oldest action",
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
return api.machines.destroy(args.id);
}
};
module.exports.setMachineFirewall = {
type: MachineType,
description: 'Allows you to set the firewall state for an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
enabled: {
type: new GraphQLNonNull(GraphQLBoolean)
}
},
resolve: (root, args) => {
const { firewall } = api.machines;
const fn = args.enabled ? firewall.enable : firewall.disable;
return fn(args.id).then(machine => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.enableMachineFirewall = {
type: MachineType,
description: 'Allows you to enable the firewall for an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
const { firewall } = api.machines;
return firewall.enable(args.id).then(machine => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.disableMachineFirewall = {
type: MachineType,
description: 'Allows you to completely disable the firewall of an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
const { firewall } = api.machines;
return firewall.disable(args.id).then(machine => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.addMachineTags = {
type: DynamicObjectType,
description: 'Set tags on the given instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
tags: {
type: new GraphQLNonNull(DynamicObjectType),
description: 'Tag name/value pairs'
}
},
resolve: (root, args) => {
const { tags } = api.machines;
return tags.add(args);
}
};
module.exports.replaceMachineTags = {
type: DynamicObjectType,
description: 'Fully replace all tags on an instance with the given tags',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
tags: {
type: new GraphQLNonNull(DynamicObjectType),
description: 'Tag name/value pairs'
}
},
resolve: (root, args) => {
const { tags } = api.machines;
return tags.replace(args);
}
};
module.exports.deleteMachineTags = {
type: DynamicObjectType,
description: 'Deletes tags from an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
tag: {
type: GraphQLString,
description: 'Tag name to remove. If value is not supplied, all machine tags are removed'
}
},
resolve: (root, args) => {
const { tags } = api.machines;
return tags.destroy(args);
}
};

View File

@ -1,71 +0,0 @@
const PolicyType = require('../types/policy');
const api = require('../../api');
const {
GraphQLNonNull,
GraphQLString,
GraphQLID,
GraphQLList
} = require('graphql');
module.exports.createPolicy = {
type: PolicyType,
description: 'Creates a new account policy',
args: {
name: {
type: new GraphQLNonNull(GraphQLString),
description: 'The policy name'
},
rules: {
type: new GraphQLNonNull(new GraphQLList(GraphQLString)),
description: 'One or more Aperture sentences to be added to the current policy'
},
description: {
type: GraphQLString,
description: 'A description for this policy (Optional)'
}
},
resolve: (root, args) => {
return api.policies.create(args);
}
};
module.exports.updatePolicy = {
type: PolicyType,
description: 'Upgrades an existing account policy. Everything but id can be modified',
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
},
name: {
type: new GraphQLNonNull(GraphQLString),
description: 'The policy name'
},
rules: {
type: new GraphQLNonNull(new GraphQLList(GraphQLString)),
description: 'One or more Aperture sentences to be added to the current policy'
},
description: {
type: GraphQLString,
description: 'A description for this policy (Optional)'
}
},
resolve: (root, args) => {
return api.policies.update(args);
}
};
module.exports.deletePolicy = {
type: GraphQLID,
description: 'Delete an RBAC policy',
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolve: (root, args) => {
return api.policies.destroy(args).then(() => {
return args.id;
});
}
};

View File

@ -1,103 +0,0 @@
const RoleType = require('../types/role');
const api = require('../../api');
const {
GraphQLNonNull,
GraphQLString,
GraphQLID,
GraphQLList
} = require('graphql');
module.exports.createRole = {
type: RoleType,
description: 'Create a new role for your account',
args: {
name: {
type: new GraphQLNonNull(GraphQLString),
description: "The role's name"
},
policies: {
type: new GraphQLList(GraphQLString),
description: "This account's policies to be given to this role (Optional)"
},
members: {
type: new GraphQLList(GraphQLString),
description: "This account's user logins to be added to this role (Optional)"
},
default_members: {
type: new GraphQLList(GraphQLString),
description: "This account's user logins to be added to this role and have it enabled by default (Optional)"
}
},
resolve: (root, args) => {
return api.roles.create(args);
}
};
module.exports.updateRole = {
type: RoleType,
description: 'Modifies an account role. Anything but id can be modified',
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
},
name: {
type: GraphQLString,
description: "The role's name"
},
policies: {
type: new GraphQLList(GraphQLString),
description: "This account's policies to be given to this role (Optional)"
},
members: {
type: new GraphQLList(GraphQLString),
description: "This account's user logins to be added to this role (Optional)"
},
default_members: {
type: new GraphQLList(GraphQLString),
description: "This account's user logins to be added to this role and have it enabled by default (Optional)"
}
},
resolve: (root, args) => {
return api.roles.update(args);
}
};
module.exports.deleteRole = {
type: GraphQLID,
description: 'Remove a role',
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolve: (root, args) => {
return api.roles.destroy(args).then(() => {
return args.id;
});
}
};
module.exports.setRoleTags = {
type: RoleType.tag,
description: "Sets the given role tags to the provided resource path. resource_path can be the path to any of the CloudAPI resources described in this document: account, keys, users, roles, policies, user's ssh keys, datacenters, images, packages, instances, analytics, instrumentations, firewall rules and networks.",
args: {
resource: {
type: new GraphQLNonNull(GraphQLString),
description: 'The resource type e.g. `machines`, `policies`...'
},
id: {
type: GraphQLID,
description: 'The resource id'
},
role: {
type: new GraphQLNonNull(new GraphQLList(GraphQLString)),
description: 'The list role-tags to be added to this resource'
}
},
resolve: (root, args) => {
const { set } = api.roles;
return set(args);
}
};

View File

@ -1,60 +0,0 @@
const SnapshotType = require('../types/snapshot');
const api = require('../../api');
const { GraphQLNonNull, GraphQLString, GraphQLID } = require('graphql');
module.exports.createSnapshot = {
type: SnapshotType,
description: 'Allows you to take a snapshot of a machine instance',
args: {
machine: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
name: {
type: GraphQLString,
description: 'The name to assign to the new snapshot'
}
},
resolve: (root, args) => {
const { snapshot: { create, get } } = api.machines;
const newArgs = {
id: args.machine,
name: args.name
};
return create(newArgs).then(snapshot => {
if (snapshot) {
return snapshot;
}
return get(newArgs);
});
}
};
module.exports.deleteSnapshot = {
type: GraphQLID,
description: 'Deletes the specified snapshot of an instance',
args: {
machine: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
name: {
type: GraphQLString,
description: 'The name to assign to the new snapshot'
}
},
resolve: (root, args) => {
const { snapshot: { destroy } } = api.machines;
const newArgs = {
id: args.machine,
name: args.name
};
return destroy(newArgs).then(() => args.name);
}
};

View File

@ -1,144 +0,0 @@
const UserType = require('../types/login');
const api = require('../../api');
const { GraphQLNonNull, GraphQLString, GraphQLID } = require('graphql');
module.exports.createUser = {
type: UserType,
description: 'Creates a new user under an account',
args: {
login: {
type: new GraphQLNonNull(GraphQLString)
},
email: {
type: new GraphQLNonNull(GraphQLString)
},
password: {
type: new GraphQLNonNull(GraphQLString)
},
company_name: {
type: GraphQLString
},
first_name: {
type: GraphQLString
},
last_name: {
type: GraphQLString
},
address: {
type: GraphQLString
},
postal_code: {
type: GraphQLString
},
city: {
type: GraphQLString
},
state: {
type: GraphQLString
},
country: {
type: GraphQLString
},
phone: {
type: GraphQLString
}
},
resolve: (root, args) => {
return api.users.create(
Object.assign(args, {
firstName: args.first_name,
lastName: args.first_name,
companyName: args.company_name,
postalCode: args.postal_code
})
);
}
};
module.exports.deleteUser = {
type: GraphQLID,
description: 'Remove a user',
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolve: (root, args) => {
return api.users.destroy(args).then(() => {
return args.id;
});
}
};
module.exports.updateUser = {
type: UserType,
description: "Update a user's modifiable properties",
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
},
login: {
type: GraphQLString
},
email: {
type: GraphQLString
},
company_name: {
type: GraphQLString
},
first_name: {
type: GraphQLString
},
last_name: {
type: GraphQLString
},
address: {
type: GraphQLString
},
postal_code: {
type: GraphQLString
},
city: {
type: GraphQLString
},
state: {
type: GraphQLString
},
country: {
type: GraphQLString
},
phone: {
type: GraphQLString
}
},
resolve: (root, args) => {
return api.users.update(
Object.assign(args, {
firstName: args.first_name,
lastName: args.first_name,
companyName: args.company_name,
postalCode: args.postal_code
})
);
}
};
// module.exports.changeUserPassword = {
// type: UserType,
// description: 'This is a separate rule for password changes, so different policies can be used for an user trying to modify other data, or only their own password',
// args: {
// id: {
// type: new GraphQLNonNull(GraphQLID)
// },
// password: {
// type: GraphQLString
// },
// password_confirmation: {
// type: GraphQLString
// }
// },
// resolve: (root, args) => {
// return api.users.updatePassword(args);
// }
// };

View File

@ -1,13 +0,0 @@
const AccountType = require('../types/login');
const api = require('../../api');
module.exports = {
type: AccountType,
resolve() {
return api.account.get().then(account => {
return Object.assign(account, {
isUser: false
});
});
}
};

View File

@ -1,19 +0,0 @@
const DatacenterType = require('../types/datacenter');
const graphql = require('graphql');
const api = require('../../api');
const { GraphQLList } = graphql;
module.exports = {
type: new GraphQLList(DatacenterType),
resolve() {
return api.datacenters().then(datacenters => {
return Object.keys(datacenters).map(name => {
return {
url: datacenters[name],
name
};
});
});
}
};

View File

@ -1,12 +0,0 @@
const FabricType = require('../types/fabrics');
const graphql = require('graphql');
const api = require('../../api');
const { GraphQLList } = graphql;
module.exports = {
type: new GraphQLList(FabricType),
resolve() {
return api.fabrics.list();
}
};

View File

@ -1,20 +0,0 @@
const FirewallRuleType = require('../types/firewall-rule');
const graphql = require('graphql');
const api = require('../../api');
const { GraphQLList, GraphQLID } = graphql;
module.exports = {
type: new GraphQLList(FirewallRuleType),
args: {
id: {
type: GraphQLID,
description: 'Filter on id'
}
},
resolve(root, args) {
const { list, get } = api.firewallRules;
return !args.id ? list() : get(args.id).then(rule => [rule]);
}
};

View File

@ -1,52 +0,0 @@
const ImageType = require('../types/image');
const graphql = require('graphql');
const api = require('../../api');
const { GraphQLList, GraphQLBoolean, GraphQLString, GraphQLID } = graphql;
module.exports = {
type: new GraphQLList(ImageType),
args: {
id: {
type: GraphQLID,
description: 'Filter on id'
},
name: {
type: GraphQLString,
description: 'Filter on "friendly" name'
},
os: {
type: GraphQLString,
description: 'Filter on the underlying operating system'
},
version: {
type: GraphQLString,
description: 'Filter on the version'
},
public: {
type: GraphQLBoolean,
description: 'Filter public/private images'
},
state: {
type: GraphQLString,
description: 'Filter on image state. By default only active images are shown. Use "all" to list all images'
},
owner: {
type: GraphQLString,
description: 'Filter on owner UUID'
},
type: {
type: GraphQLString,
description: 'Filter on image type'
}
},
resolve(root, args) {
const { list, get } = api.images;
return args.id
? get({
id: args.id
}).then(img => [img])
: list(args);
}
};

View File

@ -1,20 +0,0 @@
const { GraphQLObjectType } = require('graphql');
module.exports = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
account: require('./account'),
users: require('./users'),
policies: require('./policies'),
roles: require('./roles'),
datacenters: require('./datacenters'),
services: require('./services'),
images: require('./images'),
packages: require('./packages'),
machines: require('./machines'),
firewallRules: require('./firewall-rules'),
// fabrics: require('./fabrics')
networks: require('./networks')
// nics: require('./nics')
}
});

View File

@ -1,74 +0,0 @@
const MachineType = require('../types/machine');
const graphql = require('graphql');
const api = require('../../api');
const { GraphQLInt, GraphQLList, GraphQLString, GraphQLID } = graphql;
module.exports = {
type: new GraphQLList(MachineType),
args: {
id: {
type: GraphQLID
},
brand: {
type: GraphQLString,
description: 'Filter on the type of instance (e.g. lx)'
},
name: {
type: GraphQLString,
description: 'Machine name to find (will make your list size 1, or 0 if nothing found)'
},
image: {
type: GraphQLString,
description: 'Image id; returns instances provisioned with that image'
},
state: {
type: GraphQLString,
description: 'Filter on the current state (e.g. running)'
},
memory: {
type: GraphQLInt,
description: 'Filter on the current size of the RAM deployed (in MiB)'
},
tombstone: {
type: GraphQLInt,
description: 'Filter on instances destroyed in the last N minutes'
},
first: {
type: GraphQLInt,
description: 'Return a max of N instances; default is 1000 (which is also the maximum allowable result set size)'
},
after: {
type: GraphQLInt,
description: 'Get a `first` number of instances starting at this offset'
},
tags: {
type: new GraphQLList(GraphQLString),
description: 'Filter on existing tags'
},
docker: {
type: GraphQLString,
description: 'Whether to only list Docker instances, or only non-Docker instances, if present. Defaults to showing all instances.'
},
credentials: {
type: GraphQLString,
description: 'Whether to include the generated credentials for instances, if present. Defaults to false'
}
},
resolve(root, args) {
const { list, get } = api.machines;
const { after, first } = args;
const newArgs = Object.assign(args, {
limit: first,
offset: after
});
return args.id
? get({
id: args.id
}).then(machine => [machine])
: list(newArgs);
}
};

View File

@ -1,19 +0,0 @@
const NetworkType = require('../types/network');
const graphql = require('graphql');
const api = require('../../api');
const { GraphQLList, GraphQLID } = graphql;
module.exports = {
type: new GraphQLList(NetworkType),
args: {
id: {
type: GraphQLID
}
},
resolve(root, args) {
const { list, get } = api.networks;
return !args.id ? list() : get(args).then(network => [network]);
}
};

View File

@ -1,19 +0,0 @@
const NicType = require('../types/nic');
const graphql = require('graphql');
const api = require('../../api');
const { GraphQLList, GraphQLString } = graphql;
module.exports = {
type: new GraphQLList(NicType),
args: {
mac: {
type: GraphQLString
}
},
resolve(root, args) {
const { list, get } = api.nics;
return !args.id ? list() : get(args).then(nic => [nic]);
}
};

View File

@ -1,56 +0,0 @@
const PackageType = require('../types/package');
const graphql = require('graphql');
const api = require('../../api');
const { GraphQLInt, GraphQLList, GraphQLString, GraphQLID } = graphql;
module.exports = {
type: new GraphQLList(PackageType),
args: {
id: {
type: GraphQLID,
description: 'Filter on package id'
},
name: {
type: GraphQLString,
description: 'Filter on the "friendly" name'
},
memory: {
type: GraphQLInt,
description: 'Filter on how much memory will by available (in MiB)'
},
disk: {
type: GraphQLInt,
description: 'Filter on how much disk space will be available (in MiB)'
},
swap: {
type: GraphQLInt,
description: 'Filter on how much swap space will be available (in MiB)'
},
lwps: {
type: GraphQLInt,
description: 'Filter on maximum number of light-weight processes (threads) allowed'
},
vcpus: {
type: GraphQLInt,
description: 'Filter on number of vCPUs'
},
version: {
type: GraphQLString,
description: 'Filter on the version'
},
group: {
type: GraphQLString,
description: 'Filter on the group belonging to'
}
},
resolve(root, args) {
const { list, get } = api.packages;
return args.id
? get({
id: args.id
}).then(pkg => [pkg])
: list(args);
}
};

View File

@ -1,20 +0,0 @@
const PolicyType = require('../types/policy');
const graphql = require('graphql');
const api = require('../../api');
const { GraphQLList, GraphQLID } = graphql;
module.exports = {
type: new GraphQLList(PolicyType),
args: {
id: {
type: GraphQLID,
description: '`id` of the `PolicyType` to filter'
}
},
resolve(root, args) {
const { list, get } = api.policies;
return !args.id ? list() : get(args).then(policy => [policy]);
}
};

View File

@ -1,20 +0,0 @@
const RoleType = require('../types/role');
const graphql = require('graphql');
const api = require('../../api');
const { GraphQLList, GraphQLID } = graphql;
module.exports = {
type: new GraphQLList(RoleType),
args: {
id: {
type: GraphQLID,
description: '`id` or `name` of the `RoleType` to filter'
}
},
resolve(root, args) {
const { list, get } = api.roles;
return !args.id ? list() : get(args).then(role => [role]);
}
};

View File

@ -1,19 +0,0 @@
const ServiceType = require('../types/service');
const graphql = require('graphql');
const api = require('../../api');
const { GraphQLList } = graphql;
module.exports = {
type: new GraphQLList(ServiceType),
resolve() {
return api.services().then(services => {
return Object.keys(services).map(name => {
return {
url: services[name],
name
};
});
});
}
};

View File

@ -1,26 +0,0 @@
const UserType = require('../types/login');
const graphql = require('graphql');
const api = require('../../api');
const { GraphQLList, GraphQLID } = graphql;
module.exports = {
type: new GraphQLList(UserType),
args: {
id: {
type: GraphQLID,
description: '`id` or `login` of the `UserType` to filter'
}
},
resolve(root, args) {
const { list, get } = api.users;
return !args.id
? list()
: get(args).then(user => [user]).then(user => {
return Object.assign(user, {
isUser: true
});
});
}
};

View File

@ -1,54 +0,0 @@
const DynamicObjectType = require('./dynamic-object');
const { GraphQLString, GraphQLObjectType, GraphQLBoolean } = require('graphql');
const CallerType = new GraphQLObjectType({
name: 'CallerType',
fields: {
type: {
type: GraphQLString,
description: 'Authentication type for the action request. One of "basic", "operator", "signature" or "token"'
},
user: {
type: GraphQLString,
description: 'When the authentication type is "basic", this member will be present and include user login'
},
ip: {
type: GraphQLString,
description: 'The IP addresses this from which the action was requested. Not present if type is "operator"'
},
keyId: {
type: GraphQLString,
description: 'When authentication type is either "signature" or "token", SSH key identifier'
}
}
});
module.exports = new GraphQLObjectType({
name: 'AuditType',
fields: {
action: {
type: GraphQLString,
description: 'The name of the action'
},
parameters: {
type: DynamicObjectType,
description: 'The original set of parameters sent when the action was requested'
},
success: {
type: GraphQLBoolean,
description: "`true` or `false`, depending on the action's success",
resolve: root => {
return root.success === 'yes';
}
},
caller: {
type: CallerType,
description: 'Account requesting the action'
},
time: {
type: GraphQLString,
description: 'When the action finished'
}
}
});

View File

@ -1,14 +0,0 @@
const { GraphQLString, GraphQLObjectType } = require('graphql');
module.exports = new GraphQLObjectType({
name: 'DatacenterType',
fields: {
name: {
type: GraphQLString,
description: 'location of the datacenter'
},
url: {
type: GraphQLString
}
}
});

View File

@ -1,41 +0,0 @@
const { GraphQLScalarType, Kind } = require('graphql');
const kinds = {
[Kind.STRING]: ast => {
return ast.value;
},
[Kind.BOOLEAN]: ast => {
return kinds[Kind.STRING](ast);
},
[Kind.INT]: ast => {
return Number(ast.value);
},
[Kind.FLOAT]: ast => {
return kinds[Kind.INT](ast);
},
[Kind.OBJECT]: ast => {
const value = Object.create(null);
ast.fields.forEach(field => {
value[field.name.value] = parseLiteral(field.value);
});
return value;
},
[Kind.LIST]: ast => {
return ast.values.map(parseLiteral);
}
};
// https://github.com/taion/graphql-type-json/blob/master/src/index.js
const parseLiteral = ast => {
const kind = kinds[ast.kind];
return kind ? kinds[ast.kind](ast) : null;
};
// from http://stackoverflow.com/a/34229603
module.exports = new GraphQLScalarType({
name: 'DynamicObjectType',
serialize: v => v,
parseValue: v => v,
parseLiteral: parseLiteral
});

View File

@ -1,19 +0,0 @@
const { GraphQLString, GraphQLObjectType, GraphQLInt } = require('graphql');
module.exports = new GraphQLObjectType({
name: 'FabricsType',
fields: {
name: {
type: GraphQLString,
description: 'A unique name to identify the VLAN'
},
vlan_id: {
type: GraphQLInt,
description: "A number from 0-4095 that indicates the VLAN's id"
},
description: {
type: GraphQLString,
description: 'An optional description of the VLAN'
}
}
});

View File

@ -1,90 +0,0 @@
const api = require('../../api');
const {
GraphQLString,
GraphQLBoolean,
GraphQLObjectType,
GraphQLList,
GraphQLID,
GraphQLInt
} = require('graphql');
const FirewallRuleSyntaxType = new GraphQLObjectType({
name: 'FirewallRuleSyntaxType',
fields: {
text: {
type: GraphQLString
},
from: {
type: GraphQLString
},
to: {
type: GraphQLString
},
action: {
type: GraphQLString
},
protocol: {
type: GraphQLString
},
port: {
type: GraphQLInt
}
}
});
module.exports = new GraphQLObjectType({
name: 'FirewallRuleType',
// function to allow circular dependencies
fields: () => ({
id: {
type: GraphQLID,
description: 'Unique identifier for this rule'
},
enabled: {
type: GraphQLBoolean,
description: 'Indicates if the rule is enabled',
resolve: root => {
return !!root.enabled;
}
},
rule: {
type: FirewallRuleSyntaxType,
description: 'Firewall rule',
resolve: ({ rule }) => {
const regex = /from (.*?) to (.*?) (allow|deny) (.*?) port (\d*)/i;
const tokens = rule.match(regex);
return {
from: tokens[1],
to: tokens[2],
action: tokens[3],
protocol: tokens[4],
port: tokens[5],
text: rule
};
}
},
global: {
type: GraphQLBoolean,
description: 'Indicates if the rule is global',
resolve: root => {
return !!root.global;
}
},
description: {
type: GraphQLString,
description: 'Human-readable description for the rule'
},
machines: {
// circular dependency
type: new GraphQLList(require('./machine')),
description: 'Lists all instances a firewall rule is applied to',
resolve: root => {
return api.firewallRules.listMachines({
id: root.id
});
}
}
})
});

View File

@ -1,116 +0,0 @@
const DynamicObjectType = require('./dynamic-object');
const {
GraphQLBoolean,
GraphQLString,
GraphQLObjectType,
GraphQLInt,
GraphQLList,
GraphQLID
} = require('graphql');
const ErrorType = new GraphQLObjectType({
name: 'ErrorType',
fields: {
code: {
type: GraphQLString,
description: 'A CamelCase string code for this error, e.g. "PrepareImageDidNotRun". See GetImage docs for a table of error.code values'
},
message: {
type: GraphQLString,
description: 'A short description of the image creation failure'
}
}
});
const ImageFileType = new GraphQLObjectType({
name: 'ImageFileType',
fields: {
compression: {
type: GraphQLString,
description: 'The type of file compression used for the image file. One of "bzip2", "gzip", "none"'
},
sha1: {
type: GraphQLString,
description: 'SHA-1 hex digest of the file content. Used for corruption checking'
},
size: {
type: GraphQLInt,
description: 'File size in bytes'
}
}
});
module.exports = new GraphQLObjectType({
name: 'ImageType',
description: 'An image contains the software packages that will be available on newly-provisioned instance. In the case of hardware virtual machines, the image also includes the operating system',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this image'
},
name: {
type: GraphQLString,
description: 'The "friendly" name for this image'
},
os: {
type: GraphQLString,
description: 'The underlying operating system for this image'
},
version: {
type: GraphQLString,
description: 'The version for this image'
},
type: {
type: GraphQLString,
description: 'What kind of image this is. The values differ after v8.0.0+'
},
requirements: {
type: DynamicObjectType,
description: 'Contains a grouping of various minimum requirements for provisioning an instance with this image. For example "password" indicates that a password must be provided'
},
homepage: {
type: GraphQLString,
description: 'The URL for a web page with more detailed information for this image'
},
files: {
type: new GraphQLList(ImageFileType),
description: 'An array of image files that make up each image. Currently only a single file per image is supported'
},
published_at: {
type: GraphQLString,
description: 'The time this image has been made publicly available'
},
owner: {
type: GraphQLString,
description: 'The UUID of the user who owns this image'
},
public: {
type: GraphQLBoolean,
description: 'Indicates if this image is publicly available',
resolve: root => {
return !!root['public'];
}
},
state: {
type: GraphQLString,
description: 'The current state of the image. One of "active", "unactivated", "disabled", "creating", "failed"'
},
tags: {
type: DynamicObjectType,
description: 'An object of key/value pairs that allows clients to categorize images by any given criteria'
},
eula: {
type: GraphQLString,
description: 'URL of the End User License Agreement (EULA) for the image'
},
acl: {
type: new GraphQLList(GraphQLString),
description: 'Access Control List. An array of account UUIDs given access to a private image. The field is only relevant to private images'
},
error: {
type: ErrorType,
description: 'If state=="failed", resulting from CreateImageFromMachine failure, then there may be an error object of the form {"code": "<string error code>", "message": "<string desc>"}'
}
}
});

View File

@ -1,16 +0,0 @@
const { GraphQLString, GraphQLObjectType } = require('graphql');
module.exports = new GraphQLObjectType({
name: 'KeyType',
fields: {
name: {
type: GraphQLString
},
fingerprint: {
type: GraphQLString
},
key: {
type: GraphQLString
}
}
});

View File

@ -1,108 +0,0 @@
const KeyType = require('./key');
const api = require('../../api');
const {
GraphQLBoolean,
GraphQLString,
GraphQLList,
GraphQLObjectType,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'LoginType',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this user/account'
},
login: {
type: GraphQLString,
description: 'Account/Sub-user login name'
},
email: {
type: GraphQLString,
description: 'Email address'
},
company_name: {
type: GraphQLString,
resolve: root => {
return !!root.company_name || root.companyName;
}
},
first_name: {
type: GraphQLString,
resolve: root => {
return !!root.first_name || root.firstName;
}
},
last_name: {
type: GraphQLString,
resolve: root => {
return !!root.last_name || root.lastName;
}
},
address: {
type: GraphQLString
},
postal_code: {
type: GraphQLString,
resolve: root => {
return !!root.postal_code || root.postalCode;
}
},
city: {
type: GraphQLString
},
state: {
type: GraphQLString
},
country: {
type: GraphQLString
},
phone: {
type: GraphQLString
},
cns_enabled: {
type: GraphQLBoolean,
description: 'true if Triton CNS is enabled for account',
resolve: root => {
return root.isUser ? null : !!root.triton_cns_enabled;
}
},
keys: {
type: new GraphQLList(KeyType),
description: 'Get keys for user/account',
args: {
name: {
type: GraphQLString,
description: 'Filter on key name'
},
fingerprint: {
type: GraphQLString,
description: 'Filter on key fingerprint'
}
},
resolve(root, args) {
const _api = root.isUser ? api.keys.user : api.keys.account;
const { list, get } = _api;
const newArgs = Object.assign(args, {
userId: root.id
});
const filtered = args.name || args.fingerprint;
return !filtered ? list(newArgs) : get(newArgs).then(key => [key]);
}
},
updated: {
type: GraphQLString,
description: "When this user/account's details was last updated"
},
created: {
type: GraphQLString,
description: 'When this user/account was created'
}
}
});

View File

@ -1,162 +0,0 @@
const DynamicObjectType = require('./dynamic-object');
const SnapshotType = require('./snapshot');
const api = require('../../api');
const {
GraphQLBoolean,
GraphQLString,
GraphQLInputObjectType,
GraphQLObjectType,
GraphQLInt,
GraphQLList,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'MachineType',
description: 'An image contains the software packages that will be available on newly-provisioned instance. In the case of hardware virtual machines, the image also includes the operating system',
// function to allow circular dependencies
fields: () => ({
id: {
type: GraphQLID,
description: 'Unique id for this instance'
},
name: {
type: GraphQLString,
description: 'The "friendly" name for this instance'
},
brand: {
type: GraphQLString,
description: 'The type of instance (e.g. lx)'
},
state: {
type: GraphQLString,
description: 'The current state of this instance (e.g. running)'
},
image: {
type: GraphQLString,
description: 'The image id this instance was provisioned with'
},
memory: {
type: GraphQLInt,
description: 'The amount of RAM this instance has (in MiB)'
},
disk: {
type: GraphQLInt,
description: 'The amount of disk this instance has (in MiB)'
},
metadata: {
type: DynamicObjectType,
description: 'Any additional metadata this instance has'
},
tags: {
type: DynamicObjectType,
description: 'Any tags this instance has',
args: {
name: {
type: GraphQLString,
description: 'Filter on the name of the tag'
}
},
resolve: (root, args) => {
const { tags: { get } } = api.machines;
return !args.name
? root.tags
: get({
id: root.id,
tag: args.name
}).then(value => {
return {
[args.name]: value
};
});
}
},
created: {
type: GraphQLString,
description: 'When this instance was created'
},
updated: {
type: GraphQLString,
description: "When this instance's details was last updated"
},
docker: {
type: GraphQLBoolean,
description: 'Whether this instance is a Docker container, if present',
resolve: root => {
return !!root.docker;
}
},
ips: {
type: new GraphQLList(GraphQLString),
description: 'The IP addresses this instance has'
},
networks: {
type: new GraphQLList(GraphQLString),
description: 'The network UUIDs of the nics this instance has'
},
primaryIp: {
type: GraphQLString,
description: 'IP address of the primary nic of this instance'
},
firewall_enabled: {
type: GraphQLBoolean,
description: 'Whether firewall rules are enforced on this instance',
resolve: root => {
return !!root.firewall_enabled;
}
},
firewall_rules: {
// circular dependency
type: new GraphQLList(require('./firewall-rule')),
description: 'List of FirewallRules affecting this machine',
resolve: root => {
return api.firewallRules.listByMachine(root.id);
}
},
compute_node: {
type: GraphQLString,
description: 'UUID of the server on which the instance is located'
},
package: {
type: GraphQLString,
description: 'The id or name of the package used to create this instance'
},
snapshots: {
type: new GraphQLList(SnapshotType),
description: 'The snapshots based on this instance',
args: {
name: {
type: GraphQLString,
description: 'Filter on the name of the snapshot'
}
},
resolve: (root, args) => {
const { snapshot: { list, get } } = api.machines;
return !args.id
? list(root)
: get({
id: root.id,
name: args.name
});
}
}
})
});
module.exports.locality = new GraphQLInputObjectType({
name: 'LocalityType',
fields: {
strict: {
type: GraphQLBoolean
},
near: {
type: new GraphQLList(GraphQLID)
},
far: {
type: new GraphQLList(GraphQLID)
}
}
});

View File

@ -1,73 +0,0 @@
const DynamicObjectType = require('./dynamic-object');
const {
GraphQLBoolean,
GraphQLString,
GraphQLObjectType,
GraphQLList,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'NetworkType',
description: 'Logical networks in Triton model core network configurations to enable Triton to define Virtual Network Interfaces and IP addresses for instances',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this network'
},
name: {
type: GraphQLString,
description: 'The network name'
},
public: {
type: GraphQLBoolean,
description: 'Whether this a public or private (rfc1918) network',
resolve: root => {
return !!root['public'];
}
},
fabric: {
type: GraphQLBoolean,
description: 'Whether this network is created on a fabric',
resolve: root => {
return !!root.fabric;
}
},
description: {
type: GraphQLString,
description: 'Description of this network'
},
subnet: {
type: GraphQLString,
description: 'A CIDR formatted string that describes the network'
},
provision_start_ip: {
type: GraphQLString,
description: 'The first IP on the network that may be assigned'
},
provision_end_ip: {
type: GraphQLString,
description: 'The last IP on the network that may be assigned'
},
gateway: {
type: GraphQLString,
description: 'Optional Gateway IP address'
},
resolvers: {
type: new GraphQLList(GraphQLString),
description: 'Optional Resolver IP addresses'
},
routes: {
type: DynamicObjectType,
description: 'Optional Static routes for hosts on this network'
},
internet_nat: {
type: GraphQLBoolean,
description: 'Provision internet NAT zone on gateway address',
resolve: root => {
return !!root.internet_nat;
}
}
}
});

View File

@ -1,39 +0,0 @@
const { GraphQLBoolean, GraphQLObjectType, GraphQLString } = require('graphql');
module.exports = new GraphQLObjectType({
name: 'NicType',
description: 'Logical networks are used both on head nodes and compute nodes, and are associated with physical interfaces by using a system called NIC Tags',
fields: {
ip: {
type: GraphQLString,
description: "NIC's IPv4 address"
},
mac: {
type: GraphQLString,
description: "NIC's MAC address"
},
primary: {
type: GraphQLBoolean,
description: "Whether this is the instance's primary NIC",
resolve: root => {
return root.primary;
}
},
netmask: {
type: GraphQLString,
description: 'IPv4 netmask'
},
gateway: {
type: GraphQLString,
description: 'IPv4 gateway'
},
state: {
type: GraphQLString,
description: 'Describes the state of the NIC (e.g. provisioning, running, or stopped)'
},
network: {
type: GraphQLString,
description: "The NIC's network id (see ListNetworks)"
}
}
});

View File

@ -1,52 +0,0 @@
const {
GraphQLString,
GraphQLObjectType,
GraphQLInt,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'PackageType',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this package'
},
name: {
type: GraphQLString,
description: 'The "friendly" name for this package'
},
memory: {
type: GraphQLInt,
description: 'How much memory will by available (in MiB)'
},
disk: {
type: GraphQLInt,
description: 'How much disk space will be available (in MiB)'
},
swap: {
type: GraphQLInt,
description: 'How much swap space will be available (in MiB)'
},
lwps: {
type: GraphQLInt,
description: 'Maximum number of light-weight processes (threads) allowed'
},
vcpus: {
type: GraphQLInt,
description: 'Number of vCPUs for this package'
},
version: {
type: GraphQLString,
description: 'The version of this package'
},
group: {
type: GraphQLString,
description: 'The group this package belongs to'
},
description: {
type: GraphQLString,
description: 'A human-friendly description about this package'
}
}
});

View File

@ -1,29 +0,0 @@
const {
GraphQLString,
GraphQLObjectType,
GraphQLList,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'PolicyType',
description: 'Policies are lists of rules that describe access to resources',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this policy'
},
name: {
type: GraphQLString,
description: 'The policy name'
},
rules: {
type: new GraphQLList(GraphQLString),
description: 'One or more Aperture sentences applying to the policy'
},
description: {
type: GraphQLString,
description: 'A description for this policy'
}
}
});

View File

@ -1,50 +0,0 @@
const {
GraphQLString,
GraphQLObjectType,
GraphQLList,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'RoleType',
description: 'Roles are lists of users and policies. Roles describe which users are allowed access according to the policies',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this role'
},
name: {
type: GraphQLString,
description: 'The role name'
},
policies: {
type: new GraphQLList(GraphQLString),
description: "This account's policies which this role obeys (Optional)"
},
members: {
type: new GraphQLList(GraphQLString),
description: "This account's user logins this role applies to (Optional)"
},
default_members: {
type: new GraphQLList(GraphQLString),
description: "This account's user logins this role applies to by default (Optional)"
}
}
});
module.exports.tag = new GraphQLObjectType({
name: 'RoleTagType',
fields: {
name: {
type: GraphQLString,
description: 'Path to the resource'
},
role_tag: {
type: new GraphQLList(GraphQLString),
description: 'The role name',
resolve: root => {
return root['role-tag'] || root.role_tag;
}
}
}
});

View File

@ -1,13 +0,0 @@
const { GraphQLString, GraphQLObjectType } = require('graphql');
module.exports = new GraphQLObjectType({
name: 'ServiceType',
fields: {
name: {
type: GraphQLString
},
url: {
type: GraphQLString
}
}
});

View File

@ -1,16 +0,0 @@
const { GraphQLString, GraphQLObjectType, GraphQLID } = require('graphql');
module.exports = new GraphQLObjectType({
name: 'SnapshotType',
description: 'Policies are lists of rules that describe access to resources',
fields: {
name: {
type: GraphQLID,
description: 'The name of this snapshot'
},
state: {
type: GraphQLString,
description: 'The current state of the snapshot'
}
}
});

View File

@ -1,7 +0,0 @@
// TODO: REMOVE, JUST FOR AN EXAMPLE
const test = require('ava');
test('foo', t => {
t.pass();
});

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +0,0 @@
node_modules
.DS_Store
npm-debug.log
.eslintcache

View File

@ -1,7 +0,0 @@
# command-tower
## Usage
```bash
$ CMON_CERT_PATH=us-sw-1_api_joyent_com/cert.pem CMON_KEY_PATH=us-sw-1_api_joyent_com/key.pem control-tower
```

View File

@ -1,21 +0,0 @@
#!/usr/bin/env node
'use strict';
const Fs = require('fs');
const ControlTower = require('../');
const cert = process.env.CMON_CERT_PATH ? Fs.readFileSync(process.env.CMON_CERT_PATH) : process.env.CMON_CERT;
const key = process.env.CMON_KEY_PATH ? Fs.readFileSync(process.env.CMON_KEY_PATH) : process.env.CMON_KEY;
const datacenter = 'cmon.us-sw-1.triton.zone:9163';
const tower = new ControlTower({ cmon: { cert, key, datacenter } });
tower.start((err) => {
if (err) {
console.error(err);
process.exit(1);
}
console.log('Control Tower Started');
});

View File

@ -1,124 +0,0 @@
'use strict';
const CMonClient = require('cmon-client');
const PortalData = require('portal-data');
const VAsync = require('vasync');
module.exports = class {
constructor (options) {
options = options || {};
this._settings = options;
this._data = new PortalData(options.data);
this._cmon = new CMonClient(options.cmon);
this._deployments = {};
}
start (cb) {
this._data.connect((err) => {
if (err) {
return cb(err);
}
this._poll();
this._data.deploymentChanges((err, changes) => {
if (err) {
console.error(err);
}
if (changes) {
this._refreshContainers(changes.id);
}
});
});
}
_refreshContainers (deploymentId) {
this._data.getServices(deploymentId).then((services) => {
this._deployments[deploymentId] = services[0].containers;
});
}
_listContainers () {
let containers = [];
const deploymentIds = Object.keys(this._deployments);
deploymentIds.forEach((deploymentId) => {
containers = containers.concat(this._deployments[deploymentId]);
});
return containers;
}
_poll () {
if (this._isPolling) {
return;
}
const finish = () => {
this._isPolling = false;
setTimeout(() => { this._poll(); }, this._settings.frequency || 5000);
};
const containers = this._listContainers();
if (!containers || !containers.length) {
return finish();
}
this._isPolling = true;
VAsync.forEachParallel({
func: (containerId, next) => {
this._cmon.metrics(containerId, (err, metrics) => {
if (err) {
return next(err);
}
next(null, { containerId, metrics });
});
},
inputs: containers
}, (err, results) => {
if (err) {
console.error(err);
return finish();
}
if (!results.successes || !results.successes.length) {
return finish();
}
this._saveMetrics(results.successes, finish);
});
}
_saveMetrics (successes, cb) {
const metricOperations = successes.map((success) => {
const metrics = this._formatMetrics(success);
return this._data.insertMetrics(success.containerId, metrics);
});
Promise.all(metricOperations).then(() => {
cb();
}).catch((err) => {
cb(err);
});
}
_formatMetrics (success) {
const time = success.metrics.find((metric) => {
if (metric.name === 'time_of_day') {
return metric;
}
});
const formatted = success.metrics.map((metric) => {
return {
name: metric.name,
value: metric.metrics[0].value,
time: time.metrics[0].value
};
});
return formatted;
}
};

View File

@ -1,28 +0,0 @@
{
"name": "control-tower",
"version": "1.0.0",
"description": "portal service metrics watcher",
"main": "lib",
"bin": {
"control-tower": "./bin/control-tower"
},
"scripts": {
"lint": "belly-button",
"rethinkdb-up": "docker run -d -p 8080:8080 -p 28015:28015 -p 29015:29015 --name rethinkdb rethinkdb",
"rethinkdb-down": "docker rm -f rethinkdb",
"test": "npm run lint && lab"
},
"keywords": [],
"author": "wyatt",
"license": "MPL-2.0",
"devDependencies": {
"belly-button": "^3.1.0",
"code": "^4.0.0",
"lab": "^13.0.4"
},
"dependencies": {
"cmon-client": "^1.1.0",
"portal-data": "^1.0.0",
"vasync": "^1.6.4"
}
}

View File

@ -1,20 +0,0 @@
'use strict';
const Code = require('code');
const Lab = require('lab');
// Test shortcuts
const lab = exports.lab = Lab.script();
const describe = lab.describe;
const it = lab.it;
const expect = Code.expect;
describe('start()', () => {
it.skip('starts to listen for service changes and monitors metrics', (done) => {
expect(done).to.exist();
done();
});
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0e4cf6d271966e742c50cf6fbc27893e57f60007bcfc99c97f19e9a569abc421
size 8888320

View File

@ -1,23 +0,0 @@
{
"presets": [
["env", {
"spec": true,
"modules": false,
"targets": {
"browsers": ["last 2 versions", "safari >= 7"],
"node": 6
}
}]
],
"plugins": [
"babel-plugin-transform-flow-strip-types",
"external-helpers"
],
"env": {
"test": {
"plugins": [
"istanbul"
]
}
}
}

View File

@ -1,31 +0,0 @@
{
"parser": "babel-eslint",
"extends": [
"eslint:recommended",
"plugin:flowtype/recommended",
"xo-space/esnext",
"prettier",
"prettier/flowtype"
],
"plugins": [
"flowtype",
"flowtype-errors",
"prettier"
],
"rules": {
"prettier/prettier": ["error", {
"useTabs": false,
"printWidth": 80,
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"semi": true
}]
},
"env": {
"es6": true,
"node": true
}
}

View File

@ -1,13 +0,0 @@
[ignore]
.*/node_modules/.*
.*/dist/.*
.*/coverage/.*
.*/.nyc_output/.*
[include]
[libs]
flow-typed
./src/types.js
[options]

View File

@ -1,158 +0,0 @@
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var newArrowCheck = function (innerThis, boundThis) {
if (innerThis !== boundThis) {
throw new TypeError("Cannot instantiate an arrow function");
}
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var _require = require('zerorpc');
var Client = _require.Client;
var _require2 = require('events');
var EventEmitter = _require2.EventEmitter;
var awaitify = require('apr-awaitify');
var DockerComposeClient = function (_EventEmitter) {
inherits(DockerComposeClient, _EventEmitter);
function DockerComposeClient() {
var _this2 = this;
var endpoint = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'tcp://0.0.0.0:4242';
classCallCheck(this, DockerComposeClient);
var _this = possibleConstructorReturn(this, (DockerComposeClient.__proto__ || Object.getPrototypeOf(DockerComposeClient)).call(this));
_this.client = new Client({
heartbeatInterval: 60 * 4 * 1000, // 4m
timeout: 60 * 30 });
_this.client.connect(endpoint);
_this.client.on('error', function (err) {
newArrowCheck(this, _this2);
return _this.emit('error', err);
}.bind(this));
_this._invoke = awaitify(_this._invoke.bind(_this));
return _this;
}
// Why isn't client.connect async with error??
createClass(DockerComposeClient, [{
key: '_invoke',
value: function _invoke(name) {
var _client;
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
return (_client = this.client).invoke.apply(_client, [name].concat(args));
}
}, {
key: 'close',
value: function close() {
return this.client.close();
}
}, {
key: 'provision',
value: function provision(_ref) {
var projectName = _ref.projectName,
manifest = _ref.manifest;
// eslint-disable-next-line camelcase
return this._invoke('up', { project_name: projectName }, manifest);
}
}, {
key: 'scale',
value: function scale(_ref2) {
var _this3 = this;
var projectName = _ref2.projectName,
services = _ref2.services,
manifest = _ref2.manifest;
return this._invoke('scale', {
// eslint-disable-next-line camelcase
project_name: projectName,
services: Object.keys(services).map(function (name) {
newArrowCheck(this, _this3);
return {
name: name,
num: services[name]
};
}.bind(this))
}, manifest);
}
}]);
return DockerComposeClient;
}(EventEmitter);
module.exports = DockerComposeClient;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZXMuanMiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCB7IENsaWVudCB9ID0gcmVxdWlyZSgnemVyb3JwYycpO1xuY29uc3QgeyBFdmVudEVtaXR0ZXIgfSA9IHJlcXVpcmUoJ2V2ZW50cycpO1xuY29uc3QgYXdhaXRpZnkgPSByZXF1aXJlKCdhcHItYXdhaXRpZnknKTtcblxuY2xhc3MgRG9ja2VyQ29tcG9zZUNsaWVudCBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gIGNvbnN0cnVjdG9yKGVuZHBvaW50ID0gJ3RjcDovLzAuMC4wLjA6NDI0MicpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5jbGllbnQgPSBuZXcgQ2xpZW50KHtcbiAgICAgIGhlYXJ0YmVhdEludGVydmFsOiA2MCAqIDQgKiAxMDAwLCAvLyA0bVxuICAgICAgdGltZW91dDogNjAgKiAzMCwgLy8gMzBtXG4gICAgfSk7XG5cbiAgICB0aGlzLmNsaWVudC5jb25uZWN0KGVuZHBvaW50KTtcbiAgICB0aGlzLmNsaWVudC5vbignZXJyb3InLCBlcnIgPT4gdGhpcy5lbWl0KCdlcnJvcicsIGVycikpO1xuXG4gICAgdGhpcy5faW52b2tlID0gYXdhaXRpZnkodGhpcy5faW52b2tlLmJpbmQodGhpcykpO1xuICB9XG5cbiAgLy8gV2h5IGlzbid0IGNsaWVudC5jb25uZWN0IGFzeW5jIHdpdGggZXJyb3I/P1xuICBfaW52b2tlKG5hbWUsIC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gdGhpcy5jbGllbnQuaW52b2tlKG5hbWUsIC4uLmFyZ3MpO1xuICB9XG5cbiAgY2xvc2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2xpZW50LmNsb3NlKCk7XG4gIH1cblxuICBwcm92aXNpb24oeyBwcm9qZWN0TmFtZSwgbWFuaWZlc3QgfSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjYW1lbGNhc2VcbiAgICByZXR1cm4gdGhpcy5faW52b2tlKCd1cCcsIHsgcHJvamVjdF9uYW1lOiBwcm9qZWN0TmFtZSB9LCBtYW5pZmVzdCk7XG4gIH1cblxuICBzY2FsZSh7IHByb2plY3ROYW1lLCBzZXJ2aWNlcywgbWFuaWZlc3QgfSkge1xuICAgIHJldHVybiB0aGlzLl9pbnZva2UoXG4gICAgICAnc2NhbGUnLFxuICAgICAge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2FtZWxjYXNlXG4gICAgICAgIHByb2plY3RfbmFtZTogcHJvamVjdE5hbWUsXG4gICAgICAgIHNlcnZpY2VzOiBPYmplY3Qua2V5cyhzZXJ2aWNlcykubWFwKG5hbWUgPT4gKHtcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIG51bTogc2VydmljZXNbbmFtZV1cbiAgICAgICAgfSkpXG4gICAgICB9LFxuICAgICAgbWFuaWZlc3RcbiAgICApO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gRG9ja2VyQ29tcG9zZUNsaWVudDtcbiJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiQ2xpZW50IiwiRXZlbnRFbWl0dGVyIiwiYXdhaXRpZnkiLCJEb2NrZXJDb21wb3NlQ2xpZW50IiwiZW5kcG9pbnQiLCJjbGllbnQiLCJjb25uZWN0Iiwib24iLCJlbWl0IiwiZXJyIiwiX2ludm9rZSIsImJpbmQiLCJuYW1lIiwiYXJncyIsImludm9rZSIsImNsb3NlIiwicHJvamVjdE5hbWUiLCJtYW5pZmVzdCIsInByb2plY3RfbmFtZSIsInNlcnZpY2VzIiwiT2JqZWN0Iiwia2V5cyIsIm1hcCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7ZUFBbUJBLFFBQVEsU0FBUjtJQUFYQyxrQkFBQUE7O2dCQUNpQkQsUUFBUSxRQUFSO0lBQWpCRSx5QkFBQUE7O0FBQ1IsSUFBTUMsV0FBV0gsUUFBUSxjQUFSLENBQWpCOztJQUVNSTs7O2lDQUN5Qzs7O1FBQWpDQyxRQUFpQyx1RUFBdEIsb0JBQXNCOzs7OztVQUd0Q0MsTUFBTCxHQUFjLElBQUlMLE1BQUosQ0FBVzt5QkFDSixLQUFLLENBQUwsR0FBUyxJQURMO2VBRWQsS0FBSyxFQUZTLEVBQVgsQ0FBZDs7VUFLS0ssTUFBTCxDQUFZQyxPQUFaLENBQW9CRixRQUFwQjtVQUNLQyxNQUFMLENBQVlFLEVBQVosQ0FBZSxPQUFmLEVBQXdCOzthQUFPLE1BQUtDLElBQUwsQ0FBVSxPQUFWLEVBQW1CQyxHQUFuQixDQUFQO0tBQXhCOztVQUVLQyxPQUFMLEdBQWVSLFNBQVMsTUFBS1EsT0FBTCxDQUFhQyxJQUFiLE9BQVQsQ0FBZjs7Ozs7Ozs7OzRCQUlNQyxNQUFlOzs7d0NBQU5DLElBQU07WUFBQTs7O2FBQ2QsZ0JBQUtSLE1BQUwsRUFBWVMsTUFBWixpQkFBbUJGLElBQW5CLFNBQTRCQyxJQUE1QixFQUFQOzs7OzRCQUdNO2FBQ0MsS0FBS1IsTUFBTCxDQUFZVSxLQUFaLEVBQVA7Ozs7b0NBR21DO1VBQXpCQyxXQUF5QixRQUF6QkEsV0FBeUI7VUFBWkMsUUFBWSxRQUFaQSxRQUFZOzs7YUFFNUIsS0FBS1AsT0FBTCxDQUFhLElBQWIsRUFBbUIsRUFBRVEsY0FBY0YsV0FBaEIsRUFBbkIsRUFBa0RDLFFBQWxELENBQVA7Ozs7aUNBR3lDOzs7VUFBbkNELFdBQW1DLFNBQW5DQSxXQUFtQztVQUF0QkcsUUFBc0IsU0FBdEJBLFFBQXNCO1VBQVpGLFFBQVksU0FBWkEsUUFBWTs7YUFDbEMsS0FBS1AsT0FBTCxDQUNMLE9BREssRUFFTDs7c0JBRWdCTSxXQUZoQjtrQkFHWUksT0FBT0MsSUFBUCxDQUFZRixRQUFaLEVBQXNCRyxHQUF0QixDQUEwQjs7aUJBQVM7c0JBQUE7aUJBRXRDSCxTQUFTUCxJQUFUO1dBRjZCO1NBQTFCO09BTFAsRUFVTEssUUFWSyxDQUFQOzs7O0VBOUI4QmhCOztBQTZDbENzQixPQUFPQyxPQUFQLEdBQWlCckIsbUJBQWpCIn0=

View File

@ -1,166 +0,0 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
typeof define === 'function' && define.amd ? define(factory) :
(factory());
}(this, (function () { 'use strict';
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var newArrowCheck = function (innerThis, boundThis) {
if (innerThis !== boundThis) {
throw new TypeError("Cannot instantiate an arrow function");
}
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var _require = require('zerorpc');
var Client = _require.Client;
var _require2 = require('events');
var EventEmitter = _require2.EventEmitter;
var awaitify = require('apr-awaitify');
var DockerComposeClient = function (_EventEmitter) {
inherits(DockerComposeClient, _EventEmitter);
function DockerComposeClient() {
var _this2 = this;
var endpoint = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'tcp://0.0.0.0:4242';
classCallCheck(this, DockerComposeClient);
var _this = possibleConstructorReturn(this, (DockerComposeClient.__proto__ || Object.getPrototypeOf(DockerComposeClient)).call(this));
_this.client = new Client({
heartbeatInterval: 60 * 4 * 1000, // 4m
timeout: 60 * 30 });
_this.client.connect(endpoint);
_this.client.on('error', function (err) {
newArrowCheck(this, _this2);
return _this.emit('error', err);
}.bind(this));
_this._invoke = awaitify(_this._invoke.bind(_this));
return _this;
}
// Why isn't client.connect async with error??
createClass(DockerComposeClient, [{
key: '_invoke',
value: function _invoke(name) {
var _client;
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
return (_client = this.client).invoke.apply(_client, [name].concat(args));
}
}, {
key: 'close',
value: function close() {
return this.client.close();
}
}, {
key: 'provision',
value: function provision(_ref) {
var projectName = _ref.projectName,
manifest = _ref.manifest;
// eslint-disable-next-line camelcase
return this._invoke('up', { project_name: projectName }, manifest);
}
}, {
key: 'scale',
value: function scale(_ref2) {
var _this3 = this;
var projectName = _ref2.projectName,
services = _ref2.services,
manifest = _ref2.manifest;
return this._invoke('scale', {
// eslint-disable-next-line camelcase
project_name: projectName,
services: Object.keys(services).map(function (name) {
newArrowCheck(this, _this3);
return {
name: name,
num: services[name]
};
}.bind(this))
}, manifest);
}
}]);
return DockerComposeClient;
}(EventEmitter);
module.exports = DockerComposeClient;
})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXgudW1kLmpzIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXguanMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgeyBDbGllbnQgfSA9IHJlcXVpcmUoJ3plcm9ycGMnKTtcbmNvbnN0IHsgRXZlbnRFbWl0dGVyIH0gPSByZXF1aXJlKCdldmVudHMnKTtcbmNvbnN0IGF3YWl0aWZ5ID0gcmVxdWlyZSgnYXByLWF3YWl0aWZ5Jyk7XG5cbmNsYXNzIERvY2tlckNvbXBvc2VDbGllbnQgZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuICBjb25zdHJ1Y3RvcihlbmRwb2ludCA9ICd0Y3A6Ly8wLjAuMC4wOjQyNDInKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuY2xpZW50ID0gbmV3IENsaWVudCh7XG4gICAgICBoZWFydGJlYXRJbnRlcnZhbDogNjAgKiA0ICogMTAwMCwgLy8gNG1cbiAgICAgIHRpbWVvdXQ6IDYwICogMzAsIC8vIDMwbVxuICAgIH0pO1xuXG4gICAgdGhpcy5jbGllbnQuY29ubmVjdChlbmRwb2ludCk7XG4gICAgdGhpcy5jbGllbnQub24oJ2Vycm9yJywgZXJyID0+IHRoaXMuZW1pdCgnZXJyb3InLCBlcnIpKTtcblxuICAgIHRoaXMuX2ludm9rZSA9IGF3YWl0aWZ5KHRoaXMuX2ludm9rZS5iaW5kKHRoaXMpKTtcbiAgfVxuXG4gIC8vIFdoeSBpc24ndCBjbGllbnQuY29ubmVjdCBhc3luYyB3aXRoIGVycm9yPz9cbiAgX2ludm9rZShuYW1lLCAuLi5hcmdzKSB7XG4gICAgcmV0dXJuIHRoaXMuY2xpZW50Lmludm9rZShuYW1lLCAuLi5hcmdzKTtcbiAgfVxuXG4gIGNsb3NlKCkge1xuICAgIHJldHVybiB0aGlzLmNsaWVudC5jbG9zZSgpO1xuICB9XG5cbiAgcHJvdmlzaW9uKHsgcHJvamVjdE5hbWUsIG1hbmlmZXN0IH0pIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2FtZWxjYXNlXG4gICAgcmV0dXJuIHRoaXMuX2ludm9rZSgndXAnLCB7IHByb2plY3RfbmFtZTogcHJvamVjdE5hbWUgfSwgbWFuaWZlc3QpO1xuICB9XG5cbiAgc2NhbGUoeyBwcm9qZWN0TmFtZSwgc2VydmljZXMsIG1hbmlmZXN0IH0pIHtcbiAgICByZXR1cm4gdGhpcy5faW52b2tlKFxuICAgICAgJ3NjYWxlJyxcbiAgICAgIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNhbWVsY2FzZVxuICAgICAgICBwcm9qZWN0X25hbWU6IHByb2plY3ROYW1lLFxuICAgICAgICBzZXJ2aWNlczogT2JqZWN0LmtleXMoc2VydmljZXMpLm1hcChuYW1lID0+ICh7XG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgICBudW06IHNlcnZpY2VzW25hbWVdXG4gICAgICAgIH0pKVxuICAgICAgfSxcbiAgICAgIG1hbmlmZXN0XG4gICAgKTtcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IERvY2tlckNvbXBvc2VDbGllbnQ7XG4iXSwibmFtZXMiOlsicmVxdWlyZSIsIkNsaWVudCIsIkV2ZW50RW1pdHRlciIsImF3YWl0aWZ5IiwiRG9ja2VyQ29tcG9zZUNsaWVudCIsImVuZHBvaW50IiwiY2xpZW50IiwiY29ubmVjdCIsIm9uIiwiZW1pdCIsImVyciIsIl9pbnZva2UiLCJiaW5kIiwibmFtZSIsImFyZ3MiLCJpbnZva2UiLCJjbG9zZSIsInByb2plY3ROYW1lIiwibWFuaWZlc3QiLCJwcm9qZWN0X25hbWUiLCJzZXJ2aWNlcyIsIk9iamVjdCIsImtleXMiLCJtYXAiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O2VBQW1CQSxRQUFRLFNBQVI7SUFBWEMsa0JBQUFBOztnQkFDaUJELFFBQVEsUUFBUjtJQUFqQkUseUJBQUFBOztBQUNSLElBQU1DLFdBQVdILFFBQVEsY0FBUixDQUFqQjs7SUFFTUk7OztpQ0FDeUM7OztRQUFqQ0MsUUFBaUMsdUVBQXRCLG9CQUFzQjs7Ozs7VUFHdENDLE1BQUwsR0FBYyxJQUFJTCxNQUFKLENBQVc7eUJBQ0osS0FBSyxDQUFMLEdBQVMsSUFETDtlQUVkLEtBQUssRUFGUyxFQUFYLENBQWQ7O1VBS0tLLE1BQUwsQ0FBWUMsT0FBWixDQUFvQkYsUUFBcEI7VUFDS0MsTUFBTCxDQUFZRSxFQUFaLENBQWUsT0FBZixFQUF3Qjs7YUFBTyxNQUFLQyxJQUFMLENBQVUsT0FBVixFQUFtQkMsR0FBbkIsQ0FBUDtLQUF4Qjs7VUFFS0MsT0FBTCxHQUFlUixTQUFTLE1BQUtRLE9BQUwsQ0FBYUMsSUFBYixPQUFULENBQWY7Ozs7Ozs7Ozs0QkFJTUMsTUFBZTs7O3dDQUFOQyxJQUFNO1lBQUE7OzthQUNkLGdCQUFLUixNQUFMLEVBQVlTLE1BQVosaUJBQW1CRixJQUFuQixTQUE0QkMsSUFBNUIsRUFBUDs7Ozs0QkFHTTthQUNDLEtBQUtSLE1BQUwsQ0FBWVUsS0FBWixFQUFQOzs7O29DQUdtQztVQUF6QkMsV0FBeUIsUUFBekJBLFdBQXlCO1VBQVpDLFFBQVksUUFBWkEsUUFBWTs7O2FBRTVCLEtBQUtQLE9BQUwsQ0FBYSxJQUFiLEVBQW1CLEVBQUVRLGNBQWNGLFdBQWhCLEVBQW5CLEVBQWtEQyxRQUFsRCxDQUFQOzs7O2lDQUd5Qzs7O1VBQW5DRCxXQUFtQyxTQUFuQ0EsV0FBbUM7VUFBdEJHLFFBQXNCLFNBQXRCQSxRQUFzQjtVQUFaRixRQUFZLFNBQVpBLFFBQVk7O2FBQ2xDLEtBQUtQLE9BQUwsQ0FDTCxPQURLLEVBRUw7O3NCQUVnQk0sV0FGaEI7a0JBR1lJLE9BQU9DLElBQVAsQ0FBWUYsUUFBWixFQUFzQkcsR0FBdEIsQ0FBMEI7O2lCQUFTO3NCQUFBO2lCQUV0Q0gsU0FBU1AsSUFBVDtXQUY2QjtTQUExQjtPQUxQLEVBVUxLLFFBVkssQ0FBUDs7OztFQTlCOEJoQjs7QUE2Q2xDc0IsT0FBT0MsT0FBUCxHQUFpQnJCLG1CQUFqQjs7In0=

View File

@ -1,33 +0,0 @@
// flow-typed signature: c7a9c3b7f573e1b84f9080e5c09facb8
// flow-typed version: <<STUB>>/apr-awaitify_v^1.0.2/flow_v0.45.0
/**
* This is an autogenerated libdef stub for:
*
* 'apr-awaitify'
*
* Fill this stub out by replacing all the `any` types.
*
* Once filled out, we encourage you to share your work with the
* community by sending a pull request to:
* https://github.com/flowtype/flow-typed
*/
declare module 'apr-awaitify' {
declare module.exports: any;
}
/**
* We include stubs for each file inside this npm package in case you need to
* require those files directly. Feel free to delete any files that aren't
* needed.
*/
// Filename aliases
declare module 'apr-awaitify/index' {
declare module.exports: $Exports<'apr-awaitify'>;
}
declare module 'apr-awaitify/index.js' {
declare module.exports: $Exports<'apr-awaitify'>;
}

Some files were not shown because too many files have changed in this diff Show More