├── .gitignore ├── .gitmodules ├── .npmignore ├── CHANGES.md ├── LICENSE ├── Makefile ├── README.md ├── bin ├── sdc-addmachinetags ├── sdc-chmod ├── sdc-createfirewallrule ├── sdc-createimagefrommachine ├── sdc-createkey ├── sdc-createmachine ├── sdc-createmachinesnapshot ├── sdc-deletefirewallrule ├── sdc-deleteimage ├── sdc-deletekey ├── sdc-deletemachine ├── sdc-deletemachinemetadata ├── sdc-deletemachinesnapshot ├── sdc-deletemachinetag ├── sdc-disablefirewallrule ├── sdc-disablemachinefirewall ├── sdc-enablefirewallrule ├── sdc-enablemachinefirewall ├── sdc-exportimage ├── sdc-fabric ├── sdc-getaccount ├── sdc-getfirewallrule ├── sdc-getimage ├── sdc-getkey ├── sdc-getmachine ├── sdc-getmachineaudit ├── sdc-getmachinemetadata ├── sdc-getmachinesnapshot ├── sdc-getmachinetag ├── sdc-getnetwork ├── sdc-getpackage ├── sdc-info ├── sdc-listdatacenters ├── sdc-listfirewallrulemachines ├── sdc-listfirewallrules ├── sdc-listimages ├── sdc-listkeys ├── sdc-listmachinefirewallrules ├── sdc-listmachinemetadata ├── sdc-listmachines ├── sdc-listmachinesnapshots ├── sdc-listmachinetags ├── sdc-listnetworks ├── sdc-listpackages ├── sdc-nics ├── sdc-policy ├── sdc-rebootmachine ├── sdc-renamemachine ├── sdc-replacemachinetags ├── sdc-resizemachine ├── sdc-role ├── sdc-startmachine ├── sdc-startmachinefromsnapshot ├── sdc-stopmachine ├── sdc-updateaccount ├── sdc-updatefirewallrule ├── sdc-updateimage ├── sdc-updatemachinemetadata └── sdc-user ├── lib ├── cli │ ├── config.js │ ├── fabric-nets.js │ ├── fabric-vlans.js │ ├── index.js │ ├── paths.js │ └── validate.js ├── cli_common.js ├── cloudapi.js ├── flushingexit.js ├── index.js └── shared.js ├── package.json ├── test ├── .ssh │ ├── id_rsa │ ├── id_rsa.pub │ ├── test_id_rsa │ └── test_id_rsa.pub ├── api.test.js └── user.ldif └── tools ├── bashstyle ├── jsl.node.conf ├── jsl.web.conf ├── mk ├── Makefile.defs ├── Makefile.deps ├── Makefile.node.defs ├── Makefile.node.targ ├── Makefile.node_deps.defs ├── Makefile.node_deps.targ ├── Makefile.node_prebuilt.defs ├── Makefile.node_prebuilt.targ ├── Makefile.smf.defs ├── Makefile.smf.targ └── Makefile.targ └── service_bundle.dtd.1 /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps/jsstyle"] 2 | path = deps/jsstyle 3 | url = https://github.com/joyent/jsstyle.git 4 | [submodule "deps/javascriptlint"] 5 | path = deps/javascriptlint 6 | url = https://github.com/davepacheco/javascriptlint.git 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .gitmodules 2 | Makefile 3 | deps 4 | docs 5 | test 6 | smf 7 | tools 8 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | # node-smartdc Changelog 2 | 3 | ## 9.0.0 4 | 5 | - [Backwad incompatible] TRITON-884 - Drop support for Cloud Analytics. 6 | Cloud Analytics has been removed from Triton. See 7 | [TRITON-884](https://smartos.org/bugview/TRITON-884) for details. 8 | 9 | ## 8.1.0 10 | 11 | - PUBAPI-1219 - add --cns-enable and --cns-disable options to 12 | sdc-updateaccount, to enable and disable the Triton CNS. 13 | 14 | ## 8.0.2 15 | 16 | - PUBAPI-1215 - fix an API versioning problem with getting and listing 17 | images. This unintentionally caused a backwards-compatible-breaking 18 | change. The following attributes were being omitted, which this change 19 | brings back: owner, public, state, eula, acl, origin, error 20 | 21 | ## 8.0.1 22 | 23 | - PUBAPI-1214 updated `sshpk-agent` dependency, to fix some bad-state bugs that 24 | cause the ssh-agent support to malfunction under load. 25 | 26 | ## 8.0.0 27 | 28 | - [Backward incompatibility, PUBAPI-1161, PUBAPI-1180] All the node-smartdc 29 | `sdc-*` tools changed from using CloudAPI API version 7 to API version 8, by 30 | default. As well, support for the long deprecated API version 6.5 was dropped. 31 | 32 | To explicitly get the API version 7 behavior, either set the 33 | `SDC_API_VERSION=~7` environment variable or use the `--api-version=~7` 34 | option to `sdc-*` commands. E.g.: 35 | 36 | SDC_API_VERSION=~7 sdc-listmachines 37 | sdc-listimages --api-version=~7 --type=smartmachine 38 | 39 | See the CloudAPI [API Versions](https://apidocs.joyent.com/cloudapi/#api-versions) 40 | section for details. 41 | 42 | - `sdc-listmachines` filtering by `brand` is now supported. 43 | 44 | 45 | ## 7.6.2 46 | 47 | - PUBAPI-1166 use smartdc-auth and http-signature instead of sprintf for 48 | generating Authorization headers 49 | 50 | ## 7.6.1 51 | 52 | - #72 `sdc-fabric` doesn't honor command line flags. 53 | 54 | 55 | ## 7.6.0 56 | 57 | - #73 revive CHANGES.md changelog 58 | - #71 Fix data truncation (at 64k) from node-smartdc commands when piped to 59 | another command, when using node 4.1. E.g. `sdc-listimages | cat` would 60 | truncate. 61 | - #70 Update dep to get newer dtrace-provider to fix build against node 4.x 62 | 63 | 64 | ## 7.5.x 65 | 66 | - PUBAPI-1155, PUBAPI-1146: Updates to smartdc-auth@2.x to support `SDC_KEY_ID` 67 | being a fingerprint format other than the old `ssh-keygen` MD5 default. 68 | Recent `ssh-keygen` (e.g. as on Linuces for a while, and on Mac OS X El 69 | Capitan) changed the default fingerprint format from `ssh-keygen -l ...` to 70 | SHA1. 71 | - TOOLS-1214 Large number of keys in ssh-agent leads to failure. 72 | 73 | 74 | ## 7.4.0 75 | 76 | - TOOLS-1027 `sdc-fabric` support added. See 77 | . 78 | Implementation detail: `sdc-fabric` uses CloudAPI API version 7.3. Other 79 | commands continue to use API version 7.2 to function with older pre-fabrics 80 | CloudAPIs. 81 | 82 | 83 | ## 7.3.1 84 | 85 | - PUBAPI-1053: Bumped dependencies to work with node v0.12.0 86 | 87 | 88 | ## 7.3.0 89 | 90 | - PUBAPI-858: Updated to support RBAC. See 91 | . Account sub-users can use the 92 | CLI now. New commands include: sdc-chmod, sdc-info, sdc-policy, sdc-role, and 93 | sdc-user. 94 | 95 | 96 | ## 7.2.1 97 | 98 | - Add 'sdc-updateimage' for updating attributes on a custom image. 99 | 100 | - issue#49: Add '--version' to all `sdc-\*` CLI tools. 101 | 102 | 103 | ## 7.2.0 104 | 105 | - issue#43: Allow '-M|--metadata-file' option to `sdc-createmachine` and 106 | `sdc-updatemachinemetadata`. Accepts a parameter of the form `"key=filename"`. 107 | Example usage: 108 | 109 | $ sdc-updatemachinemetadata \ 110 | --metadata-file passwd_file=/etc/passwd \ 111 | ${uuid} 112 | 113 | ## 7.1.2 114 | 115 | - issue#47: Deprecated '-e|--dataset' option to `sdc-listmachines` and 116 | `sdc-createmachine` in favor of '-i|--image'. 117 | 118 | - issue#46: Fix '-d|--debug' option to actually include more logging. Example usage: 119 | 120 | sdc-listmachines -d 2>&1 | bunyan 121 | 122 | - Improve printing of errors on the CLI. E.g.: 123 | 124 | $ sdc-createmachine -e asdf 125 | sdc-createmachine: error (InvalidArgument): asdf is not a valid image 126 | 127 | Before: 128 | 129 | $ sdc-createmachine -e asdf 130 | asdf is not a valid image 131 | 132 | 133 | ## 7.1.0 134 | 135 | - [PUBAPI-660] Added `sdc-createimagefrommachine`, `sdc-deleteimage`, 136 | `sdc-updateimage`. 137 | 138 | - [PUBAPI-675] Allow filtering of `sdc-listimages` by `public`, `state` and 139 | `type`. 140 | 141 | - issue#34: Change `sdc-listimages` and `sdc-getimage` to use the appropriate 142 | `/:account/images` CloudAPI endpoints. 143 | 144 | 145 | ## 7.0.1 146 | 147 | - Added `sdc-enablemachinefirewall` and `sdc-disablemachinefirewall` 148 | - Added `-f | --enable-firewall` option to `sdc-createmachine` 149 | 150 | ## 7.0.0 151 | 152 | - Improved docs and usage strings 153 | 154 | ## 7.0.0-rc3 155 | 156 | - Added `sdc-listnetworks` and `sdc-getnetwork`. 157 | 158 | ## 7.0.0-rc2 159 | 160 | - Added "--networks|-w" argument to sdc-createmachine 161 | - Update README with upgrade section 162 | 163 | ## 7.0.0-rc1 164 | 165 | - New version to support SDC 7.0 new features. 166 | - Added `/images` resource 167 | - Added `/fwrules` resource 168 | - Added machine `/audit` 169 | - Added get/update account 170 | - Added tests for everything 171 | - Added token authentication 172 | - Removed the `_CLI_` part from SDC env vars 173 | - Removed basicAuth and `sdc-setup` due to PCI compliance 174 | - Retrieve all machines tagged when `tags=*` 175 | - Allow to upload DSA keys to Cloud API, but disallow using them with node-smartdc 176 | - `PUT /tags` to `ReplaceMachineTags` exposed. 177 | - Added Rename Machine 178 | - Short option `-?`, valid for all the `sdc-*` commands 179 | - Normalized arguments: when machine is required, is always last, not named, argument. 180 | - Handle `noCache` option for machine metadata/tags 181 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Joyent, Inc., All rights reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2013, Joyent, Inc. All rights reserved. 3 | # 4 | # Makefile: basic Makefile for template API service 5 | # 6 | # This Makefile is a template for new repos. It contains only repo-specific 7 | # logic and uses included makefiles to supply common targets (javascriptlint, 8 | # jsstyle, restdown, etc.), which are used by other repos as well. You may well 9 | # need to rewrite most of this file, but you shouldn't need to touch the 10 | # included makefiles. 11 | # 12 | # If you find yourself adding support for new targets that could be useful for 13 | # other projects too, you should add these to the original versions of the 14 | # included Makefiles (in eng.git) so that other teams can use them too. 15 | # 16 | 17 | # 18 | # Tools 19 | # 20 | TAP := ./node_modules/.bin/tape 21 | 22 | # 23 | # Files 24 | # 25 | JS_FILES := $(shell find lib test -name '*.js') $(shell find bin -name 'sdc-*') 26 | JSL_CONF_NODE = tools/jsl.node.conf 27 | JSL_FILES_NODE = $(JS_FILES) 28 | JSSTYLE_FILES = $(JS_FILES) 29 | JSSTYLE_FLAGS = -o indent=4,doxygen,unparenthesized-return=0 30 | 31 | include ./tools/mk/Makefile.defs 32 | 33 | .PHONY: all 34 | all $(TAP): 35 | npm install 36 | 37 | CLEAN_FILES += ./node_modules 38 | 39 | .PHONY: test 40 | test: $(TAP) 41 | TAP=1 $(TAP) test/*.test.js 42 | 43 | 44 | # Ensure all version-carrying files have the same version. 45 | .PHONY: check-version 46 | check-version: 47 | @[[ `cat package.json | json version` == `grep '^## ' CHANGES.md | head -1 | awk '{print $$2}'` ]] \ 48 | || (echo "check-version error: CHANGES.md top section version does not match package.json#version: $(shell cat package.json | json version)" && exit 2) 49 | @echo Version check ok. 50 | 51 | check:: check-version 52 | 53 | 54 | include ./tools/mk/Makefile.deps 55 | include ./tools/mk/Makefile.targ 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | node-smartdc is a node.js client library and set of CLI tools for using with 2 | the [Joyent SmartDataCenter API](http://apidocs.joyent.com/cloudapi/), for 3 | example the [Joyent Compute 4 | Service](http://www.joyent.com/products/compute-service). 5 | 6 | This repository is part of the Joyent Triton project. See the [contribution 7 | guidelines](https://github.com/joyent/triton/blob/master/CONTRIBUTING.md) 8 | and general documentation at the main 9 | [Triton project](https://github.com/joyent/triton) page. 10 | 11 | (Note: Current releases and the #master branch of this are for SmartDataCenter 12 | (SDC) version 7. It is not 100% backward compatible with SDC 6.5. For 100% 13 | compatility with SDC 6.5, you must install a "6.5.x" version of this module.) 14 | 15 | 16 | # Installation 17 | 18 | To use the CLI tools (a number of `sdc-*` commands) you may want to install 19 | globally: 20 | 21 | npm install -g smartdc 22 | 23 | The CLI commands typical work with JSON content. We suggest you also install 24 | the [`json` tool](https://github.com/trentm/json) for working with JSON on the 25 | command line. The examples below use `json` heavily. 26 | 27 | npm install -g json 28 | 29 | 30 | # CLI Setup and Authentication 31 | 32 | There are CLI commands corresponding to almost every action available in the 33 | SmartDataCenter API; see the [Joyent CloudAPI 34 | documentation](http://apidocs.joyent.com/cloudapi/) for complete information. 35 | Each command takes `--url`, `--account`, and `--keyId` flags to provide the 36 | API endpoint URL and your credentials. However you'll probably want to set 37 | the environment variable equivalents: 38 | 39 | * `SDC_URL` (`--url | -u`): URL of the CloudAPI endpoint. E.g. 40 | "https://us-east-1.api.joyent.com". 41 | * `SDC_ACCOUNT` (`--account | -a`): Login name/username. E.g. "bob". 42 | * `SDC_KEY_ID` (`--keyId | -k`): The fingerprint of an SSH public key that has 43 | been added to the account set in `SDC_ACCOUNT`. This is used for signing 44 | requests. If you use an SSH agent, the fingerprint is shown in `ssh-add -l` 45 | output. You can calculate the fingerprint like this: 46 | 47 | ssh-keygen -l -f ~/.ssh/id_rsa.pub | awk '{print $2}' | tr -d '\n' 48 | 49 | Your matching SSH *private* key must be beside the ".pub" public key file 50 | in your "~/.ssh" dir. 51 | 52 | If your client is connecting to a CloudAPI service that is using a self-signed 53 | SSL certificate, you may need to set `SDC_TESTING=1` in your client environent. 54 | (Otherwise you'll get `DEPTH_ZERO_SELF_SIGNED_CERT` error). 55 | 56 | ## Authenticating as account user 57 | 58 | Starting with version 7.3, [Role Based Access Control](https://docs.joyent.com/public-cloud/rbac) 59 | lets you provide limited access to to your Joyent Cloud account and Manta 60 | storage to other members of your organization. 61 | 62 | In order to authenticate as a member of a given organization, `SDC_ACCOUNT` 63 | will remain set to the login associated with the organization, and we'll use 64 | the `SDC_USER` environment variable to identify ourselves as a member of such 65 | organization. We can also use the `--A | --user` command line argument with 66 | any of the `sdc-*` commands if we just want to operate as an account user for 67 | just that command. 68 | 69 | Remember that if the environment variable `SDC_USER` is set, `sdc-*` binaries 70 | will remain trying to operate as the given user. If you've set this variable and 71 | want to switch back to operate as the account owner, you should 72 | `unset SDC_USER`. 73 | 74 | 75 | The SmartDataCenter Cloud API uses 76 | [http-signature](https://github.com/joyent/node-http-signature) ([IETF draft 77 | spec](http://tools.ietf.org/id/draft-cavage-http-signatures-00.txt)) for 78 | authentication. All requests to the API are signed using your RSA private key. 79 | The server uses your (previously uploaded) public key to verify the signed 80 | request. This avoids ever sending a password. 81 | 82 | Once you have set the environment variables, check that it is working by 83 | listing available images for provisioning: 84 | 85 | $ sdc-listimages 86 | [ 87 | { 88 | "id": "753ceee6-5372-11e3-8f4e-f79c1154e596", 89 | "name": "base", 90 | "version": "13.3.0", 91 | "os": "smartos", 92 | "requirements": {}, 93 | "type": "smartmachine", 94 | "description": "A 32-bit SmartOS image with just essential packages installed. Ideal for users who are comfortable with setting up their own environment and tools.", 95 | "owner": "9dce1460-0c4c-4417-ab8b-25ca478c5a78", 96 | "homepage": "http://wiki.joyent.com/jpc2/SmartMachine+Base", 97 | "published_at": "2013-11-22T12:34:40Z", 98 | "public": true, 99 | "state": "active" 100 | }, 101 | ... 102 | 103 | 104 | # CLI Usage 105 | 106 | There are many many `sdc-*` commands. Typically one for each endpoint in 107 | [the API](http://apidocs.joyent.com/cloudapi/). A common one is for provisioning 108 | a new machine (aka VM). Let's provision a new "base" (SmartOS) machine. First 109 | find the id of the "base" image (version 13.3.0): 110 | 111 | $ IMAGE=$(sdc-listimages | json -c 'this.name=="base" && this.version=="13.3.0"' 0.id) 112 | $ sdc-createmachine --image $IMAGE --name mymachine1 113 | $ sdc-getmachine f8f995da-086f-e8f5-c062-992139432c4f 114 | { 115 | "id": "f8f995da-086f-e8f5-c062-992139432c4f", 116 | "name": "mymachine1", 117 | "type": "smartmachine", 118 | "state": "provisioning", 119 | "image": "753ceee6-5372-11e3-8f4e-f79c1154e596", 120 | ... 121 | } 122 | 123 | Then you can poll until the state of the machine goes to "running": 124 | 125 | $ sdc-getmachine f8f995da-086f-e8f5-c062-992139432c4f | json state 126 | provisioning 127 | ... 128 | $ sdc-getmachine f8f995da-086f-e8f5-c062-992139432c4f | json state 129 | running 130 | 131 | At that point, you can ssh into the machine; try this: 132 | 133 | $ IP=$(sdc-getmachine f8f995da-086f-e8f5-c062-992139432c4f | json primaryIp) 134 | $ ssh root@$IP 135 | ... 136 | __ . . 137 | _| |_ | .-. . . .-. :--. |- 138 | |_ _| ;| || |(.-' | | | 139 | |__| `--' `-' `;-| `-' ' ' `-' 140 | / ; Instance (base 13.3.0) 141 | `-' http://wiki.joyent.com/jpc2/SmartMachine+Base 142 | 143 | [root@f8f995da-086f-e8f5-c062-992139432c4f ~]# 144 | 145 | 146 | Once you've played around and are done, you can delete this machine. 147 | 148 | $ sdc-deletemachine f8f995da-086f-e8f5-c062-992139432c4f 149 | ... 150 | $ sdc-getmachine f8f995da-086f-e8f5-c062-992139432c4f 151 | Object is Gone (410) 152 | 153 | There's a lot more you can do, like manage snapshots, keys, tags, 154 | etc. For the *Joyent* cloud, you can read more at . 155 | 156 | 157 | # Programmatic Usage 158 | 159 | var fs = require('fs'); 160 | var smartdc = require('smartdc'); 161 | 162 | var client = smartdc.createClient({ 163 | sign: smartdc.privateKeySigner({ 164 | key: fs.readFileSync(process.env.HOME + '/.ssh/id_rsa', 'utf8'), 165 | keyId: process.env.SDC_KEY_ID, 166 | user: process.env.SDC_ACCOUNT 167 | }), 168 | user: process.env.SDC_ACCOUNT, 169 | url: process.env.SDC_URL 170 | }); 171 | 172 | client.listMachines(function(err, machines) { 173 | if (err) { 174 | console.log('Unable to list machines: ' + err); 175 | return; 176 | } 177 | 178 | machines.forEach(function(m) { 179 | console.log('Machine: ' + JSON.stringify(m, null, 2)); 180 | }); 181 | }); 182 | 183 | 184 | 185 | # Upgrading from 6.5 to 7.0 186 | 187 | * The environment variables changed from 6.5 to 7 (the `CLI_` string was 188 | dropped): 189 | * `SDC_CLI_ACCOUNT` ==> `SDC_ACCOUNT` 190 | * `SDC_CLI_URL` ==> `SDC_URL` 191 | * `SDC_CLI_KEY_ID` ==> `SDC_KEY_ID` 192 | * The `SDC_CLI_IDENTITY` environment variable is no longer used. See above 193 | on how to determine your public key fingerprint for `SDC_KEY_ID`. 194 | * The `sdc-setup` command was removed. 195 | 196 | Note that in 6.5, `SDC_CLI_KEY_ID` was the *name* of the SSH key as specified in 197 | your Joyent Cloud account. In 7.0, `SDC_KEY_ID` is the *fingerprint* of your 198 | SSH public key. 199 | 200 | 201 | # License 202 | 203 | MIT. See the "LICENSE" file. 204 | 205 | 206 | # Development 207 | 208 | ## Contributing 209 | 210 | A few basic rules and guidelines: 211 | 212 | - Read the [Joyent Engineering Guidelines on tickets/issues and commit 213 | comments](https://github.com/joyent/eng/blob/master/docs/index.md#commit-comments-and-jira-tickets). 214 | List GitHub issues and/or Joyent JIRA tickets in commit messages and ensure 215 | thought processes are included in the issues or commit messages. 216 | 217 | - You typically want to bump the package.json version for all but trivial 218 | changes. 219 | 220 | - Update CHANGES.md (the change log) for any additions. 221 | 222 | - Run and pass `make check`. 223 | 224 | - Run and pass `make test` (caveat: I'm not sure it is passing *right now*.) 225 | Be aware that this module is meant to work with older node versions 226 | and on a number of platforms (smartos, linux, mac, windows). 227 | 228 | ## Bugs 229 | 230 | Please report issues to . 231 | 232 | 233 | ## Running the test suite 234 | 235 | Note that *this will run API calls against the SmartDataCenter setup per 236 | the `SDC_*` environment variables*. Please, make sure it is okay to try to 237 | create new machines using the configured DC and account before running the 238 | test suite. 239 | 240 | make test 241 | 242 | You may want to add a test user to your SDC setup. A sample user, with 243 | sample ssh keys can be found at `test/user.ldif` and `test/.ssh`. Once you've 244 | added this user, you can run your tests using: 245 | 246 | SDC_URL=http://127.0.0.1:8080 \ 247 | SDC_ACCOUNT=test \ 248 | SDC_KEY_ID=id_rsa \ 249 | HOME="$(pwd)/test" \ 250 | VERBOSE=1 \ 251 | make test 252 | -------------------------------------------------------------------------------- /bin/sdc-addmachinetags: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'tag': [String, Array], 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'd': ['--debug'], 31 | 'h': ['--help'], 32 | '?': ['--help'], 33 | 'k': ['--keyId'], 34 | 't': ['--tag'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options); 41 | usageStr += ' machine_id'; 42 | usageStr += common.buildDetailedUsageString(Options); 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | 48 | if (parsed.argv.remain.length < 1) { 49 | common.usage(usageStr, 1, 'machine required'); 50 | } 51 | 52 | if (!parsed.tag) { 53 | common.usage(usageStr, 1, '--tag required'); 54 | } 55 | 56 | var tags = common.parseMetadata(parsed.tag, false); 57 | 58 | var client = common.newClient(parsed); 59 | parsed.argv.remain.forEach(function (machine) { 60 | client.addMachineTags(machine, tags, common.callback); 61 | }); 62 | }, usageStr); 63 | -------------------------------------------------------------------------------- /bin/sdc-chmod: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2014 Joyent, Inc. All rights reserved. 5 | var util = require('util'); 6 | var path = require('path'); 7 | var fs = require('fs'); 8 | 9 | var bunyan = require('bunyan'); 10 | var vasync = require('vasync'); 11 | var smartdc = require('../lib/cloudapi'), 12 | CloudAPI = smartdc.CloudAPI; 13 | 14 | var shared = require('../lib/shared'), 15 | printErr = shared.printErr, 16 | DEFAULT_OPTIONS = shared.DEFAULT_OPTIONS; 17 | 18 | var cmdln = require('cmdln'), 19 | Cmdln = cmdln.Cmdln; 20 | var auth = require('smartdc-auth'); 21 | 22 | var pkg = require('../package.json'); 23 | var name = 'sdc'; 24 | var log = bunyan.createLogger({ 25 | name: name, 26 | serializers: bunyan.stdSerializers, 27 | stream: process.stderr, 28 | level: 'warn' 29 | }); 30 | 31 | 32 | 33 | var dashdash = require('dashdash'); 34 | 35 | var options = DEFAULT_OPTIONS; 36 | 37 | 38 | if (require.main === module) { 39 | 40 | var parser = dashdash.createParser({options: options}); 41 | 42 | try { 43 | var opts = parser.parse(process.argv); 44 | } catch (e) { 45 | console.error('sdc-chmod: error: %s', e.message); 46 | process.exit(1); 47 | } 48 | 49 | if (opts.debug) { 50 | process.env.DEBUG = 1; 51 | log.level('trace'); 52 | log.src = true; 53 | } 54 | 55 | // Use `parser.help()` for formatted options help. 56 | if (opts.help || !opts._args.length || opts._args[0] === 'help' || 57 | opts._args.length !== 2) { 58 | var help = parser.help({includeEnv: true}).trimRight(); 59 | shared.emit('Add role tags to SmartDC resources.\n\n' + 60 | 'Usage: sdc-chmod [OPTIONS] -- [+-=]role resource\n\n' + 61 | 'Role Tags: \n\n' + 62 | '+role: add the given role tag(s) to existing ones\n' + 63 | '-role: remove the given role tag(s) from existing ones\n' + 64 | '=role: set role tag to the given one(s)\n\n' + 65 | 'Options:\n' + help); 66 | shared.exit(0); 67 | } 68 | 69 | if (opts.version) { 70 | shared.emit('sdc-chmod', pkg.version); 71 | shared.exit(0); 72 | } 73 | 74 | if (typeof (opts.keyId) === 'undefined') { 75 | console.error('Either -k or (env) SDC_KEY_ID must be specified'); 76 | process.exit(1); 77 | } 78 | 79 | if (!opts.account) { 80 | console.error('Either -a or (env) SDC_ACCOUNT must be specified'); 81 | process.exit(1); 82 | } 83 | 84 | if (!opts.url) { 85 | console.error('Either -u or (env) SDC_URL must be specified'); 86 | process.exit(1); 87 | } 88 | 89 | opts.log = log; 90 | 91 | opts.sign = auth.cliSigner({ 92 | keyId: opts.keyId, 93 | user: opts.account, 94 | subuser: opts.user 95 | }); 96 | 97 | var resource = opts._args[1]; 98 | 99 | var reset = false; 100 | var resetTo = []; 101 | var toRemove = []; 102 | var toAppend = []; 103 | 104 | /* JSSTYLED */ 105 | var res = /^=(.*)$/.exec(opts._args[0]); 106 | if (res !== null) { 107 | reset = true; 108 | resetTo = res[1].split(','); 109 | } else { 110 | var app = /^\+(.*)$/.exec(opts._args[0]); 111 | if (app !== null) { 112 | toAppend = app[1].split(','); 113 | } else { 114 | var rem = /^-(.*)$/.exec(opts._args[0]); 115 | if (rem !== null) { 116 | toRemove = rem[1].split(','); 117 | } 118 | } 119 | } 120 | 121 | var cloudapi = new CloudAPI(opts); 122 | 123 | var funcs = []; 124 | var existing = []; 125 | if (!reset) { 126 | funcs.push(function _loadRoleTags(_, cb) { 127 | cloudapi.getRoleTags(resource, function (err, rt) { 128 | if (err) { 129 | return cb(err); 130 | } 131 | existing = rt; 132 | return cb(null); 133 | }); 134 | }); 135 | 136 | funcs.push(function _removeRoleTags(_, cb) { 137 | if (existing.length && toRemove.length) { 138 | existing = existing.filter(function (r) { 139 | return (toRemove.indexOf(r) === -1); 140 | }); 141 | } 142 | return cb(null); 143 | }); 144 | 145 | funcs.push(function _addRoleTags(_, cb) { 146 | if (toAppend.length) { 147 | existing = existing.concat(toAppend); 148 | } 149 | return cb(null); 150 | }); 151 | } else { 152 | funcs.push(function _setRoleTags(_, cb) { 153 | resetTo = resetTo.filter(function (r) { 154 | return (r.length !== 0); 155 | }); 156 | existing = resetTo; 157 | return cb(null); 158 | }); 159 | } 160 | 161 | funcs.push(function _putRoleTags(_, cb) { 162 | cloudapi.setRoleTags(resource, existing, function (err, obj) { 163 | if (err) { 164 | return cb(err); 165 | } 166 | existing = obj['role-tag']; 167 | return cb(null); 168 | }); 169 | }); 170 | 171 | vasync.pipeline({funcs: funcs}, function (er, _) { 172 | if (er) { 173 | printErr(er); 174 | process.exit(1); 175 | } 176 | shared.emit(JSON.stringify(existing)); 177 | shared.exit(0); 178 | }); 179 | 180 | } 181 | -------------------------------------------------------------------------------- /bin/sdc-createfirewallrule: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var fs = require('fs'); 7 | var url = require('url'); 8 | 9 | var common = require('../lib/cli_common'); 10 | 11 | 12 | 13 | // --- Globals 14 | 15 | var Options = { 16 | 'account': String, 17 | 'api-version': String, 18 | 'debug': Boolean, 19 | 'description': String, 20 | 'enabled': Boolean, 21 | 'help': Boolean, 22 | 'keyId': String, 23 | 'rule': String, 24 | 'url': url, 25 | 'version': Boolean, 26 | 'verbose': Boolean, 27 | 'user': String, 28 | 'role': String 29 | }; 30 | 31 | var ShortOptions = { 32 | 'a': ['--account'], 33 | 'd': ['--debug'], 34 | 'e': ['--enabled'], 35 | 'h': ['--help'], 36 | '?': ['--help'], 37 | 'k': ['--keyId'], 38 | 'r': ['--rule'], 39 | 'u': ['--url'], 40 | 'v': ['--verbose'], 41 | 'A': ['--user'] 42 | }; 43 | 44 | 45 | var usageStr = common.buildUsageString(Options); 46 | usageStr += common.buildDetailedUsageString(Options); 47 | 48 | // --- Mainline 49 | 50 | common.parseArguments(Options, ShortOptions, function (parsed) { 51 | 52 | var opts = {}; 53 | if (parsed.rule) { 54 | opts.rule = parsed.rule; 55 | } 56 | if (parsed.enabled) { 57 | opts.enabled = parsed.enabled; 58 | } 59 | if (parsed.description) { 60 | opts.description = parsed.description; 61 | } 62 | 63 | var client = common.newClient(parsed); 64 | client.createFwRule(opts, common.callback); 65 | }, usageStr); 66 | -------------------------------------------------------------------------------- /bin/sdc-createimagefrommachine: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var fs = require('fs'); 7 | var https = require('https'); 8 | var path = require('path'); 9 | var url = require('url'); 10 | 11 | var common = require('../lib/cli_common'); 12 | 13 | 14 | 15 | // --- Globals 16 | 17 | var Options = { 18 | // General 19 | 'account': String, 20 | 'api-version': String, 21 | 'debug': Boolean, 22 | 'help': Boolean, 23 | 'keyId': String, 24 | 'url': url, 25 | 'version': Boolean, 26 | 'verbose': Boolean, 27 | // Specific to this command 28 | 'machine': String, 29 | 'imageVersion': String, 30 | 'name': String, 31 | 'description': String, 32 | 'homepage': String, 33 | 'eula': String, 34 | 'acl': Array, 35 | 'tags': String, 36 | 'user': String, 37 | 'role': String 38 | }; 39 | 40 | var ShortOptions = { 41 | // General 42 | 'a': ['--account'], 43 | 'd': ['--debug'], 44 | 'h': ['--help'], 45 | '?': ['--help'], 46 | 'k': ['--keyId'], 47 | 'u': ['--url'], 48 | 'm': ['--machine'], 49 | 'i': ['--imageVersion'], 50 | 'n': ['--name'], 51 | 'v': ['--verbose'], 52 | 'A': ['--user'] 53 | }; 54 | 55 | var usageStr = common.buildUsageString(Options); 56 | usageStr += common.buildDetailedUsageString(Options, { 57 | machine: 'the ID of the machine from which the image is created (required)', 58 | imageVersion: 'the version string to use for the new image (required)', 59 | name: 'the name to use for the new image (required)', 60 | description: 'a description string for the new image', 61 | homepage: 'a homepage URL for the new image', 62 | eula: 'a EULA URL for the new image', 63 | acl: 'a user ID to which to grant access to the new image, can be ' 64 | + 'specified multiple times for multiple users', 65 | tags: 'a JSON object of tags for the new image, ' 66 | + 'e.g. --tags \'{"foo": "bar"}\'' 67 | }); 68 | 69 | 70 | // --- Mainline 71 | 72 | common.parseArguments(Options, ShortOptions, function (parsed) { 73 | var opts = {}; 74 | if (parsed.machine) 75 | opts.machine = parsed.machine; 76 | else 77 | common.usage(usageStr, 1, 'machine(id) required'); 78 | if (parsed.name) 79 | opts.name = parsed.name; 80 | else 81 | common.usage(usageStr, 1, 'name(string) required'); 82 | if (parsed.imageVersion) 83 | opts.version = parsed.imageVersion; 84 | else 85 | common.usage(usageStr, 1, 'imageVersion(string) required'); 86 | if (parsed.description) 87 | opts.description = parsed.description; 88 | if (parsed.homepage) 89 | opts.homepage = parsed.homepage; 90 | if (parsed.eula) 91 | opts.eula = parsed.eula; 92 | if (parsed.acl) 93 | opts.acl = parsed.acl; 94 | if (parsed.tags) 95 | opts.tags = JSON.parse(parsed.tags); 96 | 97 | var client = common.newClient(parsed); 98 | client.createImageFromMachine(opts, common.callback); 99 | }, usageStr); 100 | -------------------------------------------------------------------------------- /bin/sdc-createkey: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var fs = require('fs'); 7 | var url = require('url'); 8 | 9 | var common = require('../lib/cli_common'); 10 | 11 | 12 | 13 | // --- Globals 14 | 15 | var Options = { 16 | 'account': String, 17 | 'api-version': String, 18 | 'debug': Boolean, 19 | 'help': Boolean, 20 | 'keyId': String, 21 | 'name': String, 22 | 'url': url, 23 | 'version': Boolean, 24 | 'verbose': Boolean, 25 | 'user': String, 26 | 'role': String 27 | }; 28 | 29 | var ShortOptions = { 30 | 'a': ['--account'], 31 | 'd': ['--debug'], 32 | 'h': ['--help'], 33 | '?': ['--help'], 34 | 'k': ['--keyId'], 35 | 'n': ['--name'], 36 | 'u': ['--url'], 37 | 'v': ['--verbose'], 38 | 'A': ['--user'] 39 | }; 40 | 41 | var usageStr = common.buildUsageString(Options); 42 | usageStr += ' public_ssh_key'; 43 | usageStr += common.buildDetailedUsageString(Options); 44 | 45 | // --- Internal Functions 46 | 47 | function loadNewKey(key) { 48 | try { 49 | return fs.readFileSync(key, 'ascii'); 50 | } catch (e) { 51 | return common.usage(usageStr, 2, 52 | 'Unable to load key ' + key + ': ' + e); 53 | } 54 | } 55 | 56 | 57 | 58 | // --- Mainline 59 | 60 | common.parseArguments(Options, ShortOptions, function (parsed) { 61 | 62 | if (parsed.argv.remain.length < 1) { 63 | common.usage(usageStr, 1, 'ssh_key required'); 64 | } 65 | 66 | var opts = { 67 | key: loadNewKey(parsed.argv.remain[0]) 68 | }; 69 | if (parsed.name) { 70 | opts.name = parsed.name; 71 | } else { 72 | var name = parsed.argv.remain[0].split('/'); 73 | opts.name = name[name.length - 1]; 74 | } 75 | 76 | var client = common.newClient(parsed); 77 | client.createKey(opts, common.callback); 78 | }, usageStr); 79 | -------------------------------------------------------------------------------- /bin/sdc-createmachine: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var fs = require('fs'); 7 | var https = require('https'); 8 | var path = require('path'); 9 | var url = require('url'); 10 | 11 | var common = require('../lib/cli_common'); 12 | 13 | 14 | 15 | // --- Globals 16 | 17 | var Options = { 18 | 'account': String, 19 | 'api-version': String, 20 | 'debug': Boolean, 21 | 'image': String, 22 | 'enable-firewall': Boolean, 23 | 'far': String, 24 | 'help': Boolean, 25 | 'keyId': String, 26 | 'metadata': [String, Array], 27 | 'metadata-file': [String, Array], 28 | 'name': String, 29 | 'near': String, 30 | 'networks': [String, Array], 31 | 'package': String, 32 | 'script': path, 33 | 'strict-locality': Boolean, 34 | 'tag': [String, Array], 35 | 'url': url, 36 | 'version': Boolean, 37 | 'verbose': Boolean, 38 | 'user': String, 39 | 'role': String 40 | }; 41 | 42 | var ShortOptions = { 43 | 'a': ['--account'], 44 | 'd': ['--debug'], 45 | 'e': ['--image'], // DEPRECATED 46 | 'i': ['--image'], 47 | 'f': ['--enable-firewall'], 48 | 'h': ['--help'], 49 | '?': ['--help'], 50 | 'k': ['--keyId'], 51 | 'm': ['--metadata'], 52 | 'M': ['--metadata-file'], 53 | 'n': ['--name'], 54 | 'p': ['--package'], 55 | 's': ['--script'], 56 | 't': ['--tag'], 57 | 'u': ['--url'], 58 | 'v': ['--verbose'], 59 | 'w': ['--networks'], 60 | 'A': ['--user'] 61 | }; 62 | 63 | var usageStr = common.buildUsageString(Options); 64 | usageStr += common.buildDetailedUsageString(Options, { 65 | 'name': 'friendly name (may contain letters, numbers, dashes, and periods)' 66 | }); 67 | 68 | // --- Mainline 69 | 70 | common.parseArguments(Options, ShortOptions, function (parsed) { 71 | var opts = {}; 72 | var tmp; 73 | var k; 74 | if (parsed.image) { 75 | opts.image = parsed.image; 76 | } 77 | if (parsed.name) { 78 | opts.name = parsed.name; 79 | } 80 | if (parsed['package']) { 81 | opts['package'] = parsed['package']; 82 | } 83 | if (typeof (parsed['enable-firewall']) !== 'undefined') { 84 | opts.firewall_enabled = parsed['enable-firewall']; 85 | } 86 | 87 | if (parsed.tag) { 88 | tmp = common.parseMetadata(parsed.tag, false); 89 | for (k in tmp) { 90 | opts['tag.' + k] = tmp[k]; 91 | } 92 | } 93 | 94 | tmp = {}; 95 | if (parsed['metadata-file']) { 96 | tmp = common.mergeObjects(tmp, common.parseMetadata( 97 | parsed['metadata-file'], true)); 98 | } 99 | if (parsed['metadata']) { 100 | tmp = common.mergeObjects(tmp, common.parseMetadata( 101 | parsed['metadata'], false)); 102 | } 103 | for (k in tmp) { 104 | opts['metadata.' + k] = tmp[k]; 105 | } 106 | 107 | if (parsed.script) { 108 | var us = fs.readFileSync(parsed.script, 'utf-8'); 109 | opts['metadata.user-script'] = us.toString(); 110 | } 111 | 112 | if (parsed.networks) { 113 | opts.networks = parsed.networks; 114 | } 115 | 116 | if (parsed.near || parsed.far) { 117 | opts.locality = {}; 118 | 119 | if (parsed.near) { 120 | opts.locality.near = parsed.near.split(','); 121 | } 122 | 123 | if (parsed.far) { 124 | opts.locality.far = parsed.far.split(','); 125 | } 126 | 127 | if (parsed['strict-locality']) { 128 | opts.locality.strict = parsed['strict-locality']; 129 | } 130 | } 131 | 132 | var client = common.newClient(parsed); 133 | client.createMachine(opts, common.callback); 134 | }, usageStr); 135 | -------------------------------------------------------------------------------- /bin/sdc-createmachinesnapshot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'name': String, 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'd': ['--debug'], 31 | 'h': ['--help'], 32 | '?': ['--help'], 33 | 'k': ['--keyId'], 34 | 'n': ['--name'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options); 41 | usageStr += ' machine_id'; 42 | usageStr += common.buildDetailedUsageString(Options); 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | 48 | if (parsed.argv.remain.length < 1) { 49 | common.usage(usageStr, 1, 'machine required'); 50 | } 51 | 52 | var opts = {}; 53 | if (parsed.name) { 54 | opts.name = parsed.name; 55 | } 56 | 57 | var client = common.newClient(parsed); 58 | parsed.argv.remain.forEach(function (machine) { 59 | client.createMachineSnapshot(machine, opts, common.callback); 60 | }); 61 | }, usageStr); 62 | -------------------------------------------------------------------------------- /bin/sdc-deletefirewallrule: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options) + ' fwrule_id'; 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | // --- Mainline 42 | 43 | common.parseArguments(Options, ShortOptions, function (parsed) { 44 | if (parsed.argv.remain.length < 1) { 45 | common.usage(usageStr, 1, 'fwrule_id required'); 46 | } 47 | 48 | var client = common.newClient(parsed); 49 | parsed.argv.remain.forEach(function (fwrule) { 50 | client.deleteFwRule(fwrule, common.callback); 51 | }); 52 | }, usageStr); 53 | -------------------------------------------------------------------------------- /bin/sdc-deleteimage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += ' image_id'; 40 | usageStr += common.buildDetailedUsageString(Options); 41 | 42 | 43 | // --- Mainline 44 | 45 | common.parseArguments(Options, ShortOptions, function (parsed) { 46 | if (parsed.argv.remain.length === 0) { 47 | common.usage(usageStr, 1, 'image_id required'); 48 | } else if (parsed.argv.remain.length > 1) { 49 | common.usage(usageStr, 1, 'only a single image_id is supported'); 50 | } 51 | 52 | var client = common.newClient(parsed); 53 | var image_id = parsed.argv.remain[0]; 54 | client.deleteImage(image_id, common.callback); 55 | }, usageStr); 56 | -------------------------------------------------------------------------------- /bin/sdc-deletekey: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += ' key_name'; 40 | usageStr += common.buildDetailedUsageString(Options); 41 | 42 | 43 | // --- Mainline 44 | 45 | common.parseArguments(Options, ShortOptions, function (parsed) { 46 | if (parsed.argv.remain.length < 1) { 47 | common.usage(usageStr, 1, 'key_name required'); 48 | } 49 | 50 | var client = common.newClient(parsed); 51 | parsed.argv.remain.forEach(function (key) { 52 | client.deleteKey(key, common.callback); 53 | }); 54 | }, usageStr); 55 | -------------------------------------------------------------------------------- /bin/sdc-deletemachine: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += ' machine_id'; 40 | usageStr += common.buildDetailedUsageString(Options); 41 | 42 | // --- Mainline 43 | 44 | common.parseArguments(Options, ShortOptions, function (parsed) { 45 | if (parsed.argv.remain.length < 1) { 46 | common.usage(usageStr, 1, 'machine required'); 47 | } 48 | 49 | var client = common.newClient(parsed); 50 | parsed.argv.remain.forEach(function (machine) { 51 | client.deleteMachine(machine, common.callback); 52 | }); 53 | }, usageStr); 54 | -------------------------------------------------------------------------------- /bin/sdc-deletemachinemetadata: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'metadata': String, 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'd': ['--debug'], 31 | 'h': ['--help'], 32 | '?': ['--help'], 33 | 'k': ['--keyId'], 34 | 'm': ['--metadata'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options); 41 | usageStr += ' machine_id'; 42 | usageStr += common.buildDetailedUsageString(Options); 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | 48 | if (parsed.argv.remain.length < 1) { 49 | common.usage(usageStr, 1, 'machine required'); 50 | } 51 | 52 | if (!parsed.metadata) { 53 | common.usage(usageStr, 1, '--metadata required'); 54 | } 55 | 56 | var client = common.newClient(parsed); 57 | parsed.argv.remain.forEach(function (machine) { 58 | client.deleteMachineMetadata(machine, parsed.metadata, common.callback); 59 | }); 60 | }, usageStr); 61 | -------------------------------------------------------------------------------- /bin/sdc-deletemachinesnapshot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'snapshot': String, 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'd': ['--debug'], 31 | 'h': ['--help'], 32 | '?': ['--help'], 33 | 'k': ['--keyId'], 34 | 'n': ['--snapshot'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options) + ' machine_id'; 41 | usageStr += common.buildDetailedUsageString(Options); 42 | 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | if (!parsed.snapshot) { 48 | common.usage(usageStr, 1, '--snapshot required'); 49 | } 50 | if (parsed.argv.remain.length < 1) { 51 | common.usage(usageStr, 1, 'machine required'); 52 | } 53 | 54 | var client = common.newClient(parsed); 55 | 56 | parsed.argv.remain.forEach(function (machine) { 57 | client.deleteMachineSnapshot(machine, parsed.snapshot, common.callback); 58 | }); 59 | }, usageStr); 60 | -------------------------------------------------------------------------------- /bin/sdc-deletemachinetag: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'tag': String, 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'd': ['--debug'], 31 | 'h': ['--help'], 32 | '?': ['--help'], 33 | 'k': ['--keyId'], 34 | 't': ['--tag'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options) + ' machine_id'; 41 | usageStr += common.buildDetailedUsageString(Options); 42 | 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | if (!parsed.tag) { 48 | common.usage(usageStr, 1, 'tag required'); 49 | } 50 | if (parsed.argv.remain.length < 1) { 51 | common.usage(usageStr, 1, 'machine required'); 52 | } 53 | 54 | var client = common.newClient(parsed), 55 | machine = parsed.argv.remain[0]; 56 | 57 | if (parsed.tag === '*') { 58 | return client.deleteMachineTags(machine, common.callback); 59 | } else { 60 | return client.deleteMachineTag(machine, parsed.tag, common.callback); 61 | } 62 | }, usageStr); 63 | -------------------------------------------------------------------------------- /bin/sdc-disablefirewallrule: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options) + ' fwrule_id'; 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | // --- Mainline 42 | 43 | common.parseArguments(Options, ShortOptions, function (parsed) { 44 | if (parsed.argv.remain.length < 1) { 45 | common.usage(usageStr, 1, 'fwrule_id required'); 46 | } 47 | 48 | var client = common.newClient(parsed); 49 | parsed.argv.remain.forEach(function (fwrule) { 50 | client.disableFwRule(fwrule, common.callback); 51 | }); 52 | }, usageStr); 53 | -------------------------------------------------------------------------------- /bin/sdc-disablemachinefirewall: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += ' machine_id'; 40 | usageStr += common.buildDetailedUsageString(Options); 41 | 42 | 43 | // --- Mainline 44 | 45 | common.parseArguments(Options, ShortOptions, function (parsed) { 46 | if (parsed.argv.remain.length < 1) { 47 | common.usage(usageStr, 1, 'machine required'); 48 | } 49 | 50 | var client = common.newClient(parsed); 51 | parsed.argv.remain.forEach(function (machine) { 52 | client.disableFirewall(machine, common.callback); 53 | }); 54 | }, usageStr); 55 | -------------------------------------------------------------------------------- /bin/sdc-enablefirewallrule: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'u': ['--url'], 33 | 'v': ['--verbose'], 34 | 'A': ['--user'] 35 | }; 36 | 37 | var usageStr = common.buildUsageString(Options) + ' fwrule_id'; 38 | usageStr += common.buildDetailedUsageString(Options); 39 | 40 | // --- Mainline 41 | 42 | common.parseArguments(Options, ShortOptions, function (parsed) { 43 | if (parsed.argv.remain.length < 1) { 44 | common.usage(usageStr, 1, 'fwrule_id required'); 45 | } 46 | 47 | var client = common.newClient(parsed); 48 | parsed.argv.remain.forEach(function (fwrule) { 49 | client.enableFwRule(fwrule, common.callback); 50 | }); 51 | }, usageStr); 52 | -------------------------------------------------------------------------------- /bin/sdc-enablemachinefirewall: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += ' machine_id'; 40 | usageStr += common.buildDetailedUsageString(Options); 41 | 42 | 43 | // --- Mainline 44 | 45 | common.parseArguments(Options, ShortOptions, function (parsed) { 46 | if (parsed.argv.remain.length < 1) { 47 | common.usage(usageStr, 1, 'machine required'); 48 | } 49 | 50 | var client = common.newClient(parsed); 51 | parsed.argv.remain.forEach(function (machine) { 52 | client.enableFirewall(machine, common.callback); 53 | }); 54 | }, usageStr); 55 | -------------------------------------------------------------------------------- /bin/sdc-exportimage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'mantaPath': String, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'd': ['--debug'], 31 | 'h': ['--help'], 32 | '?': ['--help'], 33 | 'k': ['--keyId'], 34 | 'u': ['--url'], 35 | 'v': ['--verbose'], 36 | 'm': ['--mantaPath'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options) + ' image_id'; 41 | usageStr += common.buildDetailedUsageString(Options); 42 | 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | var mantaPath; 48 | if (parsed.argv.remain.length < 1) { 49 | common.usage(usageStr, 1, 'image required'); 50 | } 51 | if (parsed.mantaPath) 52 | mantaPath = parsed.mantaPath; 53 | else 54 | common.usage(usageStr, 1, 'mantaPath(string) required'); 55 | 56 | var client = common.newClient(parsed); 57 | parsed.argv.remain.forEach(function (image) { 58 | client.exportImage(image, mantaPath, common.callback); 59 | }); 60 | }, usageStr); 61 | -------------------------------------------------------------------------------- /bin/sdc-getaccount: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | // --- Mainline 42 | 43 | common.parseArguments(Options, ShortOptions, function (parsed) { 44 | var client = common.newClient(parsed); 45 | client.getAccount(common.callback); 46 | }, usageStr); 47 | -------------------------------------------------------------------------------- /bin/sdc-getfirewallrule: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | 39 | var usageStr = common.buildUsageString(Options) + ' fwrule_id'; 40 | usageStr += common.buildDetailedUsageString(Options); 41 | 42 | // --- Mainline 43 | 44 | common.parseArguments(Options, ShortOptions, function (parsed) { 45 | if (parsed.argv.remain.length < 1) { 46 | common.usage(usageStr, 1, 'fwrule_id required'); 47 | } 48 | 49 | var client = common.newClient(parsed); 50 | parsed.argv.remain.forEach(function (fwrule) { 51 | client.getFwRule(fwrule, common.callback); 52 | }); 53 | }, usageStr); 54 | -------------------------------------------------------------------------------- /bin/sdc-getimage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var API_VERSION = '~7||~8'; 15 | 16 | var Options = { 17 | 'account': String, 18 | 'api-version': String, 19 | 'debug': Boolean, 20 | 'help': Boolean, 21 | 'keyId': String, 22 | 'url': url, 23 | 'version': Boolean, 24 | 'verbose': Boolean, 25 | 'user': String, 26 | 'role': String 27 | }; 28 | 29 | var ShortOptions = { 30 | 'a': ['--account'], 31 | 'd': ['--debug'], 32 | 'h': ['--help'], 33 | '?': ['--help'], 34 | 'k': ['--keyId'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options) + ' image_id'; 41 | usageStr += common.buildDetailedUsageString(Options); 42 | 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | if (parsed.argv.remain.length < 1) { 48 | common.usage(usageStr, 1, 'image required'); 49 | } 50 | 51 | parsed.api_version = parsed.api_version || API_VERSION; 52 | 53 | var client = common.newClient(parsed); 54 | parsed.argv.remain.forEach(function (image) { 55 | client.getImage(image, common.callback); 56 | }); 57 | }, usageStr); 58 | -------------------------------------------------------------------------------- /bin/sdc-getkey: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options) + ' key_name'; 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | 42 | // --- Mainline 43 | 44 | common.parseArguments(Options, ShortOptions, function (parsed) { 45 | if (parsed.argv.remain.length < 1) { 46 | common.usage(usageStr, 1, 'key_name required'); 47 | } 48 | 49 | var client = common.newClient(parsed); 50 | parsed.argv.remain.forEach(function (key) { 51 | client.getKey(key, common.callback); 52 | }); 53 | }, usageStr); 54 | -------------------------------------------------------------------------------- /bin/sdc-getmachine: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'credentials': Boolean, 18 | 'debug': Boolean, 19 | 'help': Boolean, 20 | 'keyId': String, 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'c': ['--credentials'], 31 | 'd': ['--debug'], 32 | 'h': ['--help'], 33 | '?': ['--help'], 34 | 'k': ['--keyId'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options) + ' machine_id'; 41 | usageStr += common.buildDetailedUsageString(Options); 42 | 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | if (parsed.argv.remain.length < 1) { 48 | common.usage(usageStr, 1, 'machine(id) required'); 49 | } 50 | 51 | var client = common.newClient(parsed); 52 | parsed.argv.remain.forEach(function (machine) { 53 | client.getMachine(machine, 54 | parsed.credentials || false, 55 | common.callback); 56 | }); 57 | }, usageStr); 58 | -------------------------------------------------------------------------------- /bin/sdc-getmachineaudit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options) + ' machine_id'; 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | 42 | // --- Mainline 43 | 44 | common.parseArguments(Options, ShortOptions, function (parsed) { 45 | if (parsed.argv.remain.length < 1) { 46 | common.usage(usageStr, 1, 'machine required'); 47 | } 48 | 49 | var client = common.newClient(parsed); 50 | parsed.argv.remain.forEach(function (machine) { 51 | client.getMachineAudit(machine, common.callback); 52 | }); 53 | }, usageStr); 54 | -------------------------------------------------------------------------------- /bin/sdc-getmachinemetadata: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'credentials': Boolean, 18 | 'debug': Boolean, 19 | 'help': Boolean, 20 | 'keyId': String, 21 | 'metadataId': String, 22 | 'url': url, 23 | 'version': Boolean, 24 | 'user': String, 25 | 'verbose': Boolean, 26 | 'role': String 27 | }; 28 | 29 | var ShortOptions = { 30 | 'a': ['--account'], 31 | 'c': ['--credentials'], 32 | 'd': ['--debug'], 33 | 'h': ['--help'], 34 | '?': ['--help'], 35 | 'k': ['--keyId'], 36 | 'm': ['--metadataId'], 37 | 'u': ['--url'], 38 | 'v': ['--verbose'], 39 | 'A': ['--user'] 40 | }; 41 | 42 | var usageStr = common.buildUsageString(Options) + ' machine_id'; 43 | usageStr += common.buildDetailedUsageString(Options); 44 | 45 | 46 | // --- Mainline 47 | 48 | common.parseArguments(Options, ShortOptions, function (parsed) { 49 | if (parsed.argv.remain.length < 1) { 50 | common.usage(usageStr, 1, 'machine required'); 51 | } 52 | 53 | function cb(err, obj) { 54 | if (err) { 55 | try { 56 | console.error(JSON.parse(err.message).message); 57 | } catch (e) { 58 | console.error(err.message); 59 | } 60 | process.exit(3); 61 | } 62 | 63 | common.emit(JSON.stringify(obj, null, 2)); 64 | common.exit(0); 65 | } 66 | 67 | var query; 68 | if (parsed.metadataId) { 69 | query = function (machine) { 70 | client.getMachineMetadataV2(machine, parsed.metadataId, cb); 71 | }; 72 | } else { 73 | console.error('Usage without --metadataId is deprecated. To get full ' + 74 | 'metadata listings, please use sdc-listmachinemetadata ' + 75 | 'instead.'); 76 | query = function (machine) { 77 | client.listMachineMetadata(machine, parsed.credentials || false, cb); 78 | }; 79 | } 80 | 81 | 82 | var client = common.newClient(parsed); 83 | 84 | parsed.argv.remain.forEach(query); 85 | }, usageStr); 86 | -------------------------------------------------------------------------------- /bin/sdc-getmachinesnapshot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'snapshot': String, 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'd': ['--debug'], 31 | 'h': ['--help'], 32 | '?': ['--help'], 33 | 'k': ['--keyId'], 34 | 'n': ['--snapshot'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options) + ' machine_id'; 41 | usageStr += common.buildDetailedUsageString(Options); 42 | 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | if (!parsed.snapshot) { 48 | common.usage(usageStr, 1, 'snapshot required'); 49 | } 50 | if (parsed.argv.remain.length < 1) { 51 | common.usage(usageStr, 1, 'machine required'); 52 | } 53 | 54 | var client = common.newClient(parsed); 55 | 56 | parsed.argv.remain.forEach(function (machine) { 57 | client.getMachineSnapshot(machine, parsed.snapshot, common.callback); 58 | }); 59 | }, usageStr); 60 | -------------------------------------------------------------------------------- /bin/sdc-getmachinetag: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'tag': String, 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'd': ['--debug'], 31 | 'h': ['--help'], 32 | '?': ['--help'], 33 | 'k': ['--keyId'], 34 | 't': ['--tag'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options) + ' machine_id'; 41 | usageStr += common.buildDetailedUsageString(Options, { 'tag': 'tag name' }); 42 | 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | if (!parsed.tag) { 48 | common.usage(usageStr, 1, 'tag required'); 49 | } 50 | if (parsed.argv.remain.length < 1) { 51 | common.usage(usageStr, 1, 'machine required'); 52 | } 53 | 54 | function callback(err, obj) { 55 | if (err) { 56 | if (obj && obj.errors && obj.errors[0]) { 57 | console.error(err.message + ':', obj.errors[0].message); 58 | } else { 59 | console.error(err.message); 60 | } 61 | process.exit(3); 62 | } 63 | 64 | common.emit(obj); 65 | common.exit(0); 66 | } 67 | 68 | var client = common.newClient(parsed); 69 | 70 | parsed.argv.remain.forEach(function (machine) { 71 | client.getMachineTag(machine, parsed.tag, callback); 72 | }); 73 | }, usageStr); 74 | -------------------------------------------------------------------------------- /bin/sdc-getnetwork: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options) + ' network_id'; 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | 42 | // --- Mainline 43 | 44 | common.parseArguments(Options, ShortOptions, function (parsed) { 45 | if (parsed.argv.remain.length < 1) { 46 | common.usage(usageStr, 1, 'network required'); 47 | } 48 | 49 | var client = common.newClient(parsed); 50 | parsed.argv.remain.forEach(function (network) { 51 | client.getNetwork(network, common.callback); 52 | }); 53 | }, usageStr); 54 | -------------------------------------------------------------------------------- /bin/sdc-getpackage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options) + ' package_id'; 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | 42 | // --- Mainline 43 | 44 | common.parseArguments(Options, ShortOptions, function (parsed) { 45 | if (parsed.argv.remain.length < 1) { 46 | common.usage(usageStr, 1, 'package required'); 47 | } 48 | 49 | var client = common.newClient(parsed); 50 | parsed.argv.remain.forEach(function (pkg) { 51 | client.getPackage(pkg, common.callback); 52 | }); 53 | }, usageStr); 54 | -------------------------------------------------------------------------------- /bin/sdc-info: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2014 Joyent, Inc. All rights reserved. 5 | var url = require('url'); 6 | 7 | // var common = require('../lib/cli_common'); 8 | var util = require('util'); 9 | var path = require('path'); 10 | var fs = require('fs'); 11 | 12 | var bunyan = require('bunyan'); 13 | var smartdc = require('../lib/cloudapi'), 14 | CloudAPI = smartdc.CloudAPI; 15 | var shared = require('../lib/shared'), 16 | commonCb = shared.commonCb, 17 | DEFAULT_OPTIONS = shared.DEFAULT_OPTIONS; 18 | var cmdln = require('cmdln'), 19 | Cmdln = cmdln.Cmdln; 20 | var auth = require('smartdc-auth'); 21 | 22 | var pkg = require('../package.json'); 23 | var dashdash = require('dashdash'); 24 | 25 | var options = DEFAULT_OPTIONS; 26 | 27 | if (require.main === module) { 28 | 29 | var parser = dashdash.createParser({options: options}); 30 | 31 | try { 32 | var opts = parser.parse(process.argv); 33 | } catch (e) { 34 | console.error('sdc-info: error: %s', e.message); 35 | process.exit(1); 36 | } 37 | 38 | if (opts.debug) { 39 | process.env.DEBUG = 1; 40 | opts.logLevel = 'trace'; 41 | } 42 | 43 | // Use `parser.help()` for formatted options help. 44 | if (opts.help || ! opts._args.length || opts._args[0] === 'help') { 45 | var help = parser.help({includeEnv: true}).trimRight(); 46 | shared.emit('Display role tags for a given SmartDC resource\n\n' + 47 | 'Usage: sdc-info [OPTIONS] resource \n' + 'Options:\n' + 48 | help); 49 | shared.exit(0); 50 | } 51 | 52 | if (opts.version) { 53 | shared.emit('sdc-info', pkg.version); 54 | shared.exit(0); 55 | } 56 | 57 | if (typeof (opts.keyId) === 'undefined') { 58 | console.error('Either -k or (env) SDC_KEY_ID must be specified'); 59 | process.exit(1); 60 | } 61 | 62 | if (!opts.account) { 63 | console.error('Either -a or (env) SDC_ACCOUNT must be specified'); 64 | process.exit(1); 65 | } 66 | 67 | if (!opts.url) { 68 | console.error('Either -u or (env) SDC_URL must be specified'); 69 | process.exit(1); 70 | } 71 | 72 | opts.sign = auth.cliSigner({ 73 | keyId: opts.keyId, 74 | user: opts.account, 75 | subuser: opts.user 76 | }); 77 | 78 | var cloudapi = new CloudAPI(opts); 79 | cloudapi.getRoleTags(opts._args[0], commonCb); 80 | } 81 | -------------------------------------------------------------------------------- /bin/sdc-listdatacenters: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | // --- Mainline 42 | 43 | common.parseArguments(Options, ShortOptions, function (parsed) { 44 | var client = common.newClient(parsed); 45 | client.listDatacenters(common.callback); 46 | }, usageStr); 47 | -------------------------------------------------------------------------------- /bin/sdc-listfirewallrulemachines: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options) + ' fwrule_id'; 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | // --- Mainline 42 | 43 | common.parseArguments(Options, ShortOptions, function (parsed) { 44 | if (parsed.argv.remain.length < 1) { 45 | common.usage(usageStr, 1, 'fwrule(id) required'); 46 | } 47 | 48 | var client = common.newClient(parsed); 49 | parsed.argv.remain.forEach(function (fwrule) { 50 | client.listRuleMachines(fwrule, common.callback); 51 | }); 52 | }, usageStr); 53 | -------------------------------------------------------------------------------- /bin/sdc-listfirewallrules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | // --- Mainline 42 | 43 | common.parseArguments(Options, ShortOptions, function (parsed) { 44 | var client = common.newClient(parsed); 45 | client.listFwRules(common.callback); 46 | }, usageStr); 47 | -------------------------------------------------------------------------------- /bin/sdc-listimages: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var API_VERSION = '~7||~8'; 15 | 16 | var Options = { 17 | 'account': String, 18 | 'api-version': String, 19 | 'public': String, 20 | 'state': String, 21 | 'type': String, 22 | 'debug': Boolean, 23 | 'help': Boolean, 24 | 'keyId': String, 25 | 'url': url, 26 | 'version': Boolean, 27 | 'verbose': Boolean, 28 | 'user': String, 29 | 'role': String 30 | }; 31 | 32 | var ShortOptions = { 33 | 'a': ['--account'], 34 | 'p': ['--public'], 35 | 's': ['--state'], 36 | 't': ['--type'], 37 | 'd': ['--debug'], 38 | 'h': ['--help'], 39 | '?': ['--help'], 40 | 'k': ['--keyId'], 41 | 'u': ['--url'], 42 | 'v': ['--verbose'], 43 | 'A': ['--user'] 44 | }; 45 | 46 | var usageStr = common.buildUsageString(Options); 47 | usageStr += common.buildDetailedUsageString(Options); 48 | 49 | // --- Mainline 50 | 51 | common.parseArguments(Options, ShortOptions, function (parsed) { 52 | var opts = {}; 53 | if (parsed['public']) { 54 | opts['public'] = parsed['public']; 55 | } 56 | if (parsed.state) { 57 | opts.state = parsed.state; 58 | } 59 | if (parsed.type) { 60 | opts.type = parsed.type; 61 | } 62 | 63 | parsed.api_version = parsed.api_version || API_VERSION; 64 | 65 | var client = common.newClient(parsed); 66 | client.listImages(opts, common.callback); 67 | }, usageStr); 68 | -------------------------------------------------------------------------------- /bin/sdc-listkeys: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | // --- Mainline 42 | 43 | common.parseArguments(Options, ShortOptions, function (parsed) { 44 | var client = common.newClient(parsed); 45 | client.listKeys(common.callback); 46 | }, usageStr); 47 | -------------------------------------------------------------------------------- /bin/sdc-listmachinefirewallrules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options) + ' machine_id'; 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | // --- Mainline 42 | 43 | common.parseArguments(Options, ShortOptions, function (parsed) { 44 | if (parsed.argv.remain.length < 1) { 45 | common.usage(usageStr, 1, 'machine(id) required'); 46 | } 47 | 48 | var client = common.newClient(parsed); 49 | parsed.argv.remain.forEach(function (machine) { 50 | client.listMachineRules(machine, common.callback); 51 | }); 52 | }, usageStr); 53 | -------------------------------------------------------------------------------- /bin/sdc-listmachinemetadata: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2014 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'credentials': Boolean, 18 | 'debug': Boolean, 19 | 'help': Boolean, 20 | 'keyId': String, 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'c': ['--credentials'], 31 | 'd': ['--debug'], 32 | 'h': ['--help'], 33 | '?': ['--help'], 34 | 'k': ['--keyId'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options) + ' machine_id'; 41 | usageStr += common.buildDetailedUsageString(Options); 42 | 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | if (parsed.argv.remain.length < 1) { 48 | common.usage(usageStr, 1, 'machine required'); 49 | } 50 | 51 | function callback(err, obj) { 52 | if (err) { 53 | try { 54 | console.error(JSON.parse(err.message).message); 55 | } catch (e) { 56 | console.error(err.message); 57 | } 58 | process.exit(3); 59 | } 60 | 61 | common.emit(JSON.stringify(obj, null, 2)); 62 | common.exit(0); 63 | } 64 | 65 | var client = common.newClient(parsed); 66 | 67 | parsed.argv.remain.forEach(function (machine) { 68 | client.listMachineMetadata(machine, 69 | parsed.credentials || false, 70 | callback); 71 | }); 72 | }, usageStr); 73 | -------------------------------------------------------------------------------- /bin/sdc-listmachines: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'brand': String, 18 | 'credentials': Boolean, 19 | 'debug': Boolean, 20 | 'image': String, 21 | 'help': Boolean, 22 | 'keyId': String, 23 | 'limit': Number, 24 | 'memory': Number, 25 | 'name': String, 26 | 'offset': Number, 27 | 'state': String, 28 | 'tag': [String, Array], 29 | 'type': String, 30 | 'tombstone': Boolean, 31 | 'url': url, 32 | 'version': Boolean, 33 | 'verbose': Boolean, 34 | 'user': String, 35 | 'role': String 36 | }; 37 | 38 | var ShortOptions = { 39 | 'a': ['--account'], 40 | 'c': ['--credentials'], 41 | 'b': ['--tombstone'], 42 | 'd': ['--debug'], 43 | 'e': ['--image'], // DEPRECATED 44 | 'i': ['--image'], 45 | 'h': ['--help'], 46 | '?': ['--help'], 47 | 'k': ['--keyId'], 48 | 'l': ['--limit'], 49 | 'm': ['--memory'], 50 | 'n': ['--name'], 51 | 'o': ['--offset'], 52 | 's': ['--state'], 53 | 't': ['--tag'], 54 | 'y': ['--type'], 55 | 'u': ['--url'], 56 | 'v': ['--verbose'], 57 | 'A': ['--user'] 58 | }; 59 | 60 | var usageStr = common.buildUsageString(Options); 61 | usageStr += common.buildDetailedUsageString(Options); 62 | 63 | // --- Mainline 64 | 65 | common.parseArguments(Options, ShortOptions, function (parsed) { 66 | 67 | var opts = {}; 68 | var tags = {}; 69 | if (parsed.credentials) { 70 | opts.credentials = parsed.credentials; 71 | } 72 | if (parsed.image) { 73 | opts.image = parsed.image; 74 | } 75 | if (typeof (parsed.limit) !== 'undefined') { 76 | opts.limit = parsed.limit; 77 | } 78 | if (typeof (parsed.memory) !== 'undefined') { 79 | opts.memory = parsed.memory; 80 | } 81 | if (parsed.name) { 82 | opts.name = parsed.name; 83 | } 84 | if (typeof (parsed.offset) !== 'undefined') { 85 | opts.offset = parsed.offset; 86 | } 87 | if (parsed.state) { 88 | opts.state = parsed.state; 89 | } 90 | if (typeof (parsed.tombstone) !== 'undefined') { 91 | opts.tombstone = parsed.tombstone; 92 | } 93 | if (parsed.type) { 94 | opts.type = parsed.type; 95 | } 96 | if (parsed.brand) { 97 | opts.brand = parsed.brand; 98 | } 99 | 100 | if (parsed.tag) { 101 | tags = parsed.tag.indexOf('*') !== -1 ? '*' : 102 | common.parseMetadata(parsed.tag, false); 103 | } 104 | 105 | var client = common.newClient(parsed); 106 | client.listMachines(opts, tags, function (err, obj, done) { 107 | if (err) { 108 | common.printErr(err); 109 | process.exit(3); 110 | } 111 | 112 | if (obj) { 113 | common.emit(JSON.stringify(obj, null, 2)); 114 | if (!done) { 115 | console.error('Partial listing of machines. Try increasing ' + 116 | 'listing limit with sdc-listmachines --limit'); 117 | } 118 | common.exit(0); 119 | } 120 | }); 121 | 122 | }, usageStr); 123 | -------------------------------------------------------------------------------- /bin/sdc-listmachinesnapshots: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options) + ' machine_id'; 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | // --- Mainline 42 | 43 | common.parseArguments(Options, ShortOptions, function (parsed) { 44 | if (parsed.argv.remain.length < 1) { 45 | common.usage(usageStr, 1, 'machine required'); 46 | } 47 | 48 | var client = common.newClient(parsed); 49 | parsed.argv.remain.forEach(function (machine) { 50 | client.listMachineSnapshots(machine, common.callback); 51 | }); 52 | }, usageStr); 53 | -------------------------------------------------------------------------------- /bin/sdc-listmachinetags: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options) + ' machine_id'; 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | // --- Mainline 42 | 43 | common.parseArguments(Options, ShortOptions, function (parsed) { 44 | if (parsed.argv.remain.length < 1) { 45 | common.usage(usageStr, 1, 'machine required'); 46 | } 47 | 48 | var client = common.newClient(parsed); 49 | parsed.argv.remain.forEach(function (machine) { 50 | client.listMachineTags(machine, common.callback); 51 | }); 52 | }, usageStr); 53 | -------------------------------------------------------------------------------- /bin/sdc-listnetworks: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | // --- Mainline 42 | 43 | common.parseArguments(Options, ShortOptions, function (parsed) { 44 | var client = common.newClient(parsed); 45 | client.listNetworks(common.callback); 46 | }, usageStr); 47 | -------------------------------------------------------------------------------- /bin/sdc-listpackages: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += common.buildDetailedUsageString(Options); 40 | 41 | // --- Mainline 42 | 43 | common.parseArguments(Options, ShortOptions, function (parsed) { 44 | var client = common.newClient(parsed); 45 | client.listPackages(common.callback); 46 | }, usageStr); 47 | -------------------------------------------------------------------------------- /bin/sdc-nics: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2014 Joyent, Inc. All rights reserved. 5 | 6 | var util = require('util'); 7 | var shared = require('../lib/shared'), 8 | commonCb = shared.commonCb; 9 | var cmdln = require('cmdln'), 10 | Cmdln = cmdln.Cmdln; 11 | 12 | 13 | var generalOptions = [ 14 | { 15 | names: ['help', 'h', '?'], 16 | type: 'bool', 17 | help: 'Show this help.' 18 | } 19 | ]; 20 | 21 | 22 | 23 | function SDCNic() { 24 | Cmdln.call(this, { 25 | name: 'sdc-nics', 26 | desc: 'SmartDC machine NIC operations', 27 | options: shared.DEFAULT_OPTIONS, 28 | helpOpts: { 29 | includeEnv: true 30 | } 31 | }); 32 | } 33 | util.inherits(SDCNic, Cmdln); 34 | 35 | 36 | 37 | SDCNic.prototype.init = shared.checkRequiredOptions; 38 | 39 | 40 | 41 | SDCNic.prototype.do_list = function (subcmd, opts, args, callback) { 42 | if (opts.help) { 43 | return this.do_help('help', {}, [subcmd], callback); 44 | } 45 | 46 | if (args.length !== 1) { 47 | return callback(new Error('machine_id must be specified')); 48 | } 49 | 50 | return this.cloudapi.listNics(args[0], commonCb); 51 | }; 52 | 53 | SDCNic.prototype.do_list.options = generalOptions; 54 | SDCNic.prototype.do_list.help = ( 55 | 'List your machine\'s NICs.\n' + 56 | '\n' + 57 | 'Usage:\n' + 58 | ' {{name}} list [OPTIONS] machine_id\n' + 59 | '\n' + 60 | '{{options}}' 61 | ); 62 | 63 | 64 | 65 | SDCNic.prototype.do_get = function (subcmd, opts, args, callback) { 66 | if (opts.help) { 67 | return this.do_help('help', {}, [subcmd], callback); 68 | } 69 | 70 | if (args.length !== 2) { 71 | return callback(new Error('nic_mac and machine_id must be specified')); 72 | } 73 | 74 | return this.cloudapi.getNic(args[1], args[0], commonCb); 75 | 76 | }; 77 | 78 | SDCNic.prototype.do_get.options = generalOptions; 79 | SDCNic.prototype.do_get.help = ( 80 | 'Get a machine\'s NIC by MAC.\n' + 81 | '\n' + 82 | 'Usage:\n' + 83 | ' {{name}} get [OPTIONS] nic_mac machine_id\n' + 84 | '\n' + 85 | '{{options}}' 86 | ); 87 | 88 | 89 | 90 | SDCNic.prototype.do_create = function (subcmd, opts, args, callback) { 91 | var self = this; 92 | if (opts.help) { 93 | return this.do_help('help', {}, [subcmd], callback); 94 | } 95 | 96 | if (args.length !== 2) { 97 | var msg = 'network_id and machine_id must be specified'; 98 | return callback(new Error(msg)); 99 | } 100 | 101 | var params = { 102 | network: args[0], 103 | machine: args[1] 104 | }; 105 | 106 | return self.cloudapi.createNic(params, commonCb); 107 | }; 108 | 109 | SDCNic.prototype.do_create.options = generalOptions; 110 | SDCNic.prototype.do_create.help = ( 111 | 'Create a new NIC on one of your machines, and reboot the machine.\n' + 112 | '\n' + 113 | 'Usage:\n' + 114 | ' {{name}} create [OPTIONS] network_id machine_id\n' + 115 | '\n' + 116 | '{{options}}' 117 | ); 118 | 119 | 120 | 121 | SDCNic.prototype.do_delete = function (subcmd, opts, args, callback) { 122 | if (opts.help) { 123 | return this.do_help('help', {}, [subcmd], callback); 124 | } 125 | 126 | if (args.length !== 2) { 127 | return callback(new Error('nic_mac and machine_id must be specified')); 128 | } 129 | 130 | return this.cloudapi.deleteNic(args[1], args[0], commonCb); 131 | 132 | }; 133 | 134 | SDCNic.prototype.do_delete.options = generalOptions; 135 | SDCNic.prototype.do_delete.help = ( 136 | 'Removes a NIC from a machine, and reboots machine.\n' + 137 | '\n' + 138 | 'Usage:\n' + 139 | ' {{name}} delete [OPTIONS] nic_mac machine_id\n' + 140 | '\n' + 141 | '{{options}}' 142 | ); 143 | 144 | 145 | 146 | if (require.main === module) { 147 | cmdln.main(SDCNic); 148 | } 149 | -------------------------------------------------------------------------------- /bin/sdc-policy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2014 Joyent, Inc. All rights reserved. 5 | var util = require('util'); 6 | 7 | var shared = require('../lib/shared'), 8 | commonCb = shared.commonCb, 9 | DEFAULT_OPTIONS = shared.DEFAULT_OPTIONS, 10 | checkRequiredOptions = shared.checkRequiredOptions; 11 | var cmdln = require('cmdln'), 12 | Cmdln = cmdln.Cmdln; 13 | 14 | /** 15 | * SDCPolicy Cmdln sub class 16 | */ 17 | function SDCPolicy() { 18 | Cmdln.call(this, { 19 | name: 'sdc-policy', 20 | desc: 'SmartDC Account Policies', 21 | // Custom options. By default you get -h/--help. 22 | options: DEFAULT_OPTIONS, 23 | helpOpts: { 24 | includeEnv: true 25 | } 26 | }); 27 | } 28 | util.inherits(SDCPolicy, Cmdln); 29 | 30 | SDCPolicy.prototype.init = shared.checkRequiredOptions; 31 | 32 | 33 | var generalOptions = [ 34 | { 35 | names: ['help', 'h', '?'], 36 | type: 'bool', 37 | help: 'Show this help.' 38 | } 39 | ]; 40 | 41 | 42 | SDCPolicy.prototype.do_list = function (subcmd, opts, args, callback) { 43 | var self = this; 44 | if (opts.help) { 45 | return this.do_help('help', {}, [subcmd], callback); 46 | } 47 | 48 | return self.cloudapi.listPolicies(commonCb); 49 | }; 50 | 51 | 52 | SDCPolicy.prototype.do_list.options = generalOptions; 53 | SDCPolicy.prototype.do_list.help = ( 54 | 'List your Account Policies.\n' + 55 | '\n' + 56 | 'Usage:\n' + 57 | ' {{name}} list [OPTIONS]\n' + 58 | '\n' + 59 | '{{options}}' 60 | ); 61 | 62 | 63 | SDCPolicy.prototype.do_get = function (subcmd, opts, args, callback) { 64 | var self = this; 65 | if (opts.help) { 66 | return this.do_help('help', {}, [subcmd], callback); 67 | } 68 | 69 | if (!args.length) { 70 | return callback(new Error( 71 | 'Policy id must be specified')); 72 | } 73 | 74 | return self.cloudapi.getPolicy(args[0], commonCb); 75 | }; 76 | 77 | 78 | SDCPolicy.prototype.do_get.options = generalOptions; 79 | SDCPolicy.prototype.do_get.help = ( 80 | 'Get an account Policy by id.\n' + 81 | '\n' + 82 | 'Usage:\n' + 83 | ' {{name}} get [OPTIONS] policy_id \n' + 84 | '\n' + 85 | '{{options}}' 86 | ); 87 | 88 | 89 | SDCPolicy.prototype.do_create = function (subcmd, opts, args, callback) { 90 | var self = this; 91 | if (opts.help) { 92 | return this.do_help('help', {}, [subcmd], callback); 93 | } 94 | 95 | var params = {}; 96 | 97 | if (opts.name) { 98 | params.name = opts.name; 99 | } 100 | 101 | if (opts.rules) { 102 | params.rules = opts.rules; 103 | } 104 | 105 | if (opts.description) { 106 | params.description = opts.description; 107 | } 108 | 109 | return self.cloudapi.createPolicy(params, commonCb); 110 | }; 111 | 112 | 113 | SDCPolicy.prototype.do_create.options = [ { 114 | name: 'rules', 115 | type: 'arrayOfString', 116 | help: 'A list of rules for the policy' 117 | }, { 118 | names: ['help', 'h', '?'], 119 | type: 'bool', 120 | help: 'Show this help.' 121 | }, { 122 | name: 'name', 123 | type: 'string', 124 | help: 'Policy name' 125 | }, { 126 | name: 'description', 127 | type: 'string', 128 | help: 'A detailed policy description' 129 | }]; 130 | 131 | SDCPolicy.prototype.do_create.help = ( 132 | 'Creates a new Policy for your account.\n' + 133 | '\n' + 134 | 'Usage:\n' + 135 | ' {{name}} create [OPTIONS] \n' + 136 | '\n' + 137 | '{{options}}' 138 | ); 139 | 140 | 141 | SDCPolicy.prototype.do_update = function (subcmd, opts, args, callback) { 142 | var self = this; 143 | if (opts.help) { 144 | return this.do_help('help', {}, [subcmd], callback); 145 | } 146 | 147 | if (!args.length) { 148 | return callback(new Error( 149 | 'Policy id must be specified')); 150 | } 151 | 152 | var params = { 153 | id: args[0] 154 | }; 155 | 156 | if (opts.name) { 157 | params.name = opts.name; 158 | } 159 | 160 | if (opts.rules) { 161 | params.rules = opts.rules; 162 | } 163 | 164 | if (typeof (opts.description) !== 'undefined') { 165 | params.description = opts.description; 166 | } 167 | 168 | return self.cloudapi.updatePolicy(params, commonCb); 169 | }; 170 | 171 | 172 | SDCPolicy.prototype.do_update.options = [ { 173 | name: 'rules', 174 | type: 'arrayOfString', 175 | help: 'A list of rules for the policy' 176 | }, { 177 | names: ['help', 'h', '?'], 178 | type: 'bool', 179 | help: 'Show this help.' 180 | }, { 181 | name: 'name', 182 | type: 'string', 183 | help: 'Policy name' 184 | }, { 185 | name: 'description', 186 | type: 'string', 187 | help: 'A detailed policy description' 188 | }]; 189 | 190 | SDCPolicy.prototype.do_update.help = ( 191 | 'Updates a Policy of your account.\n' + 192 | '\n' + 193 | 'Usage:\n' + 194 | ' {{name}} update [OPTIONS] policy_id \n' + 195 | '\n' + 196 | '{{options}}' 197 | ); 198 | 199 | 200 | SDCPolicy.prototype.do_delete = function (subcmd, opts, args, callback) { 201 | var self = this; 202 | if (opts.help) { 203 | return this.do_help('help', {}, [subcmd], callback); 204 | } 205 | 206 | if (!args.length) { 207 | return callback(new Error( 208 | 'Policy id must be specified')); 209 | } 210 | 211 | return self.cloudapi.deletePolicy(args[0], commonCb); 212 | 213 | }; 214 | 215 | 216 | SDCPolicy.prototype.do_delete.options = generalOptions; 217 | SDCPolicy.prototype.do_delete.help = ( 218 | 'Removes a Policy from your account.\n' + 219 | '\n' + 220 | 'Usage:\n' + 221 | ' {{name}} delete [OPTIONS] policy_id \n' + 222 | '\n' + 223 | '{{options}}' 224 | ); 225 | 226 | if (require.main === module) { 227 | cmdln.main(SDCPolicy); 228 | } 229 | -------------------------------------------------------------------------------- /bin/sdc-rebootmachine: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += ' machine_id'; 40 | usageStr += common.buildDetailedUsageString(Options); 41 | 42 | // --- Mainline 43 | 44 | common.parseArguments(Options, ShortOptions, function (parsed) { 45 | if (parsed.argv.remain.length < 1) { 46 | common.usage(usageStr, 1, 'machine required'); 47 | } 48 | 49 | var client = common.newClient(parsed); 50 | parsed.argv.remain.forEach(function (machine) { 51 | client.rebootMachine(machine, common.callback); 52 | }); 53 | }, usageStr); 54 | -------------------------------------------------------------------------------- /bin/sdc-renamemachine: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'name': String, 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'd': ['--debug'], 31 | 'h': ['--help'], 32 | '?': ['--help'], 33 | 'k': ['--keyId'], 34 | 'n': ['--name'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options); 41 | usageStr += ' machine_id'; 42 | usageStr += common.buildDetailedUsageString(Options); 43 | 44 | 45 | // --- Mainline 46 | 47 | common.parseArguments(Options, ShortOptions, function (parsed) { 48 | if (parsed.argv.remain.length < 1) { 49 | common.usage(usageStr, 1, 'machine required'); 50 | } 51 | 52 | var opts = {}; 53 | if (parsed.name) { 54 | opts.name = parsed.name; 55 | } 56 | 57 | var client = common.newClient(parsed); 58 | parsed.argv.remain.forEach(function (machine) { 59 | client.renameMachine(machine, opts, common.callback); 60 | }); 61 | }, usageStr); 62 | -------------------------------------------------------------------------------- /bin/sdc-replacemachinetags: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'tag': [String, Array], 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'd': ['--debug'], 31 | 'h': ['--help'], 32 | '?': ['--help'], 33 | 'k': ['--keyId'], 34 | 't': ['--tag'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options); 41 | usageStr += ' machine_id'; 42 | usageStr += common.buildDetailedUsageString(Options); 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | 48 | if (parsed.argv.remain.length < 1) { 49 | common.usage(usageStr, 1, 'machine required'); 50 | } 51 | 52 | if (!parsed.tag) { 53 | common.usage(usageStr, 1, '--tag required'); 54 | } 55 | 56 | var tags = common.parseMetadata(parsed.tag, false); 57 | 58 | var client = common.newClient(parsed); 59 | parsed.argv.remain.forEach(function (machine) { 60 | client.replaceMachineTags(machine, tags, common.callback); 61 | }); 62 | }, usageStr); 63 | -------------------------------------------------------------------------------- /bin/sdc-resizemachine: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'package': String, 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'd': ['--debug'], 31 | 'h': ['--help'], 32 | '?': ['--help'], 33 | 'k': ['--keyId'], 34 | 'p': ['--package'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options); 41 | usageStr += ' machine_id'; 42 | usageStr += common.buildDetailedUsageString(Options); 43 | 44 | 45 | // --- Mainline 46 | 47 | common.parseArguments(Options, ShortOptions, function (parsed) { 48 | if (parsed.argv.remain.length < 1) { 49 | common.usage(usageStr, 1, 'machine required'); 50 | } 51 | 52 | var opts = {}; 53 | if (parsed['package']) { 54 | opts['package'] = parsed['package']; 55 | } 56 | 57 | 58 | var client = common.newClient(parsed); 59 | parsed.argv.remain.forEach(function (machine) { 60 | client.resizeMachine(machine, opts, common.callback); 61 | }); 62 | }, usageStr); 63 | -------------------------------------------------------------------------------- /bin/sdc-role: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2014 Joyent, Inc. All rights reserved. 5 | var util = require('util'); 6 | 7 | var shared = require('../lib/shared'), 8 | printErr = shared.printErr, 9 | argToArray = shared.argToArray, 10 | commonCb = shared.commonCb, 11 | DEFAULT_OPTIONS = shared.DEFAULT_OPTIONS, 12 | checkRequiredOptions = shared.checkRequiredOptions; 13 | var cmdln = require('cmdln'), 14 | Cmdln = cmdln.Cmdln; 15 | 16 | /** 17 | * SDCRole Cmdln sub class 18 | */ 19 | function SDCRole() { 20 | Cmdln.call(this, { 21 | name: 'sdc-role', 22 | desc: 'SmartDC Account Roles', 23 | // Custom options. By default you get -h/--help. 24 | options: DEFAULT_OPTIONS, 25 | helpOpts: { 26 | includeEnv: true 27 | } 28 | }); 29 | } 30 | util.inherits(SDCRole, Cmdln); 31 | 32 | SDCRole.prototype.init = shared.checkRequiredOptions; 33 | 34 | 35 | var generalOptions = [ 36 | { 37 | names: ['help', 'h', '?'], 38 | type: 'bool', 39 | help: 'Show this help.' 40 | } 41 | ]; 42 | 43 | 44 | SDCRole.prototype.do_list = function (subcmd, opts, args, callback) { 45 | var self = this; 46 | if (opts.help) { 47 | return this.do_help('help', {}, [subcmd], callback); 48 | } 49 | 50 | return self.cloudapi.listRoles(commonCb); 51 | }; 52 | 53 | 54 | SDCRole.prototype.do_list.options = generalOptions; 55 | SDCRole.prototype.do_list.help = ( 56 | 'List your Account Roles.\n' + 57 | '\n' + 58 | 'Usage:\n' + 59 | ' {{name}} list [OPTIONS]\n' + 60 | '\n' + 61 | '{{options}}' 62 | ); 63 | 64 | 65 | SDCRole.prototype.do_get = function (subcmd, opts, args, callback) { 66 | var self = this; 67 | if (opts.help) { 68 | return this.do_help('help', {}, [subcmd], callback); 69 | } 70 | 71 | if (!args.length) { 72 | return callback(new Error( 73 | 'Role id must be specified')); 74 | } 75 | 76 | return self.cloudapi.getRole(args[0], commonCb); 77 | 78 | }; 79 | 80 | 81 | SDCRole.prototype.do_get.options = generalOptions; 82 | SDCRole.prototype.do_get.help = ( 83 | 'Get an account Role by id.\n' + 84 | '\n' + 85 | 'Usage:\n' + 86 | ' {{name}} get [OPTIONS] role_id \n' + 87 | '\n' + 88 | '{{options}}' 89 | ); 90 | 91 | 92 | SDCRole.prototype.do_create = function (subcmd, opts, args, callback) { 93 | var self = this; 94 | if (opts.help) { 95 | return this.do_help('help', {}, [subcmd], callback); 96 | } 97 | 98 | var params = {}; 99 | 100 | if (opts.name) { 101 | params.name = opts.name; 102 | } 103 | 104 | if (opts.members) { 105 | params.members = argToArray(opts.members); 106 | } 107 | 108 | if (opts.default_members) { 109 | params.default_members = argToArray(opts.default_members); 110 | } 111 | 112 | if (opts.policies) { 113 | params.policies = argToArray(opts.policies); 114 | } 115 | 116 | return self.cloudapi.createRole(params, commonCb); 117 | }; 118 | 119 | 120 | SDCRole.prototype.do_create.options = [ { 121 | name: 'name', 122 | type: 'string', 123 | help: 'Role name' 124 | }, { 125 | names: ['help', 'h', '?'], 126 | type: 'bool', 127 | help: 'Show this help.' 128 | }, { 129 | name: 'members', 130 | type: 'arrayOfString', 131 | help: 'A list logins for users with this role (CSV or JSON)' 132 | }, { 133 | name: 'default-members', 134 | type: 'arrayOfString', 135 | help: 'A list logins for users with this role enabled (CSV or JSON)' 136 | }, { 137 | name: 'policies', 138 | type: 'arrayOfString', 139 | help: 'A list of policy names for this role (CSV or JSON)' 140 | }]; 141 | 142 | SDCRole.prototype.do_create.help = ( 143 | 'Creates a new Role for your account.\n' + 144 | '\n' + 145 | 'Usage:\n' + 146 | ' {{name}} create [OPTIONS] \n' + 147 | '\n' + 148 | '{{options}}' 149 | ); 150 | 151 | 152 | SDCRole.prototype.do_update = function (subcmd, opts, args, callback) { 153 | var self = this; 154 | if (opts.help) { 155 | return this.do_help('help', {}, [subcmd], callback); 156 | } 157 | 158 | if (!args.length) { 159 | return callback(new Error( 160 | 'Role id must be specified')); 161 | } 162 | 163 | var params = { 164 | id: args[0] 165 | }; 166 | 167 | if (opts.name) { 168 | params.name = opts.name; 169 | } 170 | 171 | if (opts.members) { 172 | params.members = argToArray(opts.members); 173 | } 174 | 175 | if (opts.default_members) { 176 | params.default_members = argToArray(opts.default_members); 177 | } 178 | 179 | if (opts.policies) { 180 | params.policies = argToArray(opts.policies); 181 | } 182 | 183 | return self.cloudapi.getRole(args[0], function (err, role) { 184 | if (err) { 185 | if (err.statusCode === 410) { 186 | console.error('Object is Gone (410)'); 187 | process.exit(3); 188 | } 189 | printErr(err); 190 | process.exit(3); 191 | } 192 | // Validate that members and default members are OK when one of them 193 | // is not provided: 194 | var errors = []; 195 | if (params.default_members && !params.members) { 196 | params.default_members.forEach(function (dm) { 197 | if (role.members.indexOf(dm) === -1) { 198 | errors.push(util.format('User \'%s\' must be a role ' + 199 | 'member in order to become a default member', dm)); 200 | } 201 | }); 202 | } else if (params.members && !params.default_members) { 203 | role.default_members.forEach(function (dm) { 204 | if (params.members.indexOf(dm) === -1) { 205 | errors.push(util.format('User \'%s\' must be removed ' + 206 | 'from both members and default members', dm)); 207 | } 208 | }); 209 | } 210 | 211 | if (errors.length) { 212 | console.error(errors.join('\n')); 213 | process.exit(3); 214 | } 215 | 216 | self.cloudapi.updateRole(params, commonCb); 217 | }); 218 | }; 219 | 220 | 221 | SDCRole.prototype.do_update.options = [ { 222 | name: 'name', 223 | type: 'string', 224 | help: 'Role name' 225 | }, { 226 | names: ['help', 'h', '?'], 227 | type: 'bool', 228 | help: 'Show this help.' 229 | }, { 230 | name: 'members', 231 | type: 'arrayOfString', 232 | help: 'A list logins for users with this role (CSV or JSON)' 233 | }, { 234 | name: 'default-members', 235 | type: 'arrayOfString', 236 | help: 'A list logins for users with this role enabled (CSV or JSON)' 237 | }, { 238 | name: 'policies', 239 | type: 'arrayOfString', 240 | help: 'A list of policy names for this role (CSV or JSON)' 241 | }]; 242 | 243 | SDCRole.prototype.do_update.help = ( 244 | 'Updates an account role.\n' + 245 | '\n' + 246 | 'Usage:\n' + 247 | ' {{name}} update [OPTIONS] role_id\n' + 248 | '\n' + 249 | '{{options}}' 250 | ); 251 | 252 | 253 | SDCRole.prototype.do_delete = function (subcmd, opts, args, callback) { 254 | var self = this; 255 | if (opts.help) { 256 | return this.do_help('help', {}, [subcmd], callback); 257 | } 258 | 259 | if (!args.length) { 260 | return callback(new Error( 261 | 'Role id must be specified')); 262 | } 263 | 264 | return self.cloudapi.deleteRole(args[0], commonCb); 265 | 266 | }; 267 | 268 | 269 | SDCRole.prototype.do_delete.options = generalOptions; 270 | SDCRole.prototype.do_delete.help = ( 271 | 'Removes an account role.\n' + 272 | '\n' + 273 | 'Usage:\n' + 274 | ' {{name}} delete [OPTIONS] role_id \n' + 275 | '\n' + 276 | '{{options}}' 277 | ); 278 | 279 | if (require.main === module) { 280 | cmdln.main(SDCRole); 281 | } 282 | -------------------------------------------------------------------------------- /bin/sdc-startmachine: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += ' machine_id'; 40 | usageStr += common.buildDetailedUsageString(Options); 41 | 42 | // --- Mainline 43 | 44 | common.parseArguments(Options, ShortOptions, function (parsed) { 45 | if (parsed.argv.remain.length < 1) { 46 | common.usage(usageStr, 1, 'machine required'); 47 | } 48 | 49 | var client = common.newClient(parsed); 50 | 51 | parsed.argv.remain.forEach(function (machine) { 52 | client.startMachine(machine, common.callback); 53 | }); 54 | }, usageStr); 55 | -------------------------------------------------------------------------------- /bin/sdc-startmachinefromsnapshot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'snapshot': String, 21 | 'url': url, 22 | 'version': Boolean, 23 | 'verbose': Boolean, 24 | 'user': String, 25 | 'role': String 26 | }; 27 | 28 | var ShortOptions = { 29 | 'a': ['--account'], 30 | 'd': ['--debug'], 31 | 'h': ['--help'], 32 | '?': ['--help'], 33 | 'k': ['--keyId'], 34 | 'n': ['--snapshot'], 35 | 'u': ['--url'], 36 | 'v': ['--verbose'], 37 | 'A': ['--user'] 38 | }; 39 | 40 | var usageStr = common.buildUsageString(Options); 41 | usageStr += ' machine_id'; 42 | usageStr += common.buildDetailedUsageString(Options); 43 | 44 | // --- Mainline 45 | 46 | common.parseArguments(Options, ShortOptions, function (parsed) { 47 | if (!parsed.snapshot) { 48 | common.usage(usageStr, 1, 'snapshot required'); 49 | } 50 | if (parsed.argv.remain.length < 1) { 51 | common.usage(usageStr, 1, 'machine required'); 52 | } 53 | 54 | var client = common.newClient(parsed); 55 | parsed.argv.remain.forEach(function (machine) { 56 | client.startMachineFromSnapshot(machine, 57 | parsed.snapshot, 58 | common.callback); 59 | }); 60 | }, usageStr); 61 | -------------------------------------------------------------------------------- /bin/sdc-stopmachine: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'help': Boolean, 19 | 'keyId': String, 20 | 'url': url, 21 | 'version': Boolean, 22 | 'verbose': Boolean, 23 | 'user': String, 24 | 'role': String 25 | }; 26 | 27 | var ShortOptions = { 28 | 'a': ['--account'], 29 | 'd': ['--debug'], 30 | 'h': ['--help'], 31 | '?': ['--help'], 32 | 'k': ['--keyId'], 33 | 'u': ['--url'], 34 | 'v': ['--verbose'], 35 | 'A': ['--user'] 36 | }; 37 | 38 | var usageStr = common.buildUsageString(Options); 39 | usageStr += ' machine_id'; 40 | usageStr += common.buildDetailedUsageString(Options); 41 | 42 | 43 | // --- Mainline 44 | 45 | common.parseArguments(Options, ShortOptions, function (parsed) { 46 | if (parsed.argv.remain.length < 1) { 47 | common.usage(usageStr, 1, 'machine required'); 48 | } 49 | 50 | var client = common.newClient(parsed); 51 | parsed.argv.remain.forEach(function (machine) { 52 | client.stopMachine(machine, common.callback); 53 | }); 54 | }, usageStr); 55 | -------------------------------------------------------------------------------- /bin/sdc-updateaccount: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'address': String, 17 | 'api-version': String, 18 | 'city': String, 19 | 'company': String, 20 | 'country': String, 21 | 'debug': Boolean, 22 | 'email': String, 23 | 'help': Boolean, 24 | 'keyId': String, 25 | 'name': String, 26 | 'phone': String, 27 | 'postal-code': String, 28 | 'state': String, 29 | 'surname': String, 30 | 'cns-disable': Boolean, 31 | 'cns-enable': Boolean, 32 | 'url': url, 33 | 'version': Boolean, 34 | 'verbose': Boolean, 35 | 'user': String, 36 | 'role': String 37 | }; 38 | 39 | var ShortOptions = { 40 | 'a': ['--account'], 41 | 'd': ['--debug'], 42 | 'h': ['--help'], 43 | '?': ['--help'], 44 | 'k': ['--keyId'], 45 | 'u': ['--url'], 46 | 'v': ['--verbose'], 47 | 'A': ['--user'] 48 | }; 49 | 50 | var usageStr = common.buildUsageString(Options); 51 | usageStr += common.buildDetailedUsageString(Options, { 52 | state: 'state or province', 53 | name: 'given name' 54 | }); 55 | 56 | // --- Mainline 57 | 58 | common.parseArguments(Options, ShortOptions, function (parsed) { 59 | var opts = {}; 60 | if (parsed.address) { 61 | opts.address = parsed.address; 62 | } 63 | 64 | if (parsed.city) { 65 | opts.city = parsed.city; 66 | } 67 | 68 | if (parsed.company) { 69 | opts.companyName = parsed.company; 70 | } 71 | 72 | if (parsed.country) { 73 | opts.country = parsed.country; 74 | } 75 | 76 | if (parsed.email) { 77 | opts.email = parsed.email; 78 | } 79 | 80 | if (parsed.name) { 81 | opts.firstName = parsed.name; 82 | } 83 | 84 | if (parsed.phone) { 85 | opts.phone = parsed.phone; 86 | } 87 | 88 | if (parsed['postal-code']) { 89 | opts.postalCode = parsed['postal-code']; 90 | } 91 | 92 | if (parsed.state) { 93 | opts.state = parsed.state; 94 | } 95 | 96 | if (parsed.surname) { 97 | opts.lastName = parsed.surname; 98 | } 99 | 100 | if (parsed['cns-enable']) { 101 | opts.triton_cns_enabled = true; 102 | } 103 | 104 | if (parsed['cns-disable']) { 105 | opts.triton_cns_enabled = false; 106 | } 107 | 108 | var client = common.newClient(parsed); 109 | client.updateAccount(opts, common.callback); 110 | }, usageStr); 111 | -------------------------------------------------------------------------------- /bin/sdc-updatefirewallrule: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | 8 | var common = require('../lib/cli_common'); 9 | 10 | 11 | 12 | // --- Globals 13 | 14 | var Options = { 15 | 'account': String, 16 | 'api-version': String, 17 | 'debug': Boolean, 18 | 'enabled': Boolean, 19 | 'help': Boolean, 20 | 'keyId': String, 21 | 'rule': String, 22 | 'url': url, 23 | 'version': Boolean, 24 | 'verbose': Boolean, 25 | 'user': String, 26 | 'role': String 27 | }; 28 | 29 | var ShortOptions = { 30 | 'a': ['--account'], 31 | 'd': ['--debug'], 32 | 'e': ['--enabled'], 33 | 'h': ['--help'], 34 | '?': ['--help'], 35 | 'k': ['--keyId'], 36 | 'r': ['--rule'], 37 | 'u': ['--url'], 38 | 'v': ['--verbose'], 39 | 'A': ['--user'] 40 | }; 41 | 42 | var usageStr = common.buildUsageString(Options) + ' fwrule_id'; 43 | usageStr += common.buildDetailedUsageString(Options); 44 | 45 | // --- Mainline 46 | 47 | common.parseArguments(Options, ShortOptions, function (parsed) { 48 | if (parsed.argv.remain.length < 1) { 49 | common.usage(usageStr, 1, 'fwrule_id required'); 50 | } 51 | 52 | var opts = {}; 53 | if (parsed.rule) { 54 | opts.rule = parsed.rule; 55 | } 56 | 57 | var client = common.newClient(parsed); 58 | parsed.argv.remain.forEach(function (fwrule) { 59 | client.updateFwRule(fwrule, opts, common.callback); 60 | }); 61 | }, usageStr); 62 | -------------------------------------------------------------------------------- /bin/sdc-updateimage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var fs = require('fs'); 7 | var https = require('https'); 8 | var path = require('path'); 9 | var url = require('url'); 10 | 11 | var common = require('../lib/cli_common'); 12 | 13 | 14 | 15 | // --- Globals 16 | 17 | var Options = { 18 | // General 19 | 'account': String, 20 | 'api-version': String, 21 | 'debug': Boolean, 22 | 'help': Boolean, 23 | 'keyId': String, 24 | 'url': url, 25 | 'version': Boolean, 26 | 'verbose': Boolean, 27 | // Specific to this command 28 | 'imageVersion': String, 29 | 'name': String, 30 | 'description': String, 31 | 'homepage': String, 32 | 'eula': String, 33 | 'acl': Array, 34 | 'tags': String, 35 | 'user': String, 36 | 'role': String 37 | }; 38 | 39 | var ShortOptions = { 40 | // General 41 | 'a': ['--account'], 42 | 'd': ['--debug'], 43 | 'h': ['--help'], 44 | '?': ['--help'], 45 | 'k': ['--keyId'], 46 | 'u': ['--url'], 47 | 'v': ['--verbose'], 48 | 'A': ['--user'] 49 | }; 50 | 51 | var usageStr = common.buildUsageString(Options); 52 | usageStr += common.buildDetailedUsageString(Options, { 53 | imageVersion: 'the version of the image', 54 | name: 'the name of the image', 55 | description: 'a description string for the image', 56 | homepage: 'a homepage URL for the image', 57 | eula: 'a EULA URL for the image', 58 | acl: 'a user ID to which to grant access to the new image, can be ' + 59 | 'specified multiple times for multiple users', 60 | tags: 'a JSON object of tags for the image, ' + 61 | 'e.g. --tags \'{"foo": "bar"}\'' 62 | }); 63 | 64 | 65 | // --- Mainline 66 | 67 | common.parseArguments(Options, ShortOptions, function (parsed) { 68 | var opts = {}; 69 | 70 | if (parsed.argv.remain.length < 1) { 71 | common.usage(usageStr, 1, 'image required'); 72 | } 73 | if (parsed.name) 74 | opts.name = parsed.name; 75 | if (parsed.imageVersion) 76 | opts.version = parsed.imageVersion; 77 | if (parsed.description) 78 | opts.description = parsed.description; 79 | if (parsed.homepage) 80 | opts.homepage = parsed.homepage; 81 | if (parsed.eula) 82 | opts.eula = parsed.eula; 83 | if (parsed.acl) 84 | opts.acl = parsed.acl; 85 | if (parsed.tags) 86 | opts.tags = JSON.parse(parsed.tags); 87 | 88 | var client = common.newClient(parsed); 89 | parsed.argv.remain.forEach(function (image) { 90 | client.updateImage(image, opts, common.callback); 91 | }); 92 | 93 | }, usageStr); 94 | -------------------------------------------------------------------------------- /bin/sdc-updatemachinemetadata: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // -*- mode: js -*- 3 | // vim: set filetype=javascript : 4 | // Copyright 2013 Joyent, Inc. All rights reserved. 5 | 6 | var url = require('url'); 7 | var fs = require('fs'); 8 | 9 | var common = require('../lib/cli_common'); 10 | 11 | 12 | 13 | // --- Globals 14 | 15 | var Options = { 16 | 'account': String, 17 | 'api-version': String, 18 | 'debug': Boolean, 19 | 'help': Boolean, 20 | 'keyId': String, 21 | 'metadata': [String, Array], 22 | 'metadata-file': [String, Array], 23 | 'url': url, 24 | 'version': Boolean, 25 | 'verbose': Boolean, 26 | 'user': String, 27 | 'role': String 28 | }; 29 | 30 | var ShortOptions = { 31 | 'a': ['--account'], 32 | 'd': ['--debug'], 33 | 'h': ['--help'], 34 | '?': ['--help'], 35 | 'k': ['--keyId'], 36 | 'm': ['--metadata'], 37 | 'M': ['--metadata-file'], 38 | 'u': ['--url'], 39 | 'v': ['--verbose'], 40 | 'A': ['--user'] 41 | }; 42 | 43 | var usageStr = common.buildUsageString(Options); 44 | usageStr += ' machine_id'; 45 | usageStr += common.buildDetailedUsageString(Options); 46 | 47 | // --- Mainline 48 | 49 | common.parseArguments(Options, ShortOptions, function (parsed) { 50 | 51 | if (parsed.argv.remain.length < 1) { 52 | common.usage(usageStr, 1, 'machine required'); 53 | } 54 | 55 | if (!parsed.metadata && !parsed['metadata-file']) { 56 | common.usage(usageStr, 1, '--metadata or --metadata-file required'); 57 | } 58 | 59 | var metadata = {}; 60 | 61 | metadata = common.mergeObjects(metadata, common.parseMetadata( 62 | parsed['metadata-file'], true)); 63 | metadata = common.mergeObjects(metadata, common.parseMetadata( 64 | parsed['metadata'], false)); 65 | 66 | var client = common.newClient(parsed); 67 | parsed.argv.remain.forEach(function (machine) { 68 | client.updateMachineMetadata(machine, metadata, common.callback); 69 | }); 70 | }, usageStr); 71 | -------------------------------------------------------------------------------- /lib/cli/config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Joyent, Inc. 3 | */ 4 | 5 | /* 6 | * Config methods for the CloudAPI object 7 | */ 8 | 9 | var paths = require('./paths'); 10 | var sprintf = require('util').format; 11 | var validate = require('./validate'); 12 | 13 | 14 | // --- Exports 15 | 16 | 17 | /** 18 | * Retrieves a user's config object. 19 | * 20 | * Returns an object. 21 | * 22 | * @param {String} account (optional) the login name of the account. 23 | * @param {Function} callback of the form f(err, conf). 24 | * @param {Boolean} noCache optional flag to force skipping the cache. 25 | * @throws {TypeError} on bad input. 26 | */ 27 | function getConfig(account, callback, noCache) { 28 | var self = this; 29 | 30 | if (typeof (account) === 'function') { 31 | callback = account; 32 | account = this.account; 33 | } 34 | 35 | account = validate.account(account); 36 | validate.callback(callback); 37 | 38 | return self._request(sprintf(paths.config, account), null, function (req) { 39 | return self._get(req, callback, noCache); 40 | }); 41 | } 42 | 43 | 44 | /** 45 | * Updates a user's config object. 46 | * 47 | * Returns the updated config object. 48 | * 49 | * @param {String} account (optional) the login name of the account. 50 | * @param {Object} options update params to be passed to the API. 51 | * @param {Function} callback of the form f(err, conf). 52 | * @throws {TypeError} on bad input. 53 | */ 54 | function updateConfig(account, options, callback) { 55 | var self = this; 56 | 57 | if (typeof (options) === 'function') { 58 | callback = options; 59 | options = account; 60 | account = this.account; 61 | } 62 | 63 | account = validate.account(account); 64 | validate.options(options); 65 | validate.callback(callback); 66 | 67 | return self._request(sprintf(paths.config, account), options, 68 | function (req) { 69 | return self._put(req, callback); 70 | }); 71 | } 72 | 73 | 74 | 75 | module.exports = { 76 | getConfig: getConfig, 77 | updateConfig: updateConfig 78 | }; 79 | -------------------------------------------------------------------------------- /lib/cli/fabric-nets.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Joyent, Inc. 3 | */ 4 | 5 | /* 6 | * Fabric network methods for the CloudAPI object 7 | */ 8 | 9 | var paths = require('./paths'); 10 | var sprintf = require('util').format; 11 | var validate = require('./validate'); 12 | 13 | 14 | 15 | // --- Exports 16 | 17 | 18 | 19 | /** 20 | * Creates a fabric network. 21 | * 22 | * Returns a JS object (the created network). 23 | * 24 | * @param {String} account (optional) the login name of the account. 25 | * @param {Object} options object to be passed to the API 26 | * @param {Function} callback of the form f(err, network). 27 | * @throws {TypeError} on bad input. 28 | */ 29 | function createFabricNetwork(account, options, callback) { 30 | var self = this; 31 | var opts; 32 | 33 | if (typeof (options) === 'function') { 34 | callback = options; 35 | options = account; 36 | account = this.account; 37 | } 38 | 39 | account = validate.account(account); 40 | opts = validate.networkOptions(options); 41 | validate.callback(callback); 42 | 43 | return self._request(sprintf(paths.fabricNetworks, account, opts.vlan_id), 44 | opts, function (req) { 45 | return self._post(req, callback); 46 | }); 47 | } 48 | 49 | 50 | /** 51 | * Deletes a fabric network. 52 | * 53 | * @param {String} account (optional) the login name of the account. 54 | * @param {Number} vlanId the ID of the VLAN the network is on. 55 | * @param {String} network the ID of the network. 56 | * @param {Function} callback of the form f(err). 57 | * @param {Boolean} noCache optional flag to force skipping the cache. 58 | * @throws {TypeError} on bad input. 59 | */ 60 | function deleteFabricNetwork(account, vlanId, network, callback, noCache) { 61 | var self = this; 62 | 63 | if (typeof (network) === 'function') { 64 | noCache = callback; 65 | callback = network; 66 | network = vlanId; 67 | vlanId = account; 68 | account = this.account; 69 | } 70 | 71 | account = validate.account(account); 72 | vlanId = validate.vlanId(vlanId); 73 | validate.network(network); 74 | validate.callback(callback); 75 | 76 | return self._request(sprintf(paths.fabricNetwork, account, vlanId, 77 | network), null, function (req) { 78 | return self._del(req, callback, noCache); 79 | }); 80 | } 81 | 82 | 83 | /** 84 | * Retrieves a fabric network. 85 | * 86 | * Returns an object. 87 | * 88 | * @param {String} account (optional) the login name of the account. 89 | * @param {String} network the ID of the network. 90 | * @param {Function} callback of the form f(err, network). 91 | * @param {Boolean} noCache optional flag to force skipping the cache. 92 | * @throws {TypeError} on bad input. 93 | */ 94 | function getFabricNetwork(account, network, callback, noCache) { 95 | var self = this; 96 | 97 | if (typeof (network) === 'function') { 98 | noCache = callback; 99 | callback = network; 100 | network = account; 101 | account = this.account; 102 | } 103 | 104 | account = validate.account(account); 105 | validate.network(network); 106 | validate.callback(callback); 107 | 108 | return self._request(sprintf(paths.network, account, network), null, 109 | function (req) { 110 | return self._get(req, callback, noCache); 111 | }); 112 | } 113 | 114 | 115 | /** 116 | * Lists all fabric networks for a given user. 117 | * 118 | * Returns an array of objects. 119 | * 120 | * @param {String} account (optional) the login name of the account. 121 | * @param {Object} options object containing: 122 | * - {Number} vlan_id (optional) VLAN ID to filter on. 123 | * @param {Function} callback of the form f(err, networks). 124 | * @param {Boolean} noCache optional flag to force skipping the cache. 125 | * @throws {TypeError} on bad input. 126 | */ 127 | function listFabricNetworks(account, options, callback, noCache) { 128 | var self = this; 129 | var vlanId; 130 | 131 | if (typeof (options) === 'function') { 132 | noCache = callback; 133 | callback = options; 134 | options = account; 135 | account = this.account; 136 | } 137 | 138 | validate.options(options); 139 | if (options.hasOwnProperty('vlan_id')) { 140 | vlanId = validate.vlanId(options.vlan_id); 141 | } 142 | 143 | account = validate.account(account); 144 | validate.callback(callback); 145 | 146 | if (vlanId !== undefined) { 147 | return self._request(sprintf(paths.fabricNetworks, account, vlanId), {}, 148 | function (req) { 149 | return self._get(req, callback, noCache); 150 | }); 151 | } 152 | 153 | return self._request(sprintf(paths.networks, account), {}, function (req) { 154 | req.query.fabric = true; 155 | return self._get(req, callback, noCache); 156 | }); 157 | } 158 | 159 | 160 | 161 | module.exports = { 162 | createFabricNetwork: createFabricNetwork, 163 | deleteFabricNetwork: deleteFabricNetwork, 164 | getFabricNetwork: getFabricNetwork, 165 | listFabricNetworks: listFabricNetworks 166 | }; 167 | -------------------------------------------------------------------------------- /lib/cli/fabric-vlans.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Joyent, Inc. 3 | */ 4 | 5 | /* 6 | * Fabric VLAN methods for the CloudAPI object 7 | */ 8 | 9 | var paths = require('./paths'); 10 | var sprintf = require('util').format; 11 | var validate = require('./validate'); 12 | 13 | 14 | 15 | // --- Exports 16 | 17 | 18 | 19 | /** 20 | * Creates a fabric VLAN. 21 | * 22 | * Returns a JS object (the created VLAN). 23 | * 24 | * @param {String} account (optional) the login name of the account. 25 | * @param {Object} options object containing: 26 | * - {Number} vlan_id (required) VLAN ID 27 | * - {String} name (required) name 28 | * - {String} description (optional) description 29 | * @param {Function} callback of the form f(err, vlan). 30 | * @throws {TypeError} on bad input. 31 | */ 32 | function createFabricVlan(account, options, callback) { 33 | var self = this; 34 | var opts; 35 | 36 | if (typeof (options) === 'function') { 37 | callback = options; 38 | options = account; 39 | account = this.account; 40 | } 41 | 42 | account = validate.account(account); 43 | opts = validate.vlanOptions(options); 44 | validate.callback(callback); 45 | 46 | return self._request(sprintf(paths.vlans, account), opts, function (req) { 47 | return self._post(req, callback); 48 | }); 49 | } 50 | 51 | 52 | /** 53 | * Deletes a fabric VLAN. 54 | * 55 | * @param {String} account (optional) the login name of the account. 56 | * @param {Number} vlanId the ID of the VLAN. 57 | * @param {Function} callback of the form f(err, vlan). 58 | * @param {Boolean} noCache optional flag to force skipping the cache. 59 | * @throws {TypeError} on bad input. 60 | */ 61 | function deleteFabricVlan(account, vlanId, callback, noCache) { 62 | var self = this; 63 | 64 | if (typeof (vlanId) === 'function') { 65 | noCache = callback; 66 | callback = vlanId; 67 | vlanId = account; 68 | account = this.account; 69 | } 70 | 71 | account = validate.account(account); 72 | vlanId = validate.vlanId(vlanId); 73 | validate.callback(callback); 74 | 75 | return self._request(sprintf(paths.vlan, account, vlanId), null, 76 | function (req) { 77 | return self._del(req, callback, noCache); 78 | }); 79 | } 80 | 81 | 82 | /** 83 | * Retrieves a fabric VLAN. 84 | * 85 | * Returns an object. 86 | * 87 | * @param {String} account (optional) the login name of the account. 88 | * @param {Number} vlanId the ID of the VLAN. 89 | * @param {Function} callback of the form f(err, vlan). 90 | * @param {Boolean} noCache optional flag to force skipping the cache. 91 | * @throws {TypeError} on bad input. 92 | */ 93 | function getFabricVlan(account, vlanId, callback, noCache) { 94 | var self = this; 95 | 96 | if (typeof (vlanId) === 'function') { 97 | noCache = callback; 98 | callback = vlanId; 99 | vlanId = account; 100 | account = this.account; 101 | } 102 | 103 | account = validate.account(account); 104 | vlanId = validate.vlanId(vlanId); 105 | validate.callback(callback); 106 | 107 | return self._request(sprintf(paths.vlan, account, vlanId), null, 108 | function (req) { 109 | return self._get(req, callback, noCache); 110 | }); 111 | } 112 | 113 | 114 | /** 115 | * Lists all fabric VLANs for a given user. 116 | * 117 | * Returns an array of objects. 118 | * 119 | * @param {String} account (optional) the login name of the account. 120 | * @param {Function} callback of the form f(err, vlans). 121 | * @param {Boolean} noCache optional flag to force skipping the cache. 122 | * @throws {TypeError} on bad input. 123 | */ 124 | function listFabricVlans(account, callback, noCache) { 125 | var self = this; 126 | 127 | if (typeof (account) === 'function') { 128 | noCache = callback; 129 | callback = account; 130 | account = this.account; 131 | } 132 | 133 | account = validate.account(account); 134 | validate.callback(callback); 135 | 136 | self._request(sprintf(paths.vlans, account), null, function (req) { 137 | return self._get(req, callback, noCache); 138 | }); 139 | } 140 | 141 | 142 | /** 143 | * Updates a fabric VLAN. 144 | * 145 | * Returns a JS object (the updated VLAN). 146 | * 147 | * @param {String} account (optional) the login name of the account. 148 | * @param {Number} vlanID ID of the VLAN to update. 149 | * @param {Object} options object containing: 150 | * - {String} name (optional) name 151 | * - {String} description (optional) description 152 | * @param {Function} callback of the form f(err, vlan). 153 | * @throws {TypeError} on bad input. 154 | */ 155 | function updateFabricVlan(account, vlanId, options, callback, noCache) { 156 | var self = this; 157 | var opts; 158 | 159 | if (typeof (options) === 'function') { 160 | noCache = callback; 161 | callback = options; 162 | options = vlanId; 163 | vlanId = account; 164 | account = this.account; 165 | } 166 | 167 | account = validate.account(account); 168 | vlanId = validate.vlanId(vlanId); 169 | opts = validate.vlanOptions(options); 170 | validate.callback(callback); 171 | 172 | return self._request(sprintf(paths.vlan, account, vlanId), opts, 173 | function (req) { 174 | return self._put(req, callback); 175 | }); 176 | } 177 | 178 | 179 | 180 | module.exports = { 181 | createFabricVlan: createFabricVlan, 182 | deleteFabricVlan: deleteFabricVlan, 183 | getFabricVlan: getFabricVlan, 184 | listFabricVlans: listFabricVlans, 185 | updateFabricVlan: updateFabricVlan 186 | }; 187 | -------------------------------------------------------------------------------- /lib/cli/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Joyent, Inc. 3 | */ 4 | 5 | /* 6 | * Exports all of the CloudAPI methods broken out into separate files 7 | */ 8 | 9 | [ 10 | require('./config'), 11 | require('./fabric-nets'), 12 | require('./fabric-vlans') 13 | ].forEach(function (mod) { 14 | for (var e in mod) { 15 | module.exports[e] = mod[e]; 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /lib/cli/paths.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Joyent, Inc. 3 | */ 4 | 5 | /* 6 | * REST paths 7 | */ 8 | 9 | 10 | 11 | // --- Exports 12 | 13 | 14 | 15 | module.exports = { 16 | config: '/%s/config', 17 | fabricNetwork: '/%s/fabrics/default/vlans/%d/networks/%s', 18 | fabricNetworks: '/%s/fabrics/default/vlans/%d/networks', 19 | network: '%s/networks/%s', 20 | networks: '%s/networks', 21 | vlan: '/%s/fabrics/default/vlans/%d', 22 | vlans: '/%s/fabrics/default/vlans' 23 | }; 24 | -------------------------------------------------------------------------------- /lib/cli/validate.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Joyent, Inc. 3 | */ 4 | 5 | /* 6 | * Shared validation functions 7 | */ 8 | 9 | var util = require('util'); 10 | 11 | 12 | 13 | /** 14 | * Accepts an account object or string, and validates that it's actually a 15 | * string. Returns the account string. 16 | */ 17 | function validateAccount(account) { 18 | if (typeof (account) === 'object') { 19 | account = account.login; 20 | } 21 | 22 | if (typeof (account) !== 'string') { 23 | throw new TypeError('account (string) required'); 24 | } 25 | 26 | return account; 27 | } 28 | 29 | 30 | /** 31 | * Validates that callback is a function. 32 | */ 33 | function validateCallback(callback) { 34 | if (typeof (callback) !== 'function') { 35 | throw new TypeError('callback (function) required'); 36 | } 37 | } 38 | 39 | 40 | /** 41 | * Validates that network is a string. 42 | */ 43 | function validateNetwork(network) { 44 | if (typeof (network) !== 'string') { 45 | throw new TypeError('network (string) required'); 46 | } 47 | } 48 | 49 | 50 | /** 51 | * Validates that options is an object with the correct options 52 | */ 53 | function validateNetworkOptions(options) { 54 | var opts = {}; 55 | 56 | validateOptions(options); 57 | if (options.hasOwnProperty('vlan_id')) { 58 | opts.vlan_id = validateVlanId(options.vlan_id); 59 | } 60 | 61 | ['gateway', 'provision_end_ip', 'provision_start_ip', 'subnet', 62 | 'description', 'name'].forEach(function (p) { 63 | if (options.hasOwnProperty(p)) { 64 | if (typeof (options[p]) !== 'string') { 65 | throw new TypeError('options.' + p + ' (string) required'); 66 | } 67 | opts[p] = options[p]; 68 | } 69 | }); 70 | 71 | if (options.hasOwnProperty('no_internet_nat')) { 72 | opts.internet_nat = false; 73 | } 74 | 75 | if (options.hasOwnProperty('resolvers')) { 76 | opts.resolvers = validateResolvers(options.resolvers); 77 | } 78 | 79 | if (options.hasOwnProperty('routes')) { 80 | opts.routes = validateRoutes(options.routes); 81 | } 82 | 83 | return opts; 84 | } 85 | 86 | 87 | /** 88 | * Validates that options is an object. 89 | */ 90 | function validateOptions(options) { 91 | if (typeof (options) !== 'object') { 92 | throw new TypeError('options (object) required'); 93 | } 94 | } 95 | 96 | 97 | /** 98 | * Validates that resolvers is either an object or an array of strings 99 | */ 100 | function validateResolvers(resolvers) { 101 | var res = []; 102 | 103 | if (typeof (resolvers) !== 'string' && !util.isArray(resolvers)) { 104 | throw new TypeError('resolvers (array of strings) required'); 105 | } 106 | 107 | if (typeof (resolvers) === 'string') { 108 | res = resolvers.split(','); 109 | } else { 110 | res = resolvers; 111 | } 112 | 113 | res.forEach(function (r) { 114 | if (typeof (r) !== 'string') { 115 | throw new TypeError('resolvers (array of strings) required'); 116 | } 117 | }); 118 | 119 | return res; 120 | } 121 | 122 | 123 | /** 124 | * A very simple validation that route objects contain string values. 125 | */ 126 | function validateRoutes(routes) { 127 | if (typeof (routes) !== 'object') { 128 | throw new TypeError('routes (object) required'); 129 | } 130 | 131 | Object.keys(routes).forEach(function (net) { 132 | var route = routes[net]; 133 | 134 | if (typeof (route) !== 'string') { 135 | throw new TypeError('route (string in object) required'); 136 | } 137 | }); 138 | 139 | return routes; 140 | } 141 | 142 | 143 | /** 144 | * Validates that vlanId is a number, or string that can be turned into a 145 | * number. Returns the ID as a number. 146 | */ 147 | function validateVlanId(vlanId) { 148 | var num = Number(vlanId); 149 | 150 | if (isNaN(num)) { 151 | throw new TypeError('vlan_id (number) required'); 152 | } 153 | 154 | return num; 155 | } 156 | 157 | 158 | /** 159 | * Validates that options is an object with the correct options 160 | */ 161 | function validateVlanOptions(options) { 162 | var opts = {}; 163 | 164 | validateOptions(options); 165 | if (options.hasOwnProperty('vlan_id')) { 166 | opts.vlan_id = validateVlanId(options.vlan_id); 167 | } 168 | 169 | if (options.hasOwnProperty('name')) { 170 | opts.name = options.name; 171 | } 172 | 173 | if (options.hasOwnProperty('description')) { 174 | opts.description = options.description; 175 | } 176 | 177 | return opts; 178 | } 179 | 180 | 181 | 182 | module.exports = { 183 | account: validateAccount, 184 | callback: validateCallback, 185 | network: validateNetwork, 186 | networkOptions: validateNetworkOptions, 187 | options: validateOptions, 188 | vlanId: validateVlanId, 189 | vlanOptions: validateVlanOptions 190 | }; 191 | -------------------------------------------------------------------------------- /lib/flushingexit.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Joyent, Inc. 3 | */ 4 | 5 | /* 6 | * Exported `emit` and `exit` methods to replace `process.stdout.write` and 7 | * `process.exit` such that stdout is flushed on process.exit. 8 | * 9 | * Code adapted from joyent/manta-thoth. 10 | */ 11 | 12 | var util = require('util'); 13 | 14 | 15 | var writable = true; 16 | 17 | 18 | function exit(code, asynchronous) { 19 | var exiting = {}; 20 | 21 | /* 22 | * Unfortunately, node's process.exit() does no flushing of output 23 | * for us. And because we have scattered state that we don't want to 24 | * bother cleaning up to induce a proper exit, to correctly exit we 25 | * need to not actually exit until stdout is known to be writable 26 | * (indicating that it has been successfully flushed). 27 | */ 28 | if (writable) 29 | process.exit(code); 30 | 31 | setTimeout(function () { exit(code, true); }, 10); 32 | 33 | if (asynchronous) 34 | return; 35 | 36 | /* 37 | * If we have been called synchronously, callers are expecting exit() 38 | * to not return. To effect this, we throw a bogus exception and 39 | * then use an installed uncaughtException listener to catch this 40 | * sentinel and ignore it -- which allows I/O to be asynchronously 41 | * flushed and process.exit() to be ultimately called. 42 | */ 43 | process.addListener('uncaughtException', function (err) { 44 | if (err === exiting) 45 | return; 46 | 47 | process.stderr.write('uncaught exception: ' + 48 | util.inspect(err) + '\n'); 49 | process.exit(1); 50 | }); 51 | 52 | throw (exiting); 53 | } 54 | 55 | process.stdout.on('drain', function () { writable = true; }); 56 | 57 | function emit(str) { 58 | writable = process.stdout.write(str + 59 | (str[str.length - 1] != '\n' ? '\n' : '')); 60 | } 61 | 62 | 63 | 64 | module.exports = { 65 | emit: emit, 66 | exit: exit 67 | }; 68 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Joyent, Inc. All rights reserved. 2 | 3 | var cloudapi = require('./cloudapi'); 4 | var auth = require('smartdc-auth'); 5 | 6 | module.exports = { 7 | CloudAPI: cloudapi.CloudAPI, 8 | createClient: cloudapi.createClient, 9 | cliSigner: auth.cliSigner, 10 | privateKeySigner: auth.privateKeySigner, 11 | sshAgentSigner: auth.sshAgentSigner, 12 | signUrl: auth.signUrl, 13 | loadSSHKey: auth.loadSSHKey 14 | }; 15 | -------------------------------------------------------------------------------- /lib/shared.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Joyent, Inc. 3 | */ 4 | 5 | var auth = require('smartdc-auth'); 6 | var bunyan = require('bunyan'); 7 | var fs = require('fs'); 8 | var path = require('path'); 9 | var util = require('util'); 10 | 11 | var flushingexit = require('./flushingexit'); 12 | var pkg = require('../package.json'); 13 | var smartdc = require('../lib/cloudapi'), 14 | CloudAPI = smartdc.CloudAPI; 15 | 16 | 17 | 18 | var SSH_HEX_KEY_ID_RE = /^(MD5:)?[0-9a-f]{2}(?:\:[0-9a-f]{2}){15}$/i; 19 | /*JSSTYLED*/ 20 | var SSH_BASE64_KEY_ID_RE = /^[A-Z0-9]+:[-A-Za-z0-9+\/=]+$/; 21 | var URL_RE = '^https?\://.+'; 22 | 23 | 24 | /** 25 | * Print a CLI error for the given error object. 26 | * 27 | * @param error {Error} The error to print 28 | * @param options {Object} Optional: 29 | * - `command` {String} The CLI command name. Else a guess is made. 30 | */ 31 | function printErr(err) { 32 | var code = (err.body && err.body.code ? err.body.code : err.code); 33 | // if there's no message, it's not certain there will be syscall, but 34 | // worth a try, since that's a common class of error 35 | var msg = (err.body && err.body.message ? err.body.message : err.syscall); 36 | var cmd = path.basename(process.argv[1]); 37 | 38 | if (err.body && err.body.errors) { 39 | var details = err.body.errors.map(function (e) { 40 | return e.code + ', ' + e.field + ': ' + e.message; 41 | }).join(', '); 42 | } 43 | 44 | console.error('%s: error%s: %s%s', 45 | cmd, 46 | (code ? util.format(' (%s)', code) : ''), 47 | msg, 48 | (details ? util.format(' (%s)', details) : '')); 49 | } 50 | 51 | 52 | /** 53 | * We want to support the passing of multiple types of arrays to command args. 54 | * This here churns through the various possibilities (same flag multiple times, 55 | * passing in CSV, JSON) and returns a proper array. 56 | * 57 | * @param obj {Object} Array containing command-line args from the same flag 58 | */ 59 | function argToArray(obj) { 60 | if (!obj || obj.length !== 1) 61 | return obj; 62 | 63 | obj = obj[0]; 64 | 65 | try { 66 | return JSON.parse(obj); 67 | } catch (e) {} 68 | 69 | return obj.split(','); 70 | } 71 | 72 | 73 | /** 74 | * Common callback for all CLI operations. 75 | * 76 | * @param {Error} err optional error object. 77 | * @param {Object} obj optional response object. 78 | */ 79 | function commonCb(err, obj, headers) { 80 | if (err) { 81 | if (err.statusCode === 410) { 82 | console.error('Object is Gone (410)'); 83 | } else { 84 | printErr(err); 85 | } 86 | 87 | process.exit(3); 88 | } 89 | 90 | if (obj) { 91 | flushingexit.emit(JSON.stringify(obj, null, 2)); 92 | } 93 | flushingexit.exit(0); 94 | } 95 | 96 | function checkRequiredOptions(opts, args, callback) { 97 | var self = this; 98 | 99 | if (opts.version) { 100 | flushingexit.emit(this.name, pkg.version); 101 | return callback(false); 102 | } 103 | 104 | this.opts = opts; 105 | 106 | if (opts.debug || opts.verbose) { 107 | process.env.DEBUG = 1; 108 | opts.logLevel = 'trace'; 109 | } 110 | 111 | if (typeof (opts.keyId) === 'undefined') { 112 | return callback(new Error( 113 | 'Either --key or (env) SDC_KEY_ID must be specified')); 114 | } 115 | 116 | if (!opts.keyId.match(SSH_HEX_KEY_ID_RE) && 117 | !opts.keyId.match(SSH_BASE64_KEY_ID_RE)) { 118 | return callback(new Error( 119 | '--keyId or (env) SDC_KEY_ID must be a valid SSH key ID')); 120 | } 121 | 122 | if (!opts.account) { 123 | return callback(new Error( 124 | 'Either --account or (env) SDC_ACCOUNT must be specified')); 125 | } 126 | 127 | var halves = opts.account.split('/'); 128 | if (halves.length === 2) { 129 | opts.account = halves[0]; 130 | 131 | if (!opts.user) { 132 | opts.user = halves[1]; 133 | } 134 | 135 | console.warn('Warning: The given --account or SDC_ACCOUNT ' + 136 | 'appears to be an account/user combination. Please ' + 137 | 'split between --account and --user (or SDC_ACCOUNT ' + 138 | 'and SDC_USER) to avoid unexpected behaviours'); 139 | } 140 | 141 | if (!opts.url) { 142 | return callback(new Error( 143 | 'Either --url or (env) SDC_URL must be specified')); 144 | } 145 | 146 | if (!opts.url.match(URL_RE)) { 147 | return callback(new Error( 148 | '--url or (env) SDC_URL must be a valid URL')); 149 | } 150 | 151 | opts.sign = auth.cliSigner({ 152 | keyId: opts.keyId, 153 | user: opts.account, 154 | subuser: opts.user 155 | }); 156 | 157 | if (opts.role) { 158 | opts.asRole = opts.role; 159 | delete opts.role; 160 | } 161 | 162 | this.__defineGetter__('cloudapi', function () { 163 | if (self._cloudapi === undefined) { 164 | self._cloudapi = new CloudAPI(opts); 165 | } 166 | return (self._cloudapi); 167 | }); 168 | 169 | return callback(); 170 | } 171 | 172 | var KV_RE = new RegExp('^([^=]+)=(.*)$'); 173 | 174 | function parseMetadata(metas, fromFiles) { 175 | var i; 176 | var m; 177 | var out = {}; 178 | 179 | if (!metas) { 180 | return (out); 181 | } 182 | 183 | for (i = 0; i < metas.length; i++) { 184 | if (!(m = KV_RE.exec(metas[i]))) { 185 | var example = fromFiles ? 'foo=filename.txt' : 'foo=bar'; 186 | console.error(metas[i] + ' is invalid metadata; try ' + example); 187 | process.exit(1); 188 | } 189 | 190 | if (fromFiles) { 191 | try { 192 | out[m[1]] = fs.readFileSync(m[2], 'utf-8'); 193 | } catch (ex) { 194 | console.error('could not load metadata from: %s: %s', 195 | m[1], ex.message); 196 | process.exit(1); 197 | } 198 | } else { 199 | out[m[1]] = m[2]; 200 | } 201 | } 202 | 203 | return (out); 204 | } 205 | 206 | var DEFAULT_OPTIONS = [ 207 | { 208 | names: ['help', 'h', '?'], 209 | type: 'bool', 210 | help: 'Print help and exit.' 211 | }, { 212 | name: 'version', 213 | type: 'bool', 214 | help: 'Print version and exit.' 215 | }, { 216 | names: ['debug', 'd'], 217 | type: 'bool', 218 | help: 'equivalent to --verbose' 219 | }, 220 | { 221 | names: ['api-version'], 222 | type: 'string', 223 | help: 'Which version of Cloudapi\'s API to use', 224 | env: 'SDC_API_VERSION' 225 | }, 226 | { 227 | names: ['account', 'a'], 228 | type: 'string', 229 | help: 'account name', 230 | env: 'SDC_ACCOUNT' 231 | }, 232 | { 233 | names: ['user', 'A'], 234 | type: 'string', 235 | help: 'account sub-user login', 236 | env: 'SDC_USER' 237 | }, 238 | { 239 | names: ['url', 'u'], 240 | type: 'string', 241 | help: 'url for SmartDataCenter API', 242 | env: 'SDC_URL' 243 | }, 244 | { 245 | names: ['verbose', 'v'], 246 | type: 'bool', 247 | help: 'display additional internal details during request' 248 | }, 249 | 250 | { 251 | names: ['keyId', 'k'], 252 | type: 'string', 253 | help: 'your ssh key fingerprint', 254 | env: 'SDC_KEY_ID' 255 | }, 256 | { 257 | names: ['role'], 258 | type: 'string', 259 | help: 'non-default roles to make request with' 260 | } 261 | ]; 262 | 263 | module.exports = { 264 | emit: flushingexit.emit, 265 | exit: flushingexit.exit, 266 | printErr: printErr, 267 | argToArray: argToArray, 268 | commonCb: commonCb, 269 | checkRequiredOptions: checkRequiredOptions, 270 | DEFAULT_OPTIONS: DEFAULT_OPTIONS, 271 | parseMetadata: parseMetadata 272 | }; 273 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Joyent, Inc. http://www.joyent.com", 3 | "name": "smartdc", 4 | "description": "Old Client SDK and CLI for the Joyent SmartDataCenter API", 5 | "version": "9.0.1", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/joyent/node-smartdc.git" 9 | }, 10 | "main": "lib/index.js", 11 | "engines": { 12 | "node": ">=0.8.14" 13 | }, 14 | "directories": { 15 | "bin": "./bin", 16 | "lib": "./lib" 17 | }, 18 | "dependencies": { 19 | "assert-plus": "0.1.5", 20 | "lru-cache": "2.2.0", 21 | "nopt": "2.0.0", 22 | "restify": "4.0.3", 23 | "bunyan": "1.5.1", 24 | "clone": "0.1.6", 25 | "smartdc-auth": "2.3.1", 26 | "cmdln": "3.2.1", 27 | "dashdash": "1.7.3", 28 | "vasync": "1.6.2" 29 | }, 30 | "devDependencies": { 31 | "tape": "3.5.0", 32 | "node-uuid": "1.4.2" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/.ssh/id_rsa: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAza+KvczCrcpQGRq9e347VHx9oEvuhseJt0ydR+UMAveyQprU 3 | 4JHvzwUUhGnG147GJQYyfQ4nzaSG62az/YThoZJzw8gtxGkVHv0wlAlRkYhxbKbq 4 | 8WQIh73xDQkHLw2lXLvf7Tt0Mhow0qGEmkOjTb5fPsj2evphrV3jJ15QlhL4cv33 5 | t8jVadIrL0iIpwdqWiPqUKpsrSfKJghkoXS6quPy78P820TnuoBG+/Ppr8Kkvn6m 6 | A7j4xnOQ12QE6jPK4zkikj5ZczSC4fTG0d3BwwX4VYu+4y/T/BX0L9VNUmQU22Y+ 7 | /MRXAUZxsa8VhNB+xXF5XSubyb2n6loMWWaYGwIDAQABAoIBAQDCJt9JxYxGS+BL 8 | sigF9+O9Hj3fH42p/5QJR/J2uMgbzP+hS1GCIX9B5MO3MbmWI5j5vd3OmZwMyy7n 9 | 6Wwg9FufDgTkW4KIEcD0HX7LXfh27VpTe0PuU8SRjUOKUGlNiw36eQUog6Rs3rgT 10 | Oo9Wpl3xtq9lLoErGEk3QpZ2xNpArTfsN9N3pdmD4sv7wmJq0PZQyej482g9R0g/ 11 | 5k2ni6JpcEifzBQ6Bzx3EV2l9UipEIqbqDpMOtYFCpnLQhEaDfUribqXINGIsjiq 12 | VyFa3Mbg/eayqG3UX3rVTCif2NnW2ojl4mMgWCyxgWfb4Jg1trc3v7X4SXfbgPWD 13 | WcfrOhOhAoGBAP7ZC8KHAnjujwvXf3PxVNm6CTs5evbByQVyxNciGxRuOomJIR4D 14 | euqepQ4PuNAabnrbMyQWXpibIKpmLnBVoj1q0IMXYvi2MZF5e2tH/Gx01UvxamHh 15 | bKhHmp9ImHhVl6kObXOdNvLVTt/BI5FZBblvm7qOoiVwImPbqqVHP7Q5AoGBAM6d 16 | mNsrW0iV/nP1m7d8mcFw74PI0FNlNdfUoePUgokO0t5OU0Ri/lPBDCRGlvVF3pj1 17 | HnmwroNtdWr9oPVB6km8193fb2zIWe53tj+6yRFQpz5elrSPfeZaZXlJZAGCCCdN 18 | gBggWQFPeQiT54aPywPpcTZHIs72XBqQ6QsIPrbzAoGAdW2hg5MeSobyFuzHZ69N 19 | /70/P7DuvgDxFbeah97JR5K7GmC7h87mtnE/cMlByXJEcgvK9tfv4rWoSZwnzc9H 20 | oLE1PxJpolyhXnzxp69V2svC9OlasZtjq+7Cip6y0s/twBJL0Lgid6ZeX6/pKbIx 21 | dw68XSwX/tQ6pHS1ns7DxdECgYBJbBWapNCefbbbjEcWsC+PX0uuABmP2SKGHSie 22 | ZrEwdVUX7KuIXMlWB/8BkRgp9vdAUbLPuap6R9Z2+8RMA213YKUxUiotdREIPgBE 23 | q2KyRX/5GPHjHi62Qh9XN25TXtr45ICFklEutwgitTSMS+Lv8+/oQuUquL9ILYCz 24 | C+4FYwKBgQDE9yZTUpJjG2424z6bl/MHzwl5RB4pMronp0BbeVqPwhCBfj0W5I42 25 | 1ZL4+8eniHfUs4GXzf5tb9YwVt3EltIF2JybaBvFsv2o356yJUQmqQ+jyYRoEpT5 26 | 2SwilFo/XCotCXxi5n8sm9V94a0oix4ehZrohTA/FZLsggwFCPmXfw== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /test/.ssh/id_rsa.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNr4q9zMKtylAZGr17fjtUfH2gS+6Gx4m3TJ1H5QwC97JCmtTgke/PBRSEacbXjsYlBjJ9DifNpIbrZrP9hOGhknPDyC3EaRUe/TCUCVGRiHFspurxZAiHvfENCQcvDaVcu9/tO3QyGjDSoYSaQ6NNvl8+yPZ6+mGtXeMnXlCWEvhy/fe3yNVp0isvSIinB2paI+pQqmytJ8omCGShdLqq4/Lvw/zbROe6gEb78+mvwqS+fqYDuPjGc5DXZATqM8rjOSKSPllzNILh9MbR3cHDBfhVi77jL9P8FfQv1U1SZBTbZj78xFcBRnGxrxWE0H7FcXldK5vJvafqWgxZZpgb test@localhost.local 2 | -------------------------------------------------------------------------------- /test/.ssh/test_id_rsa: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA4NhQ+WCdHPNry2bjVFBLIAMLDTiUwPRfd8jHsIANvZ1zgqcG 3 | xYgtV6ZNZicb1QR823K6wJupsw7mGB+h+YeUQFY53l0D7jgk05Xtl1MVKFmhU5OZ 4 | pF1ywn8fy8nuwF20ZI2JNKRgoY1DH+MA3SG7wuTulpIpjL0HT/75wmRSpQJFzku5 5 | 45Uc6PzQrFgWWv0nb/jydqLoQwVtuL90q7MyVJH75L0egND6HGrAa0CXkwSzr/ZG 6 | L7yd49NzWgYcgHX+q/Tj4lnk3jzFjFgWvoELwTKoC5neMeBK/QUrw6dxH4NLdSE2 7 | sp8owywFR3iOFC/Bw+WxA8+kjP2l2ts4VyTSfwIDAQABAoIBAFJk8sdv8CM70LSo 8 | 74VmJyGD+/jMUzaiVpm+qe6z/lUN7dZi/shELtl/x703d6uICXkhge4zHOzQ+OC+ 9 | Ns0KMfmhn3MtAtO5H0WqG3boq0guEEBgRl1FIVjE3RIA3c0AiaqPc0gnNIH/EioN 10 | NbPTOMsiuYvT5AX+/z8BYOUrfl2Y17z0LbULiXDAsN350W8K5BBuZYNcc5HefaW+ 11 | CHeKrcpW3t0Gmjmd+fMnv+iKG4d2Xrkeca2raG8d/IICe7EVE6GR4rWcZb8S1tUm 12 | BWqew7QuUDijHHV4Tb4UriZyLUI7ONPMbOmbsFc1/vcw9RgY2wuEvKbrYlP90DM0 13 | NS2H9oECgYEA9JdWD5PHj03vk9TWZUUskEl+j1sO1mBoxHKGz9naFIxV8CRTbTCc 14 | Fht0vf+qyXPwzJVR6R/3OST3FMem5gcXJl9HFomuBLwPFHhal9vnOhP5pnjSYbYU 15 | QxJjeFfaNTgFyxXCSnGfwgzbfjhYumBti7jINu9YGBul0GzD0SJ6M6UCgYEA61Uw 16 | 53Eh/jXOSU5wTTefm84a/BMzSt4n1mz7mt5D014Z1lO2XTp1fgBCucL42mJtCThZ 17 | NILs5ZJHLqV8D4zOKm9ptLTzN1WYDcYUv7A+P/42vfXVwiX1RT9e4mAHsbWZLwd6 18 | 4s8lq2oChN8zI5hSS3yJAjo+fD8y8xhtRcJBhFMCgYAdvrHGnzArq0yxa7bPBgSP 19 | X4C2qlo5k+vpyAvBBztQOGjTFXfX1YuF3LzrxkXcze7A0n/tm+eS2X361vTjEIWu 20 | MvQQN5okFUK4OJK72RBbrcY0ioj7PQtlxLy4C+cLhc6ejfzc1Mia7rlatjuEHunz 21 | jfs7Qwwxklst56xAqLK3yQKBgACFSrtoW6vlUJSG8Oaq1daRaSvfmwByZ2IpEZFx 22 | JnNERQhdXQztwS7LL1qb3NMW3qjjkAb2tzF21mN7CEA8joQ3hONadyNLNC/rnUYj 23 | TK/1jwdykMuCK/3AOySDE+FHxpP9Dz+LN8keTe0fVUyh3KTAHMl9eX/q3+D7z9oU 24 | qPJzAoGBAMUmW8WqjHughUfd/0GLlsXgVRqHfDVyFZkX31tSDoKY9ljHe2lZbDrz 25 | OEC36ln9qRiiHy+M7bBMWFTba2UXERE2wHa+6X6OHYVotmM31z6rTFa79w+zFje7 26 | y73kOsYH7rLaJWaBYobyndXUg71AUwcc6ZUlJQrPucz08haoAF1c 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /test/.ssh/test_id_rsa.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDg2FD5YJ0c82vLZuNUUEsgAwsNOJTA9F93yMewgA29nXOCpwbFiC1Xpk1mJxvVBHzbcrrAm6mzDuYYH6H5h5RAVjneXQPuOCTTle2XUxUoWaFTk5mkXXLCfx/Lye7AXbRkjYk0pGChjUMf4wDdIbvC5O6WkimMvQdP/vnCZFKlAkXOS7njlRzo/NCsWBZa/Sdv+PJ2ouhDBW24v3SrszJUkfvkvR6A0PocasBrQJeTBLOv9kYvvJ3j03NaBhyAdf6r9OPiWeTePMWMWBa+gQvBMqgLmd4x4Er9BSvDp3Efg0t1ITaynyjDLAVHeI4UL8HD5bEDz6SM/aXa2zhXJNJ/ test.key@localhost.local 2 | -------------------------------------------------------------------------------- /test/user.ldif: -------------------------------------------------------------------------------- 1 | dn: uuid=a820621a-5007-4a2a-9636-edde809106de, ou=users, o=smartdc 2 | changetype: add 3 | login: test 4 | uuid: a820621a-5007-4a2a-9636-edde809106de 5 | userpassword: verys3cret 6 | email: test@example.com 7 | cn: Test 8 | sn: User 9 | company: Testing Inc. 10 | address: liltingly, Inc. 11 | address: 6165 pyrophyllite Street 12 | city: benzoylation concoctive 13 | state: SP 14 | postalCode: 4967 15 | country: BAT 16 | phone: +1 891 657 5818 17 | objectclass: sdcPerson 18 | 19 | dn: fingerprint=66:ca:1c:09:75:99:35:69:be:91:08:25:03:c0:17:c0, uuid=a820621a-5007-4a2a-9636-edde809106de, ou=users, o=smartdc 20 | changetype: add 21 | name: id_rsa 22 | fingerprint: 66:ca:1c:09:75:99:35:69:be:91:08:25:03:c0:17:c0 23 | openssh: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNr4q9zMKtylAZGr17fjtUfH2gS+6Gx4m3TJ1H5QwC97JCmtTgke/PBRSEacbXjsYlBjJ9DifNpIbrZrP9hOGhknPDyC3EaRUe/TCUCVGRiHFspurxZAiHvfENCQcvDaVcu9/tO3QyGjDSoYSaQ6NNvl8+yPZ6+mGtXeMnXlCWEvhy/fe3yNVp0isvSIinB2paI+pQqmytJ8omCGShdLqq4/Lvw/zbROe6gEb78+mvwqS+fqYDuPjGc5DXZATqM8rjOSKSPllzNILh9MbR3cHDBfhVi77jL9P8FfQv1U1SZBTbZj78xFcBRnGxrxWE0H7FcXldK5vJvafqWgxZZpgb test@localhost.local 24 | objectclass: sdcKey 25 | -------------------------------------------------------------------------------- /tools/bashstyle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* 4 | * Copyright (c) 2012, Joyent, Inc. All rights reserved. 5 | * 6 | * bashstyle: check bash scripts for adherence to style guidelines, including: 7 | * 8 | * o no lines longer than 80 characters 9 | * o file does not end with a blank line 10 | * 11 | * Future enhancements could include: 12 | * o indents consistent with respect to tabs, spaces 13 | * o indents consistently sized (all are some multiple of the smallest 14 | * indent, which must be a tab or 4 or 8 spaces) 15 | */ 16 | 17 | var mod_assert = require('assert'); 18 | var mod_fs = require('fs'); 19 | 20 | var nerrors = 0; 21 | 22 | main(); 23 | process.exit(0); 24 | 25 | function main() 26 | { 27 | var files = process.argv.slice(2); 28 | 29 | if (files.length === 0) { 30 | console.error('usage: %s file1 [...]', 31 | process.argv.slice(0, 2).join(' ')); 32 | process.exit(2); 33 | } 34 | 35 | files.forEach(checkFile); 36 | 37 | if (nerrors != 0) 38 | process.exit(1); 39 | } 40 | 41 | function checkFile(filename) 42 | { 43 | var text = mod_fs.readFileSync(filename, 'utf-8'); 44 | var lines = text.split('\n'); 45 | var i; 46 | 47 | mod_assert.ok(lines.length > 0); 48 | 49 | /* 50 | * Expand tabs in each line and check for long lines. 51 | */ 52 | for (i = 1; i <= lines.length; i++) { 53 | var line = expandTabs(lines[i - 1]); 54 | 55 | if (line.length > 80) { 56 | nerrors++; 57 | console.log('%s: %d: line exceeds 80 columns', 58 | filename, i); 59 | } 60 | } 61 | 62 | /* 63 | * No sane editor lets you save a file without a newline at the very end. 64 | */ 65 | if (lines[lines.length - 1].length !== 0) { 66 | nerrors++; 67 | console.log('%s: %d: file does not end with newline', 68 | filename, lines.length); 69 | } 70 | 71 | /* 72 | * Since the file will always end with a newline, the last entry of 73 | * "lines" will actually be blank. 74 | */ 75 | if (lines.length > 1 && lines[lines.length - 2].length === 0) { 76 | nerrors++; 77 | console.log('%s: %d: file ends with a blank line', 78 | filename, lines.length - 1); 79 | } 80 | } 81 | 82 | function expandTabs(text) 83 | { 84 | var out = ''; 85 | var col = 0; 86 | var j, k; 87 | 88 | for (j = 0; j < text.length; j++) { 89 | if (text[j] != '\t') { 90 | out += text[j]; 91 | col++; 92 | continue; 93 | } 94 | 95 | k = 8 - (col % 8); 96 | col += k; 97 | 98 | do { 99 | out += ' '; 100 | } while (--k > 0); 101 | 102 | col += k; 103 | } 104 | 105 | return (out); 106 | } 107 | -------------------------------------------------------------------------------- /tools/jsl.node.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Configuration File for JavaScript Lint 3 | # 4 | # This configuration file can be used to lint a collection of scripts, or to enable 5 | # or disable warnings for scripts that are linted via the command line. 6 | # 7 | 8 | ### Warnings 9 | # Enable or disable warnings based on requirements. 10 | # Use "+WarningName" to display or "-WarningName" to suppress. 11 | # 12 | +ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent 13 | +ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity 14 | +ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement 15 | +anon_no_return_value # anonymous function does not always return value 16 | +assign_to_function_call # assignment to a function call 17 | -block_without_braces # block statement without curly braces 18 | +comma_separated_stmts # multiple statements separated by commas (use semicolons?) 19 | +comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==) 20 | +default_not_at_end # the default case is not at the end of the switch statement 21 | +dup_option_explicit # duplicate "option explicit" control comment 22 | +duplicate_case_in_switch # duplicate case in switch statement 23 | +duplicate_formal # duplicate formal argument {name} 24 | +empty_statement # empty statement or extra semicolon 25 | +identifier_hides_another # identifer {name} hides an identifier in a parent scope 26 | -inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement 27 | +incorrect_version # Expected /*jsl:content-type*/ control comment. The script was parsed with the wrong version. 28 | +invalid_fallthru # unexpected "fallthru" control comment 29 | +invalid_pass # unexpected "pass" control comment 30 | +jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax 31 | +leading_decimal_point # leading decimal point may indicate a number or an object member 32 | +legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax 33 | +meaningless_block # meaningless block; curly braces have no impact 34 | +mismatch_ctrl_comments # mismatched control comment; "ignore" and "end" control comments must have a one-to-one correspondence 35 | +misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma 36 | +missing_break # missing break statement 37 | +missing_break_for_last_case # missing break statement for last case in switch 38 | +missing_default_case # missing default case in switch statement 39 | +missing_option_explicit # the "option explicit" control comment is missing 40 | +missing_semicolon # missing semicolon 41 | +missing_semicolon_for_lambda # missing semicolon for lambda assignment 42 | +multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs 43 | +nested_comment # nested comment 44 | +no_return_value # function {name} does not always return a value 45 | +octal_number # leading zeros make an octal number 46 | +parseint_missing_radix # parseInt missing radix parameter 47 | +partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag 48 | +redeclared_var # redeclaration of {name} 49 | +trailing_comma_in_array # extra comma is not recommended in array initializers 50 | +trailing_decimal_point # trailing decimal point may indicate a number or an object member 51 | +undeclared_identifier # undeclared identifier: {name} 52 | +unreachable_code # unreachable code 53 | -unreferenced_argument # argument declared but never referenced: {name} 54 | -unreferenced_function # function is declared but never referenced: {name} 55 | +unreferenced_variable # variable is declared but never referenced: {name} 56 | +unsupported_version # JavaScript {version} is not supported 57 | +use_of_label # use of label 58 | +useless_assign # useless assignment 59 | +useless_comparison # useless comparison; comparing identical expressions 60 | -useless_quotes # the quotation marks are unnecessary 61 | +useless_void # use of the void type may be unnecessary (void is always undefined) 62 | +var_hides_arg # variable {name} hides argument 63 | +want_assign_or_call # expected an assignment or function call 64 | +with_statement # with statement hides undeclared variables; use temporary variable instead 65 | 66 | 67 | ### Output format 68 | # Customize the format of the error message. 69 | # __FILE__ indicates current file path 70 | # __FILENAME__ indicates current file name 71 | # __LINE__ indicates current line 72 | # __COL__ indicates current column 73 | # __ERROR__ indicates error message (__ERROR_PREFIX__: __ERROR_MSG__) 74 | # __ERROR_NAME__ indicates error name (used in configuration file) 75 | # __ERROR_PREFIX__ indicates error prefix 76 | # __ERROR_MSG__ indicates error message 77 | # 78 | # For machine-friendly output, the output format can be prefixed with 79 | # "encode:". If specified, all items will be encoded with C-slashes. 80 | # 81 | # Visual Studio syntax (default): 82 | +output-format __FILE__(__LINE__): __ERROR__ 83 | # Alternative syntax: 84 | #+output-format __FILE__:__LINE__: __ERROR__ 85 | 86 | 87 | ### Context 88 | # Show the in-line position of the error. 89 | # Use "+context" to display or "-context" to suppress. 90 | # 91 | +context 92 | 93 | 94 | ### Control Comments 95 | # Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for 96 | # the /*@keyword@*/ control comments and JScript conditional comments. (The latter is 97 | # enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason, 98 | # although legacy control comments are enabled by default for backward compatibility. 99 | # 100 | -legacy_control_comments 101 | 102 | 103 | ### Defining identifiers 104 | # By default, "option explicit" is enabled on a per-file basis. 105 | # To enable this for all files, use "+always_use_option_explicit" 106 | -always_use_option_explicit 107 | 108 | # Define certain identifiers of which the lint is not aware. 109 | # (Use this in conjunction with the "undeclared identifier" warning.) 110 | # 111 | # Common uses for webpages might be: 112 | +define __dirname 113 | +define clearInterval 114 | +define clearTimeout 115 | +define console 116 | +define exports 117 | +define global 118 | +define module 119 | +define process 120 | +define require 121 | +define setInterval 122 | +define setTimeout 123 | +define Buffer 124 | +define JSON 125 | +define Math 126 | 127 | ### JavaScript Version 128 | # To change the default JavaScript version: 129 | #+default-type text/javascript;version=1.5 130 | #+default-type text/javascript;e4x=1 131 | 132 | ### Files 133 | # Specify which files to lint 134 | # Use "+recurse" to enable recursion (disabled by default). 135 | # To add a set of files, use "+process FileName", "+process Folder\Path\*.js", 136 | # or "+process Folder\Path\*.htm". 137 | # 138 | 139 | -------------------------------------------------------------------------------- /tools/jsl.web.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Configuration File for JavaScript Lint 3 | # Developed by Matthias Miller (http://www.JavaScriptLint.com) 4 | # 5 | # This configuration file can be used to lint a collection of scripts, or to enable 6 | # or disable warnings for scripts that are linted via the command line. 7 | # 8 | 9 | ### Warnings 10 | # Enable or disable warnings based on requirements. 11 | # Use "+WarningName" to display or "-WarningName" to suppress. 12 | # 13 | +ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent 14 | +ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity 15 | +ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement 16 | +anon_no_return_value # anonymous function does not always return value 17 | +assign_to_function_call # assignment to a function call 18 | -block_without_braces # block statement without curly braces 19 | +comma_separated_stmts # multiple statements separated by commas (use semicolons?) 20 | +comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==) 21 | +default_not_at_end # the default case is not at the end of the switch statement 22 | +dup_option_explicit # duplicate "option explicit" control comment 23 | +duplicate_case_in_switch # duplicate case in switch statement 24 | +duplicate_formal # duplicate formal argument {name} 25 | +empty_statement # empty statement or extra semicolon 26 | +identifier_hides_another # identifer {name} hides an identifier in a parent scope 27 | +inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement 28 | +incorrect_version # Expected /*jsl:content-type*/ control comment. The script was parsed with the wrong version. 29 | +invalid_fallthru # unexpected "fallthru" control comment 30 | +invalid_pass # unexpected "pass" control comment 31 | +jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax 32 | +leading_decimal_point # leading decimal point may indicate a number or an object member 33 | +legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax 34 | +meaningless_block # meaningless block; curly braces have no impact 35 | +mismatch_ctrl_comments # mismatched control comment; "ignore" and "end" control comments must have a one-to-one correspondence 36 | +misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma 37 | +missing_break # missing break statement 38 | +missing_break_for_last_case # missing break statement for last case in switch 39 | +missing_default_case # missing default case in switch statement 40 | +missing_option_explicit # the "option explicit" control comment is missing 41 | +missing_semicolon # missing semicolon 42 | +missing_semicolon_for_lambda # missing semicolon for lambda assignment 43 | +multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs 44 | +nested_comment # nested comment 45 | +no_return_value # function {name} does not always return a value 46 | +octal_number # leading zeros make an octal number 47 | +parseint_missing_radix # parseInt missing radix parameter 48 | +partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag 49 | +redeclared_var # redeclaration of {name} 50 | +trailing_comma_in_array # extra comma is not recommended in array initializers 51 | +trailing_decimal_point # trailing decimal point may indicate a number or an object member 52 | +undeclared_identifier # undeclared identifier: {name} 53 | +unreachable_code # unreachable code 54 | +unreferenced_argument # argument declared but never referenced: {name} 55 | +unreferenced_function # function is declared but never referenced: {name} 56 | +unreferenced_variable # variable is declared but never referenced: {name} 57 | +unsupported_version # JavaScript {version} is not supported 58 | +use_of_label # use of label 59 | +useless_assign # useless assignment 60 | +useless_comparison # useless comparison; comparing identical expressions 61 | +useless_quotes # the quotation marks are unnecessary 62 | +useless_void # use of the void type may be unnecessary (void is always undefined) 63 | +var_hides_arg # variable {name} hides argument 64 | +want_assign_or_call # expected an assignment or function call 65 | +with_statement # with statement hides undeclared variables; use temporary variable instead 66 | 67 | 68 | ### Output format 69 | # Customize the format of the error message. 70 | # __FILE__ indicates current file path 71 | # __FILENAME__ indicates current file name 72 | # __LINE__ indicates current line 73 | # __COL__ indicates current column 74 | # __ERROR__ indicates error message (__ERROR_PREFIX__: __ERROR_MSG__) 75 | # __ERROR_NAME__ indicates error name (used in configuration file) 76 | # __ERROR_PREFIX__ indicates error prefix 77 | # __ERROR_MSG__ indicates error message 78 | # 79 | # For machine-friendly output, the output format can be prefixed with 80 | # "encode:". If specified, all items will be encoded with C-slashes. 81 | # 82 | # Visual Studio syntax (default): 83 | +output-format __FILE__(__LINE__): __ERROR__ 84 | # Alternative syntax: 85 | #+output-format __FILE__:__LINE__: __ERROR__ 86 | 87 | 88 | ### Context 89 | # Show the in-line position of the error. 90 | # Use "+context" to display or "-context" to suppress. 91 | # 92 | +context 93 | 94 | 95 | ### Control Comments 96 | # Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for 97 | # the /*@keyword@*/ control comments and JScript conditional comments. (The latter is 98 | # enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason, 99 | # although legacy control comments are enabled by default for backward compatibility. 100 | # 101 | -legacy_control_comments 102 | 103 | 104 | ### Defining identifiers 105 | # By default, "option explicit" is enabled on a per-file basis. 106 | # To enable this for all files, use "+always_use_option_explicit" 107 | +always_use_option_explicit 108 | 109 | # Define certain identifiers of which the lint is not aware. 110 | # (Use this in conjunction with the "undeclared identifier" warning.) 111 | # 112 | # Common uses for webpages might be: 113 | +define JSON 114 | +define Math 115 | +define $ 116 | +define XMLHttpRequest 117 | +define alert 118 | +define clearInterval 119 | +define clearTimeout 120 | +define confirm 121 | +define document 122 | +define setInterval 123 | +define setTimeout 124 | +define window 125 | 126 | ### JavaScript Version 127 | # To change the default JavaScript version: 128 | #+default-type text/javascript;version=1.5 129 | #+default-type text/javascript;e4x=1 130 | 131 | ### Files 132 | # Specify which files to lint 133 | # Use "+recurse" to enable recursion (disabled by default). 134 | # To add a set of files, use "+process FileName", "+process Folder\Path\*.js", 135 | # or "+process Folder\Path\*.htm". 136 | # 137 | 138 | -------------------------------------------------------------------------------- /tools/mk/Makefile.defs: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | 8 | # 9 | # Copyright (c) 2014, Joyent, Inc. 10 | # 11 | 12 | # 13 | # Makefile.defs: common defines. 14 | # 15 | # NOTE: This makefile comes from the "eng" repo. It's designed to be dropped 16 | # into other repos as-is without requiring any modifications. If you find 17 | # yourself changing this file, you should instead update the original copy in 18 | # eng.git and then update your repo to use the new version. 19 | # 20 | # This makefile defines some useful defines. Include it at the top of 21 | # your Makefile. 22 | # 23 | # Definitions in this Makefile: 24 | # 25 | # TOP The absolute path to the project directory. The top dir. 26 | # BRANCH The current git branch. 27 | # TIMESTAMP The timestamp for the build. This can be set via 28 | # the TIMESTAMP envvar (used by MG-based builds). 29 | # STAMP A build stamp to use in built package names. 30 | # 31 | 32 | TOP := $(shell pwd) 33 | 34 | # 35 | # Mountain Gorilla-spec'd versioning. 36 | # See "Package Versioning" in MG's README.md: 37 | # 38 | # 39 | # Need GNU awk for multi-char arg to "-F". 40 | _AWK := $(shell (which gawk >/dev/null && echo gawk) \ 41 | || (which nawk >/dev/null && echo nawk) \ 42 | || echo awk) 43 | BRANCH := $(shell git symbolic-ref HEAD | $(_AWK) -F/ '{print $$3}') 44 | ifeq ($(TIMESTAMP),) 45 | TIMESTAMP := $(shell date -u "+%Y%m%dT%H%M%SZ") 46 | endif 47 | _GITDESCRIBE := g$(shell git describe --all --long --dirty | $(_AWK) -F'-g' '{print $$NF}') 48 | STAMP := $(BRANCH)-$(TIMESTAMP)-$(_GITDESCRIBE) 49 | 50 | # node-gyp will print build info useful for debugging with V=1 51 | export V=1 52 | -------------------------------------------------------------------------------- /tools/mk/Makefile.deps: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | 8 | # 9 | # Copyright (c) 2014, Joyent, Inc. 10 | # 11 | 12 | # 13 | # Makefile.deps: Makefile for including common tools as dependencies 14 | # 15 | # NOTE: This makefile comes from the "eng" repo. It's designed to be dropped 16 | # into other repos as-is without requiring any modifications. If you find 17 | # yourself changing this file, you should instead update the original copy in 18 | # eng.git and then update your repo to use the new version. 19 | # 20 | # This file is separate from Makefile.targ so that teams can choose 21 | # independently whether to use the common targets in Makefile.targ and the 22 | # common tools here. 23 | # 24 | 25 | # 26 | # javascriptlint 27 | # 28 | JSL_EXEC ?= deps/javascriptlint/build/install/jsl 29 | JSL ?= $(JSL_EXEC) 30 | 31 | $(JSL_EXEC): | deps/javascriptlint/.git 32 | cd deps/javascriptlint && make install 33 | 34 | distclean:: 35 | if [[ -f deps/javascriptlint/Makefile ]]; then \ 36 | cd deps/javascriptlint && make clean; \ 37 | fi 38 | 39 | # 40 | # jsstyle 41 | # 42 | JSSTYLE_EXEC ?= deps/jsstyle/jsstyle 43 | JSSTYLE ?= $(JSSTYLE_EXEC) 44 | 45 | $(JSSTYLE_EXEC): | deps/jsstyle/.git 46 | 47 | # 48 | # restdown 49 | # 50 | RESTDOWN_EXEC ?= deps/restdown/bin/restdown 51 | RESTDOWN ?= python $(RESTDOWN_EXEC) 52 | $(RESTDOWN_EXEC): | deps/restdown/.git 53 | 54 | EXTRA_DOC_DEPS ?= 55 | -------------------------------------------------------------------------------- /tools/mk/Makefile.node.defs: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | 8 | # 9 | # Copyright (c) 2014, Joyent, Inc. 10 | # 11 | 12 | # 13 | # Makefile.node.defs: Makefile for building and bundling your own Node.js. 14 | # 15 | # NOTE: This makefile comes from the "eng" repo. It's designed to be dropped 16 | # into other repos as-is without requiring any modifications. If you find 17 | # yourself changing this file, you should instead update the original copy in 18 | # eng.git and then update your repo to use the new version. 19 | # 20 | 21 | # 22 | # This Makefile facilitates building and bundling your own copy of Node.js in 23 | # your repo. All it does is define variables for node, node-waf, and npm for 24 | # you to use elsewhere in your Makefile and rules to build these tools when 25 | # needed. 26 | # 27 | # To use this facility, include "Makefile.node.defs", use the variables as 28 | # described below to define targets, and then include "Makefile.node.targ". 29 | # 30 | # There are two use cases addressed here: 31 | # 32 | # (1) Invoking node, node-waf, or npm as part of the build process, as in "npm 33 | # install" and "node-waf configure build". To facilitate this, this 34 | # Makefile defines Make variables NODE, NODE_WAF, and NPM that you can use 35 | # to invoke these commands during the build process. You MUST NOT assume 36 | # that these variables just evaluate to the filenames themselves, as they 37 | # may have environment variable definitions and other things that prevent 38 | # you from using them directly as a filename. If you want that, see (2). 39 | # 40 | # Wherever you use one of these variables, you MUST include a dependency on 41 | # the corresponding *_EXEC variable as well, like so: 42 | # 43 | # node_modules/restify: deps/restify $(NPM_EXEC) 44 | # $(NPM) install deps/restify 45 | # 46 | # or better, use an order-only dependency to avoid spurious rebuilds: 47 | # 48 | # node_modules/restify: deps/restify | $(NPM_EXEC) 49 | # $(NPM) install deps/restify 50 | # 51 | # Otherwise, the underlying file will not get built. We don't 52 | # automatically build them as part of "all" because that approach is 53 | # brittle. 54 | # 55 | # (2) Specifying paths for invoking node, node-waf, or npm at RUNTIME, as in 56 | # specifying the path to node used for the start method of your service's 57 | # SMF manifest. For this, this Makefile defines variables NODE_EXEC, 58 | # NODE_WAF_EXEC, and NPM_EXEC, which represent the relative paths of these 59 | # files from the root of the workspace. You MUST NOT use these variables 60 | # to invoke these commands during the build process. See (1) instead. 61 | # 62 | # However, in order to work at runtime, you must build the tool as well. 63 | # That is, if you use NODE_EXEC to specify the path to node, you must 64 | # depend on NODE_EXEC somewhere. This usually happens anyway because you 65 | # usually need them during the build process too, but if you don't then 66 | # you need to explicitly add NODE_EXEC (or whichever) to your "all" 67 | # target. 68 | # 69 | # When including this Makefile, you MAY also specify: 70 | # 71 | # BUILD top-level directory for built binaries 72 | # (default: "build") 73 | # 74 | # NODE_INSTALL where node should install its built items 75 | # (default: "$BUILD/node") 76 | # 77 | # NODE_CONFIG_FLAGS extra flags to pass to Node's "configure" 78 | # (default: "--with-dtrace" on SmartOS; empty 79 | # otherwise.) 80 | # 81 | 82 | TOP ?= $(error You must include Makefile.defs before this makefile) 83 | 84 | BUILD ?= build 85 | NODE_INSTALL ?= $(BUILD)/node 86 | DISTCLEAN_FILES += $(NODE_INSTALL) 87 | 88 | NODE_CONFIG_FLAGS += --prefix=$(TOP)/$(NODE_INSTALL) 89 | 90 | ifeq ($(shell uname -s),SunOS) 91 | NODE_CONFIG_FLAGS += --with-dtrace \ 92 | --openssl-libpath=/opt/local/lib \ 93 | --openssl-includes=/opt/local/include 94 | endif 95 | 96 | NODE_EXEC = $(NODE_INSTALL)/bin/node 97 | NODE_WAF_EXEC = $(NODE_INSTALL)/bin/node-waf 98 | NPM_EXEC = $(NODE_INSTALL)/bin/npm 99 | 100 | # Ensure these use absolute paths to the executables to allow running 101 | # from a dir other than the project top. 102 | NODE := $(TOP)/$(NODE_EXEC) 103 | NODE_WAF := $(TOP)/$(NODE_WAF_EXEC) 104 | NPM := PATH=$(TOP)/$(NODE_INSTALL)/bin:$(PATH) node $(TOP)/$(NPM_EXEC) 105 | -------------------------------------------------------------------------------- /tools/mk/Makefile.node.targ: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | 8 | # 9 | # Copyright (c) 2014, Joyent, Inc. 10 | # 11 | 12 | # 13 | # Makefile.node.targ: See Makefile.node.defs. 14 | # 15 | # NOTE: This makefile comes from the "eng" repo. It's designed to be dropped 16 | # into other repos as-is without requiring any modifications. If you find 17 | # yourself changing this file, you should instead update the original copy in 18 | # eng.git and then update your repo to use the new version. 19 | # 20 | 21 | ifneq ($(shell uname -s),SunOS) 22 | NODE_PREBUILT_VERSION ?= $(error You must define NODE_PREBUILT_VERSION to use Makefile.node.targ on non-SunOS) 23 | endif 24 | 25 | ifeq ($(shell uname -s),SunOS) 26 | $(NODE_EXEC) $(NPM_EXEC) $(NODE_WAF_EXEC): | deps/node/.git 27 | (cd deps/node; ./configure $(NODE_CONFIG_FLAGS) && $(MAKE) && $(MAKE) install) 28 | else 29 | $(NODE_EXEC) $(NPM_EXEC) $(NODE_WAF_EXEC): 30 | (mkdir -p $(BUILD) \ 31 | && cd $(BUILD) \ 32 | && [[ -d src-node ]] && (cd src-node && git checkout master && git pull) || git clone https://github.com/joyent/node.git src-node \ 33 | && cd src-node \ 34 | && git checkout $(NODE_PREBUILT_VERSION) \ 35 | && ./configure $(NODE_CONFIG_FLAGS) \ 36 | && $(MAKE) && $(MAKE) install) 37 | endif 38 | 39 | DISTCLEAN_FILES += $(NODE_INSTALL) $(BUILD)/src-node 40 | 41 | distclean:: 42 | -([[ ! -d deps/node ]] || (cd deps/node && $(MAKE) distclean)) 43 | -------------------------------------------------------------------------------- /tools/mk/Makefile.node_deps.defs: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | 8 | # 9 | # Copyright (c) 2014, Joyent, Inc. 10 | # 11 | 12 | # 13 | # Makefile.node_deps.defs: Makefile for including npm modules whose sources 14 | # reside inside the repo. This should NOT be used for modules in the npm 15 | # public repo or modules that could be specified with git SHAs. 16 | # 17 | # NOTE: This makefile comes from the "eng" repo. It's designed to be dropped 18 | # into other repos as-is without requiring any modifications. If you find 19 | # yourself changing this file, you should instead update the original copy in 20 | # eng.git and then update your repo to use the new version. 21 | # 22 | 23 | # 24 | # This Makefile takes as input the following make variable: 25 | # 26 | # REPO_MODULES List of relative paths to node modules (i.e., npm 27 | # packages) inside this repo. For example: 28 | # src/node-canative, where there's a binary npm package 29 | # in src/node-canative. 30 | # 31 | # Based on the above, this Makefile defines the following new variables: 32 | # 33 | # REPO_DEPS List of relative paths to the installed modules. For 34 | # example: "node_modules/canative". 35 | # 36 | # The accompanying Makefile.node_deps.targ defines a target that will install 37 | # each of REPO_MODULES into REPO_DEPS and remove REPO_DEPS with "make clean". 38 | # The top-level Makefile is responsible for depending on REPO_DEPS where 39 | # appropriate (usually the "deps" or "all" target). 40 | # 41 | 42 | REPO_DEPS = $(REPO_MODULES:src/node-%=node_modules/%) 43 | CLEAN_FILES += $(REPO_DEPS) 44 | -------------------------------------------------------------------------------- /tools/mk/Makefile.node_deps.targ: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | 8 | # 9 | # Copyright (c) 2014, Joyent, Inc. 10 | # 11 | 12 | # 13 | # Makefile.node_deps.targ: targets for Makefile.node_deps.defs. 14 | # 15 | # NOTE: This makefile comes from the "eng" repo. It's designed to be dropped 16 | # into other repos as-is without requiring any modifications. If you find 17 | # yourself changing this file, you should instead update the original copy in 18 | # eng.git and then update your repo to use the new version. 19 | # 20 | 21 | NPM_EXEC ?= $(error NPM_EXEC must be defined for Makefile.node_deps.targ) 22 | 23 | node_modules/%: src/node-% | $(NPM_EXEC) 24 | $(NPM) install $< 25 | -------------------------------------------------------------------------------- /tools/mk/Makefile.node_prebuilt.defs: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | 8 | # 9 | # Copyright (c) 2014, Joyent, Inc. 10 | # 11 | 12 | # 13 | # Makefile.node_prebuilt.defs: Makefile for including a prebuilt Node.js build. 14 | # 15 | # NOTE: This makefile comes from the "eng" repo. It's designed to be dropped 16 | # into other repos as-is without requiring any modifications. If you find 17 | # yourself changing this file, you should instead update the original copy in 18 | # eng.git and then update your repo to use the new version. 19 | # 20 | 21 | # 22 | # This Makefile facilitates downloading and bundling a prebuilt node.js 23 | # build (using the 'sdcnode' distro builds). This is an alternative to 24 | # the "Makefile.node.*" makefiles for *building* a node from source. 25 | # 26 | # Usage: 27 | # 28 | # - Define `NODE_PREBUILT_VERSION` in your Makefile to choose a node version. 29 | # E.g.: `NODE_PREBUILT_VERSION=v0.6.19`. See other optional variables 30 | # below. 31 | # - `include tools/mk/Makefile.node_prebuilt.defs` after this in your Makefile. 32 | # - `include tools/mk/Makefile.node_prebuilt.targ` near the end of your 33 | # Makefile. 34 | # - Have at least one of your Makefile targets depend on either `$(NODE_EXEC)` 35 | # or `$(NPM_EXEC)`. E.g.: 36 | # 37 | # node_modules/restify: deps/restify $(NPM_EXEC) 38 | # $(NPM) install deps/restify 39 | # 40 | # or better, use an order-only dependency to avoid spurious rebuilds: 41 | # 42 | # node_modules/restify: deps/restify | $(NPM_EXEC) 43 | # $(NPM) install deps/restify 44 | # 45 | # - Use `$(NPM)` or `$(NODE)` to use your node build. 46 | # - Include the "$(NODE_INSTALL)" tree in your release package. 47 | # 48 | # 49 | # When including this Makefile, you MUST also specify: 50 | # 51 | # NODE_PREBUILT_VERSION The node version in the prebuilt 'sdcnode' 52 | # package to use. Typically this is one of the 53 | # node version tags, e.g. "v0.6.18" but it 54 | # can be any commitish. 55 | # 56 | # When including this Makefile, you MAY also specify: 57 | # 58 | # NODE_PREBUILT_DIR The dir in which to find sdcnode builds. This 59 | # can either be a *local directory* or *a 60 | # URL* dir (with trailing '/') which serves 61 | # Apache/Nginx dir listing HTML. 62 | # (default: sdcnode master build dir on stuff) 63 | # 64 | # NODE_PREBUILT_TAG The 'sdcnode' project supports special 65 | # configuration builds of node, e.g. say a 66 | # build configured `--without-ssl`. These 67 | # special configurations are given a tag, e.g. 68 | # 'gz', that is used in the filename. Optionally 69 | # specify a tag name here. 70 | # (default: empty) 71 | # 72 | # NODE_PREBUILT_BRANCH Specify a particular branch of 'sdcnode' builds 73 | # from which to pull. Generally one should stick 74 | # with the default. 75 | # (default: master) 76 | # 77 | # NODE_PREBUILT_IMAGE If you have a zone image that differs from that 78 | # for an sdcnode build that you want to use (potential compat 79 | # issues be damned), then set this to the UUID of the sdcnode 80 | # build you want. See here for available build image uuids: 81 | # 82 | # 83 | # BUILD top-level directory for built binaries 84 | # (default: "build") 85 | # 86 | # NODE_INSTALL where node should install its built items 87 | # (default: "$BUILD/node") 88 | # 89 | # 90 | # Dev Notes: 91 | # 92 | # This works by getting "NODE_PREBUILT_NAME" from the provided "NODE_PREBUILT_*" 93 | # vars and the image version (via 'mdata-get sdc:image_uuid'). The image uuid is 94 | # included to ensure an exact match with the build machine. This name (e.g. 95 | # "v0.6.18-zone-$uuid") is used to find a matching "sdcnode-$name-*.tgz" build 96 | # in "NODE_PREBUILT_DIR" (either a local directory or a URL). That tarball is 97 | # downloaded and extracted into "NODE_INSTALL". 98 | # 99 | # The "*_EXEC" vars are set to named symlinks, e.g. 100 | # "build/prebuilt-node-v0.6.18-$uuid", so that a change of selected node 101 | # build (say the developer changes NODE_PREBUILT_VERSION) will recreate the 102 | # node install. 103 | # 104 | # See for details on 'sdcnode-*' 105 | # package naming. 106 | # 107 | 108 | TOP ?= $(error You must include Makefile.defs before this makefile) 109 | NODE_PREBUILT_VERSION ?= $(error NODE_PREBUILT_VERSION is not set.) 110 | 111 | 112 | BUILD ?= build 113 | NODE_INSTALL ?= $(BUILD)/node 114 | DISTCLEAN_FILES += $(NODE_INSTALL) \ 115 | $(BUILD)/prebuilt-node-* $(BUILD)/prebuilt-npm-* 116 | 117 | NODE_PREBUILT_BRANCH ?= master 118 | NODE_PREBUILT_IMAGE ?= $(shell pfexec mdata-get sdc:image_uuid) 119 | ifeq ($(NODE_PREBUILT_TAG),) 120 | NODE_PREBUILT_NAME := $(NODE_PREBUILT_VERSION)-$(NODE_PREBUILT_IMAGE) 121 | else 122 | NODE_PREBUILT_NAME := $(NODE_PREBUILT_VERSION)-$(NODE_PREBUILT_TAG)-$(NODE_PREBUILT_IMAGE) 123 | endif 124 | NODE_PREBUILT_PATTERN := sdcnode-$(NODE_PREBUILT_NAME)-$(NODE_PREBUILT_BRANCH)-.*\.tgz 125 | NODE_PREBUILT_DIR ?= https://download.joyent.com/pub/build/sdcnode/$(NODE_PREBUILT_IMAGE)/$(NODE_PREBUILT_BRANCH)-latest/sdcnode/ 126 | ifeq ($(shell echo $(NODE_PREBUILT_DIR) | cut -c 1-4),http) 127 | NODE_PREBUILT_BASE := $(shell curl -ksS --fail --connect-timeout 30 $(NODE_PREBUILT_DIR) | grep 'href=' | cut -d'"' -f2 | grep "^$(NODE_PREBUILT_PATTERN)$$" | sort | tail -1) 128 | ifneq ($(NODE_PREBUILT_BASE),) 129 | NODE_PREBUILT_TARBALL := $(NODE_PREBUILT_DIR)$(NODE_PREBUILT_BASE) 130 | endif 131 | else 132 | NODE_PREBUILT_BASE := $(shell ls -1 $(NODE_PREBUILT_DIR)/ | grep "^$(NODE_PREBUILT_PATTERN)$$" 2>/dev/null | sort | tail -1) 133 | ifneq ($(NODE_PREBUILT_BASE),) 134 | NODE_PREBUILT_TARBALL := $(NODE_PREBUILT_DIR)/$(NODE_PREBUILT_BASE) 135 | endif 136 | endif 137 | ifeq ($(NODE_PREBUILT_TARBALL),) 138 | NODE_PREBUILT_TARBALL = $(error NODE_PREBUILT_TARBALL is empty: no '$(NODE_PREBUILT_DIR)/$(NODE_PREBUILT_PATTERN)' found) 139 | endif 140 | 141 | 142 | # Prebuild-specific paths for the "*_EXEC" vars to ensure that 143 | # a prebuild change (e.g. if master Makefile's NODE_PREBUILT_VERSION 144 | # choice changes) causes a install of the new node. 145 | NODE_EXEC := $(BUILD)/prebuilt-node-$(NODE_PREBUILT_NAME) 146 | NODE_WAF_EXEC := $(BUILD)/prebuilt-node-waf-$(NODE_PREBUILT_NAME) 147 | NPM_EXEC := $(BUILD)/prebuilt-npm-$(NODE_PREBUILT_NAME) 148 | 149 | # Ensure these use absolute paths to the executables to allow running 150 | # from a dir other than the project top. 151 | NODE := $(TOP)/$(NODE_INSTALL)/bin/node 152 | NODE_WAF := $(TOP)/$(NODE_INSTALL)/bin/node-waf 153 | NPM := PATH=$(TOP)/$(NODE_INSTALL)/bin:$(PATH) node $(TOP)/$(NODE_INSTALL)/bin/npm 154 | -------------------------------------------------------------------------------- /tools/mk/Makefile.node_prebuilt.targ: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | 8 | # 9 | # Copyright (c) 2014, Joyent, Inc. 10 | # 11 | 12 | # 13 | # Makefile.node_prebuilt.targ: Makefile for including a prebuilt Node.js 14 | # build. 15 | # 16 | # NOTE: This makefile comes from the "eng" repo. It's designed to be dropped 17 | # into other repos as-is without requiring any modifications. If you find 18 | # yourself changing this file, you should instead update the original copy in 19 | # eng.git and then update your repo to use the new version. 20 | 21 | 22 | NODE_PREBUILT_TARBALL ?= $(error NODE_PREBUILT_TARBALL is not set: was Makefile.node_prebuilt.defs included?) 23 | 24 | 25 | # TODO: remove this limitation 26 | # Limitation: currently presuming that the NODE_INSTALL basename is 27 | # 'node' and that sdcnode tarballs have a 'node' top-level dir. 28 | $(NODE_EXEC) $(NPM_EXEC) $(NODE_WAF_EXEC): 29 | [[ $(shell basename $(NODE_INSTALL)) == "node" ]] \ 30 | || (echo "Limitation: 'basename NODE_INSTALL' is not 'node'" && exit 1) 31 | rm -rf $(NODE_INSTALL) \ 32 | $(BUILD)/prebuilt-node-* $(BUILD)/prebuilt-npm-* 33 | mkdir -p $(shell dirname $(NODE_INSTALL)) 34 | if [[ $(shell echo $(NODE_PREBUILT_TARBALL) | cut -c 1-4) == "http" ]]; then \ 35 | echo "Downloading '$(NODE_PREBUILT_BASE)'."; \ 36 | curl -ksS --fail --connect-timeout 30 -o $(shell dirname $(NODE_INSTALL))/$(NODE_PREBUILT_BASE) $(NODE_PREBUILT_TARBALL); \ 37 | (cd $(shell dirname $(NODE_INSTALL)) && $(TAR) xf $(NODE_PREBUILT_BASE)); \ 38 | else \ 39 | (cd $(shell dirname $(NODE_INSTALL)) && $(TAR) xf $(NODE_PREBUILT_TARBALL)); \ 40 | fi 41 | ln -s $(TOP)/$(NODE_INSTALL)/bin/node $(NODE_EXEC) 42 | ln -s $(TOP)/$(NODE_INSTALL)/bin/npm $(NPM_EXEC) 43 | -------------------------------------------------------------------------------- /tools/mk/Makefile.smf.defs: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | 8 | # 9 | # Copyright (c) 2014, Joyent, Inc. 10 | # 11 | 12 | # 13 | # Makefile.smf.defs: common targets for SMF manifests 14 | # 15 | # NOTE: This makefile comes from the "eng" repo. It's designed to be dropped 16 | # into other repos as-is without requiring any modifications. If you find 17 | # yourself changing this file, you should instead update the original copy in 18 | # eng.git and then update your repo to use the new version. 19 | # 20 | # This Makefile uses the following definitions: 21 | # 22 | # SMF_MANIFESTS_IN Source files for SMF manifests. The following 23 | # substitutions will be made on these files: 24 | # 25 | # @@NODE@@ path to installed node 26 | # 27 | # It updates SMF_MANIFESTS with the set of files generated by SMF_MANIFESTS_IN. 28 | # It also updates the "check" target to check the XML syntax of all manifests, 29 | # generated or otherwise. 30 | # 31 | # To use this file, be sure to also include Makefile.smf.targ after defining 32 | # targets. 33 | # 34 | 35 | SED ?= sed 36 | SMF_DTD ?= tools/service_bundle.dtd.1 37 | XMLLINT ?= xmllint --noout 38 | 39 | SMF_MANIFESTS += $(SMF_MANIFESTS_IN:%.in=%) 40 | CLEAN_FILES += $(SMF_MANIFESTS_IN:%.in=%) 41 | -------------------------------------------------------------------------------- /tools/mk/Makefile.smf.targ: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | 8 | # 9 | # Copyright (c) 2014, Joyent, Inc. 10 | # 11 | 12 | # 13 | # Makefile.smf.targ: see Makefile.smf.defs. 14 | # 15 | # NOTE: This makefile comes from the "eng" repo. It's designed to be dropped 16 | # into other repos as-is without requiring any modifications. If you find 17 | # yourself changing this file, you should instead update the original copy in 18 | # eng.git and then update your repo to use the new version. 19 | # 20 | .PHONY: check-manifests 21 | check-manifests: $(SMF_MANIFESTS:%=%.smfchk) 22 | 23 | %.smfchk: % 24 | $(XMLLINT) --path $(dir $(SMF_DTD)) --dtdvalid $(SMF_DTD) $^ 25 | 26 | check:: check-manifests 27 | 28 | $(SMF_MANIFESTS): %: %.in 29 | $(SED) -e 's#@@NODE@@#@@PREFIX@@/$(NODE_INSTALL)/bin/node#' $< > $@ 30 | -------------------------------------------------------------------------------- /tools/mk/Makefile.targ: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | 8 | # 9 | # Copyright (c) 2014, Joyent, Inc. 10 | # 11 | 12 | # 13 | # Makefile.targ: common targets. 14 | # 15 | # NOTE: This makefile comes from the "eng" repo. It's designed to be dropped 16 | # into other repos as-is without requiring any modifications. If you find 17 | # yourself changing this file, you should instead update the original copy in 18 | # eng.git and then update your repo to use the new version. 19 | # 20 | # This Makefile defines several useful targets and rules. You can use it by 21 | # including it from a Makefile that specifies some of the variables below. 22 | # 23 | # Targets defined in this Makefile: 24 | # 25 | # check Checks JavaScript files for lint and style 26 | # Checks bash scripts for syntax 27 | # Checks SMF manifests for validity against the SMF DTD 28 | # 29 | # clean Removes built files 30 | # 31 | # docs Builds restdown documentation in docs/ 32 | # 33 | # prepush Depends on "check" and "test" 34 | # 35 | # test Does nothing (you should override this) 36 | # 37 | # xref Generates cscope (source cross-reference index) 38 | # 39 | # For details on what these targets are supposed to do, see the Joyent 40 | # Engineering Guide. 41 | # 42 | # To make use of these targets, you'll need to set some of these variables. Any 43 | # variables left unset will simply not be used. 44 | # 45 | # BASH_FILES Bash scripts to check for syntax 46 | # (paths relative to top-level Makefile) 47 | # 48 | # CLEAN_FILES Files to remove as part of the "clean" target. Note 49 | # that files generated by targets in this Makefile are 50 | # automatically included in CLEAN_FILES. These include 51 | # restdown-generated HTML and JSON files. 52 | # 53 | # DOC_FILES Restdown (documentation source) files. These are 54 | # assumed to be contained in "docs/", and must NOT 55 | # contain the "docs/" prefix. 56 | # 57 | # JSL_CONF_NODE Specify JavaScriptLint configuration files 58 | # JSL_CONF_WEB (paths relative to top-level Makefile) 59 | # 60 | # Node.js and Web configuration files are separate 61 | # because you'll usually want different global variable 62 | # configurations. If no file is specified, none is given 63 | # to jsl, which causes it to use a default configuration, 64 | # which probably isn't what you want. 65 | # 66 | # JSL_FILES_NODE JavaScript files to check with Node config file. 67 | # JSL_FILES_WEB JavaScript files to check with Web config file. 68 | # 69 | # JSON_FILES JSON files to be validated 70 | # 71 | # JSSTYLE_FILES JavaScript files to be style-checked 72 | # 73 | # You can also override these variables: 74 | # 75 | # BASH Path to bash (default: "bash") 76 | # 77 | # CSCOPE_DIRS Directories to search for source files for the cscope 78 | # index. (default: ".") 79 | # 80 | # JSL Path to JavaScriptLint (default: "jsl") 81 | # 82 | # JSL_FLAGS_NODE Additional flags to pass through to JSL 83 | # JSL_FLAGS_WEB 84 | # JSL_FLAGS 85 | # 86 | # JSON Path to json tool (default: "json") 87 | # 88 | # JSSTYLE Path to jsstyle (default: "jsstyle") 89 | # 90 | # JSSTYLE_FLAGS Additional flags to pass through to jsstyle 91 | # 92 | # RESTDOWN_EXT By default '.md' is required for DOC_FILES (see above). 93 | # If you want to use, say, '.restdown' instead, then set 94 | # 'RESTDOWN_EXT=.restdown' in your Makefile. 95 | # 96 | 97 | # 98 | # Defaults for the various tools we use. 99 | # 100 | BASH ?= bash 101 | BASHSTYLE ?= tools/bashstyle 102 | CP ?= cp 103 | CSCOPE ?= cscope 104 | CSCOPE_DIRS ?= . 105 | JSL ?= jsl 106 | JSON ?= json 107 | JSSTYLE ?= jsstyle 108 | MKDIR ?= mkdir -p 109 | MV ?= mv 110 | RESTDOWN_FLAGS ?= 111 | RESTDOWN_EXT ?= .md 112 | RMTREE ?= rm -rf 113 | JSL_FLAGS ?= --nologo --nosummary 114 | 115 | ifeq ($(shell uname -s),SunOS) 116 | TAR ?= gtar 117 | else 118 | TAR ?= tar 119 | endif 120 | 121 | 122 | # 123 | # Defaults for other fixed values. 124 | # 125 | BUILD = build 126 | DISTCLEAN_FILES += $(BUILD) 127 | DOC_BUILD = $(BUILD)/docs/public 128 | 129 | # 130 | # Configure JSL_FLAGS_{NODE,WEB} based on JSL_CONF_{NODE,WEB}. 131 | # 132 | ifneq ($(origin JSL_CONF_NODE), undefined) 133 | JSL_FLAGS_NODE += --conf=$(JSL_CONF_NODE) 134 | endif 135 | 136 | ifneq ($(origin JSL_CONF_WEB), undefined) 137 | JSL_FLAGS_WEB += --conf=$(JSL_CONF_WEB) 138 | endif 139 | 140 | # 141 | # Targets. For descriptions on what these are supposed to do, see the 142 | # Joyent Engineering Guide. 143 | # 144 | 145 | # 146 | # Instruct make to keep around temporary files. We have rules below that 147 | # automatically update git submodules as needed, but they employ a deps/*/.git 148 | # temporary file. Without this directive, make tries to remove these .git 149 | # directories after the build has completed. 150 | # 151 | .SECONDARY: $($(wildcard deps/*):%=%/.git) 152 | 153 | # 154 | # This rule enables other rules that use files from a git submodule to have 155 | # those files depend on deps/module/.git and have "make" automatically check 156 | # out the submodule as needed. 157 | # 158 | deps/%/.git: 159 | git submodule update --init deps/$* 160 | 161 | # 162 | # These recipes make heavy use of dynamically-created phony targets. The parent 163 | # Makefile defines a list of input files like BASH_FILES. We then say that each 164 | # of these files depends on a fake target called filename.bashchk, and then we 165 | # define a pattern rule for those targets that runs bash in check-syntax-only 166 | # mode. This mechanism has the nice properties that if you specify zero files, 167 | # the rule becomes a noop (unlike a single rule to check all bash files, which 168 | # would invoke bash with zero files), and you can check individual files from 169 | # the command line with "make filename.bashchk". 170 | # 171 | .PHONY: check-bash 172 | check-bash: $(BASH_FILES:%=%.bashchk) $(BASH_FILES:%=%.bashstyle) 173 | 174 | %.bashchk: % 175 | $(BASH) -n $^ 176 | 177 | %.bashstyle: % 178 | $(BASHSTYLE) $^ 179 | 180 | .PHONY: check-json 181 | check-json: $(JSON_FILES:%=%.jsonchk) 182 | 183 | %.jsonchk: % 184 | $(JSON) --validate -f $^ 185 | 186 | # 187 | # The above approach can be slow when there are many files to check because it 188 | # requires that "make" invoke the check tool once for each file, rather than 189 | # passing in several files at once. For the JavaScript check targets, we define 190 | # a variable for the target itself *only if* the list of input files is 191 | # non-empty. This avoids invoking the tool if there are no files to check. 192 | # 193 | JSL_NODE_TARGET = $(if $(JSL_FILES_NODE), check-jsl-node) 194 | .PHONY: check-jsl-node 195 | check-jsl-node: $(JSL_EXEC) 196 | $(JSL) $(JSL_FLAGS) $(JSL_FLAGS_NODE) $(JSL_FILES_NODE) 197 | 198 | JSL_WEB_TARGET = $(if $(JSL_FILES_WEB), check-jsl-web) 199 | .PHONY: check-jsl-web 200 | check-jsl-web: $(JSL_EXEC) 201 | $(JSL) $(JSL_FLAGS) $(JSL_FLAGS_WEB) $(JSL_FILES_WEB) 202 | 203 | .PHONY: check-jsl 204 | check-jsl: $(JSL_NODE_TARGET) $(JSL_WEB_TARGET) 205 | 206 | JSSTYLE_TARGET = $(if $(JSSTYLE_FILES), check-jsstyle) 207 | .PHONY: check-jsstyle 208 | check-jsstyle: $(JSSTYLE_EXEC) 209 | $(JSSTYLE) $(JSSTYLE_FLAGS) $(JSSTYLE_FILES) 210 | 211 | .PHONY: check 212 | check:: check-jsl check-json $(JSSTYLE_TARGET) check-bash 213 | @echo check ok 214 | 215 | .PHONY: clean 216 | clean:: 217 | -$(RMTREE) $(CLEAN_FILES) 218 | 219 | .PHONY: distclean 220 | distclean:: clean 221 | -$(RMTREE) $(DISTCLEAN_FILES) 222 | 223 | CSCOPE_FILES = cscope.in.out cscope.out cscope.po.out 224 | CLEAN_FILES += $(CSCOPE_FILES) 225 | 226 | .PHONY: xref 227 | xref: cscope.files 228 | $(CSCOPE) -bqR 229 | 230 | .PHONY: cscope.files 231 | cscope.files: 232 | find $(CSCOPE_DIRS) -name '*.c' -o -name '*.h' -o -name '*.cc' \ 233 | -o -name '*.js' -o -name '*.s' -o -name '*.cpp' > $@ 234 | 235 | # 236 | # The "docs" target is complicated because we do several things here: 237 | # 238 | # (1) Use restdown to build HTML and JSON files from each of DOC_FILES. 239 | # 240 | # (2) Copy these files into $(DOC_BUILD) (build/docs/public), which 241 | # functions as a complete copy of the documentation that could be 242 | # mirrored or served over HTTP. 243 | # 244 | # (3) Then copy any directories and media from docs/media into 245 | # $(DOC_BUILD)/media. This allows projects to include their own media, 246 | # including files that will override same-named files provided by 247 | # restdown. 248 | # 249 | # Step (3) is the surprisingly complex part: in order to do this, we need to 250 | # identify the subdirectories in docs/media, recreate them in 251 | # $(DOC_BUILD)/media, then do the same with the files. 252 | # 253 | DOC_MEDIA_DIRS := $(shell find docs/media -type d 2>/dev/null | grep -v "^docs/media$$") 254 | DOC_MEDIA_DIRS := $(DOC_MEDIA_DIRS:docs/media/%=%) 255 | DOC_MEDIA_DIRS_BUILD := $(DOC_MEDIA_DIRS:%=$(DOC_BUILD)/media/%) 256 | 257 | DOC_MEDIA_FILES := $(shell find docs/media -type f 2>/dev/null) 258 | DOC_MEDIA_FILES := $(DOC_MEDIA_FILES:docs/media/%=%) 259 | DOC_MEDIA_FILES_BUILD := $(DOC_MEDIA_FILES:%=$(DOC_BUILD)/media/%) 260 | 261 | # 262 | # Like the other targets, "docs" just depends on the final files we want to 263 | # create in $(DOC_BUILD), leveraging other targets and recipes to define how 264 | # to get there. 265 | # 266 | .PHONY: docs 267 | docs:: \ 268 | $(DOC_FILES:%$(RESTDOWN_EXT)=$(DOC_BUILD)/%.html) \ 269 | $(DOC_FILES:%$(RESTDOWN_EXT)=$(DOC_BUILD)/%.json) \ 270 | $(DOC_MEDIA_FILES_BUILD) 271 | 272 | # 273 | # We keep the intermediate files so that the next build can see whether the 274 | # files in DOC_BUILD are up to date. 275 | # 276 | .PRECIOUS: \ 277 | $(DOC_FILES:%$(RESTDOWN_EXT)=docs/%.html) \ 278 | $(DOC_FILES:%$(RESTDOWN_EXT)=docs/%json) 279 | 280 | # 281 | # We do clean those intermediate files, as well as all of DOC_BUILD. 282 | # 283 | CLEAN_FILES += \ 284 | $(DOC_BUILD) \ 285 | $(DOC_FILES:%$(RESTDOWN_EXT)=docs/%.html) \ 286 | $(DOC_FILES:%$(RESTDOWN_EXT)=docs/%.json) 287 | 288 | # 289 | # Before installing the files, we must make sure the directories exist. The | 290 | # syntax tells make that the dependency need only exist, not be up to date. 291 | # Otherwise, it might try to rebuild spuriously because the directory itself 292 | # appears out of date. 293 | # 294 | $(DOC_MEDIA_FILES_BUILD): | $(DOC_MEDIA_DIRS_BUILD) 295 | 296 | $(DOC_BUILD)/%: docs/% | $(DOC_BUILD) 297 | $(CP) $< $@ 298 | 299 | docs/%.json docs/%.html: docs/%$(RESTDOWN_EXT) | $(DOC_BUILD) $(RESTDOWN_EXEC) \ 300 | $(EXTRA_DOC_DEPS) 301 | $(RESTDOWN) $(RESTDOWN_FLAGS) -m $(DOC_BUILD) $< 302 | 303 | $(DOC_BUILD): 304 | $(MKDIR) $@ 305 | 306 | $(DOC_MEDIA_DIRS_BUILD): 307 | $(MKDIR) $@ 308 | 309 | # 310 | # The default "test" target does nothing. This should usually be overridden by 311 | # the parent Makefile. It's included here so we can define "prepush" without 312 | # requiring the repo to define "test". 313 | # 314 | .PHONY: test 315 | test: 316 | 317 | .PHONY: prepush 318 | prepush: check test 319 | --------------------------------------------------------------------------------