Commit Graph

320 Commits

Author SHA1 Message Date
Tim Perry
2c46c59a79 Update resin-image-fs to stop non-config commands failing in node 10
This doesn't fix actual usage of image fs, just makes it possible to
stop commands that don't use it from failing entirely.

Connects-To: #869
Change-Type: patch
2018-04-30 11:14:39 +02:00
Tim Perry
37e4ec6364 Rename expectedError to exitWithExpectedError 2018-04-17 15:18:06 +02:00
Tim Perry
6a8b947c2e Don't report lots of user input errors
Change-Type: patch
2018-04-17 15:18:06 +02:00
Akis Kesoglou
4f167cb836 Address review feedback 2018-03-22 13:26:47 +02:00
Akis Kesoglou
9455d438e2 Formatting fixes 2018-03-22 13:26:47 +02:00
Akis Kesoglou
a356ecf9b6 Remove unused code 2018-03-22 13:26:47 +02:00
Akis Kesoglou
62f006b89a Add legacy deploy method back
This mostly reverts the removal of the legacy deploy code that pushed image tars via the builder. It’s needed for users to avoid having to switch between CLI versions in order to push to legacy apps as well.

Note: this pins resin-sdk to 9.0.0-beta14 as I couldn’t get it to install otherwise — npm would always install 9.0.0-beta9 instead.

Change-Type: minor
2018-03-22 13:26:47 +02:00
Akis Kesoglou
242c3731ee Remove redundant import 2018-03-19 20:52:51 +02:00
Akis Kesoglou
5f7eee8eac Make sure image name is all lowercase
Change-Type: patch
2018-03-19 20:52:51 +02:00
Akis Kesoglou
1833f6ff0a Improve handling of build log output
This makes sure build logs don’t leak escape sequences and new lines and they don’t break the output. Also improved “inline” logs by normalising the stream before passing it to “transpose build stream”.

Fixes: #808
Change-Type: patch
2018-03-19 20:52:51 +02:00
Akis Kesoglou
fe01ead023 Fix getting window size when there’s no TTY attached
Change-Type: patch
2018-03-15 10:30:54 +02:00
Akis Kesoglou
14a3f51b73
Add docker-compose-aware builds and deployments
Legacy behaviour is mostly retained. The most notable change in behaviour is that invoking `resin deploy` without options is now allowed (see help string how it behaves).

In this commit there are also the following notable changes:

- Deploy/Build are promoted to primary commands
- Extracts QEMU-related code to a new file
- Adds a utility file to retrieve the CLI version and its parts
- Adds a helper that can be used to manipulate display on capable clients
- Declares several new dependencies. Most are already indirectly installed via some dependency

Change-Type: minor
2018-03-07 14:48:05 +00:00
Akis Kesoglou
96116aeaec
Fix invoking undefined method
Have no idea how this used to work.
2018-03-07 14:47:16 +00:00
Akis Kesoglou
299bc0db13
Update docker-toolbelt
New version is 3.1.0.

The updated version is not backwards compatible as it removes all *Async methods that are in wide use in the CLI. The workaround for now is to manually promisify the client and replace all `new Docker()` calls with a shared function that returns a promisified client.
2018-03-07 14:47:15 +00:00
Tim Perry
079ce552e3
*BREAKING*: Remove support for plugins entirely
There are very few plugins in real-world use, we're not actively working
on this at all, and the current approach won't work once we move to
standalone node-less binary installation anyway.

Change-Type: major
2018-03-07 14:46:35 +00:00
Alexis Svinartchouk
76a5cdc977
Require multicontainer SDK
* require('resin-sdk') => multicontainer SDK
 * require('resin-sdk-preconfigured') => 6.15.0 SDK
 * all 'resin-sdk' requires replaced with 'resin-sdk-preconfigured'
 * resin-sdk-preconfigured TS typings are copy pasted from the current resin-sdk master

The idea is to progressively replace all 'resin-sdk-preconfigured'
requires with 'resin-sdk' (multicontainer sdk) and eventually remove
resin-sdk-preconfigured from package.json.

Change-Type: patch
2018-03-07 14:46:31 +00:00
Tim Perry
c12360daa8 Tweak TS & add missing deps that may cause build failures in some envs
Connects-To: #765
Change-Type: patch
2018-02-20 20:26:18 +01:00
Thodoris Greasidis
d1c773360f Fix uuid params being parsed a numbers
Connects-To: #489
Change-Type: patch
2018-02-01 17:48:01 +02:00
Tim Perry
0ba96adbbc Fix breakage in deploy command from recent TS conversion
Change-Type: patch
2018-01-11 10:33:08 +01:00
Tim Perry
83a76f7d6f Start using Prettier
Change-Type: patch
2018-01-10 09:23:00 +01:00
Tim Perry
612012aff8 Lots of small TypeScript tweaks & clarifications from review 2018-01-09 17:14:49 +01:00
Tim Perry
6daed83d88 Lint TypeScript and CoffeeScript with resin-lint
Change-Type: patch
2018-01-09 17:14:49 +01:00
Tim Perry
ffffd447f2 Convert most of utils to TypeScript
Change-Type: patch
2018-01-09 17:14:48 +01:00
Tim Perry
4b511c47f0 Start on some easy TS conversion 2018-01-09 17:14:48 +01:00
Andrew Shirley
ce5fd53822 convert windows paths to posix when passing to tar
Due to https://github.com/mafintosh/tar-stream/issues/3, the tar module
needs posix style paths but system-specific paths are being supplied

Change-Type: patch
2018-01-08 22:50:11 +00:00
Tim Perry
eef0d9cdbe Print help even for expected errors
Change-Type: patch
2017-11-16 19:51:17 +01:00
Tim Perry
f7075d7db9 Fix issue where network settings were not used by config generate
Change-Type: patch
2017-11-16 15:03:49 +01:00
Tim Perry
890a02e2c8 Fix 'cannot read property R_OK of undefined' error in Node >=6 <6.3
Change-Type: patch
2017-11-11 12:29:49 +01:00
Tim Perry
a8f1d16b26 Make resin os configure safe with device keys for all ResinOS versions 2017-10-18 13:43:16 +02:00
Tim Perry
492e35e5c2 Fix lodash bugs in device move & quickstart
Change-Type: patch
2017-08-31 20:22:36 +08:00
Tim Perry
2bbd45e867 Use DOCKER_HOST from env if possible, and no connection options are available
Connects-to: #625
Change-Type: patch
2017-08-31 15:18:32 +08:00
Cameron Diver
dc1b3c3239
Allow the looking up of applications with the owner
change-type: minor
Connects-to: #594
Signed-off-by: Cameron Diver <cameron@resin.io>
2017-08-14 17:00:33 +01:00
Alexis Svinartchouk
22b3c39b2b Integrate resin-preload
* split docker connection options from lib.utils.docker.appendOptions

Connects to #609
Connects to https://github.com/resin-io/resin-preload/pull/81

Change-Type: minor
2017-08-11 15:43:07 +02:00
Tim Perry
b7e2c2571f Remove inconsistent (and now unneccesary) 'Tagging image as' message
Change-Type: patch
2017-08-11 13:30:44 +02:00
Tim Perry
5daa682183 Provide a helpful warning when Docker is not installed
Change-Type: patch
2017-08-10 21:40:05 +02:00
Tim Perry
1f0bec39d9 Hide the intro quickstart message for now (until it gets renovated) 2017-07-18 16:57:16 +02:00
Tim Perry
e2a165ce80 Show a correct [Info] tag with the deploying progress bar 2017-06-28 18:57:49 +02:00
Tim Perry
15e677e9f1 Refactor stream logger to keep streams as state 2017-06-28 18:52:40 +02:00
Jacinto Arias
bea7b2035a Added --squash option to resin build command 2017-06-26 13:33:50 +02:00
Cameron Diver
5000febf72
Read ca files and convert to string before passing to the docker daemon
Before this commit, the docker daemon would recieve the filename of the
.pem files, which would be interpreted as the body and would fail. This
commit ensures that the actual body of the pem files are sent to the
daemon.

Change-type: patch
Connects-to: #562
Signed-off-by: Cameron Diver <cameron@resin.io>
2017-06-21 11:11:24 +01:00
Tim Perry
8efaec63ff Merge pull request #559 from resin-io/558-absolute-qemu
Make emulated builds reliable in the presence for WORKDIR comands
2017-06-15 19:41:52 +02:00
Tim Perry
b756f2a597 Make emulated builds reliable in the presence for WORKDIR comands
Connects-To: #558
Change-Type: patch
2017-06-15 16:36:44 +02:00
Eugene Mirotin
77a4c6fdc2 move available-drives command to util 2017-06-15 16:43:02 +03:00
Eugene Mirotin
ed83514a2f allow passing --drive to resin device init 2017-06-15 16:39:55 +03:00
Tim Perry
a29b40eefa Move promise.spread to promise.join for clarity (from review) 2017-06-15 12:34:26 +02:00
Tim Perry
df3c5ca07f Gzip while streaming, rather than gzipping the buffer up front
Connects-To: #549
2017-06-15 12:01:22 +02:00
Tim Perry
e584dc43f7 Gzip images when uploading in resin deploy
Change-Type: minor
Connects-To: #549
2017-06-15 12:01:22 +02:00
Tim Perry
90a5b15dbc Refactor docker stream buffering before start gzipping 2017-06-15 12:01:22 +02:00
Tim Perry
37ec11bf25 Ensure emulated builds use the correct relative path to qemu
Change-Type: patch
Connects-To: #553
2017-06-14 20:50:24 +02:00
Cameron Diver
f2862f7fe2
Add emulated build option to resin build
This commit adds the ability to run a Docker build for an architecture
which is not the host architecture, using qemu-linux-user. Currently
this is only supported for linux.

Added:
* Installation of qemu which supports propagated execve flags
* Copying of qemu binary into the build context
* Transposing the given Dockerfile to use the qemu binary
* Intercepting of the build stream, so the output looks *almost* exactly
  the same.

Change-type: minor
Signed-off-by: Cameron Diver <cameron@resin.io>
2017-06-14 12:06:03 +01:00
Cameron Diver
abc183a729
Change update check interval to once a day
This gives the user enough notice to stay well updated, but won't spam
them if they're using resin-cli frequently.

Connects-to: #485
Change-type: patch
Signed-off-by: Cameron Diver <cameron@resin.io>
2017-05-23 17:29:23 -07:00
Eugene Mirotin
2d729a82a0 fix valid-email path 2017-05-20 00:19:31 +03:00
Eugene Mirotin
bc79832e1d resin ssh proxy support 2017-05-12 18:09:43 +03:00
Akis Kesoglou
654ec75598 Renamed build arg option to —buildArg/-B 2017-05-11 14:20:24 +03:00
Akis Kesoglou
66876a2c85 Add ability to specify built-time variables for local build
Change-Type: patch
2017-05-11 14:14:43 +03:00
Cameron Diver
404348f92e
Highlight cache usage in resin build
This commit will highlight the usage of the cache when doing a docker
build via `resin build`, which not only helps the user understand what
the build is doing, but also achieves more parity with the cloud
builder.

Change-type: patch
Signed-off-by: Cameron Diver <cameron@resin.io>
2017-05-04 14:09:23 +01:00
Cameron Diver
d249ac168a
Fix the not-enough-unicorns bug
Add successful build indicator in the form of a unicorn.

Change-type: patch
Signed-off-by: Cameron Diver <cameron@resin.io>
2017-05-04 13:18:25 +01:00
Cameron Diver
3ff5880ae3
Allow resin-cli deploy to also upload build logs if present
If build is ran through `resin deploy`, then logs will be stored and
uploaded to the database, where the dashboard can display them

Change-type: minor
Signed-off-by: Cameron Diver <cameron@resin.io>
2017-05-04 13:11:50 +01:00
Cameron Diver
f50ae65560
Add cloud-builder builder output parity to build and deploy
Change-type: minor
Signed-off-by: Cameron Diver <cameron@resin.io>
2017-04-25 13:13:11 +01:00
Cameron Diver
4fa1a9c1c6
Share nocache and tag build options between build and deploy
`resin build` had access to the `--nocache` and `--tag` options for
building with docker, but `resin deploy` did not. This commit adds the
options to the shared dockerUtils.appendOptions function.

Change-type: patch
Signed-off-by: Cameron Diver <cameron@resin.io>
2017-04-24 20:05:18 +01:00
Cameron Diver
9050cb1975
Respect source parameter in resin build
Upon changing the name of the source parameter from `context`, some
places weren't changed, this commit fixes that.

Change-type: patch
Signed-off-by: Cameron Diver <cameron@resin.io>
2017-04-24 16:41:15 +01:00
Cameron Diver
d3772386bf
Add ability to build and deploy image locally using resin-cli
Using `resin build` a user can now build an image on their own docker
daemon. The daemon can be accessed via a local socket, a remote host and
a remote host over a TLS socket. Project type resolution is supported.
Nocache and tagging of images is also supported.

Using `resin deploy` a user can now deploy an image to their fleet. The
image can either be built by `resin-cli`, plain Docker, or from a remote
source.

Change-type: minor
Signed-off-by: Cameron Diver <cameron@resin.io>
2017-04-23 14:31:45 +01:00
Eugene Mirotin
77b30409bb update resin-device-init to pull in etcher-image-write 2017-03-28 14:37:13 +03:00
Eugene Mirotin
08b3db717e use individual methods promisification instead of promisifyAll 2017-03-27 12:14:55 +03:00
Eugene Mirotin
6cf32e445a isolate the sudo-runnable command 2017-03-27 11:43:35 +03:00
Kostas Lekkas
f940d7428c
Point to forums instead of gitter
change-type: patch
2017-03-23 12:19:59 +02:00
Tim Perry
b629ee6164
Move to preconfigured resin sdk 2017-01-25 19:33:43 +01:00
Tim Perry
7a4de5357e
Fix some issues with Resin-SDK usage after initial testing 2017-01-25 19:25:12 +01:00
Eugene Mirotin
f17cbb1205
use the new SDK factory 2017-01-25 19:25:12 +01:00
Kostas Lekkas
16a1741374 resin sync: always display device selection dialog when uuid is not passed as an argument
Closes #375
2016-09-15 13:09:25 +03:00
Kostas Lekkas
e0a2217b94 resin sync/ssh: always display selection dialog, even for a single online device
Closes #373
2016-09-15 13:09:25 +03:00
Juan Cruz Viotti
8b485b5ad5 Attempt to get device type from the image first partition
New images will ship a `device-type.json` file in the first partition,
which we can use instead of querying the API for certain configuration
and initialisation commands.

If the file is not found, or is malformed, we still fallback to the API.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
2016-09-14 11:06:17 -07:00
Kostas Lekkas
68808e760e resin sync: filter out offline devices in interactive choosing dialog 2016-07-07 19:12:39 +03:00
Juan Cruz Viotti
4a05ce3f53 Attempt to infer the device uuid in resin sync
This PR adds functionality to `resin sync` to try to infer what the
device uuid is as follows:

- If the argument to `resin sync` is an app, get all the devices from
that application. If there is only one, auto-select it, otherwise show
an interactive drive selection widget.

- If the argument to `resin sync` is a uuid, use it directly, without
trying to infer anything.

- If no argument is passed to `resin sync`, display an interactive
selection widget showing all your devices from all your applications.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-04-25 08:57:19 -04:00
Juan Cruz Viotti
c5692f8b13 Only throw "Invalid 2FA code" if we're sure that's the cause
Currently, such error will be thrown when
`resin.auth.twoFactor.challenge()` rejects, but an invalid code is not
the only thing this function can reject for.
2016-03-17 15:37:02 -04:00
Juan Cruz Viotti
30663b0301 Force update alert to be always shown
If `updateCheckInterval` has any meanginful value, the alert will be
shown one out of ten times, or something like that, making the user
likely to miss updates.

The underlying issue is that `update-notifier`, if it detects a cached
update notification, it deletes it, and only attempts to show it back if
`updateCheckInterval` is greater than `Date.now() - lastUpdateCheck`.
2016-03-08 09:23:03 -04:00
Juan Cruz Viotti
bee523828a Improve awaitDevice success message 2016-01-25 08:59:09 -04:00
Juan Cruz Viotti
4645ad06bc Redirect users to signup from login if they don't have an account 2016-01-13 00:25:31 -04:00
Juan Cruz Viotti
c3a5998d5c Reuse messages 2016-01-12 10:45:32 -04:00
Juan Cruz Viotti
78ab2af8ba Print verbose help in resin help command 2016-01-12 10:39:29 -04:00
Juan Cruz Viotti
8d709aea7d Implement purely interactive login command
The new login command interactively asks the user if he wants to login
using web/credentials/token.
2016-01-12 09:08:03 -04:00
Juan Cruz Viotti
70ea8dd1a3 Redirect users to GitHub and Gitter in case of errors
Users will ge a better experience by knowing exactly where to go for
help if things go wrong.
2016-01-12 08:31:40 -04:00
Juan Cruz Viotti
9cfce68489 Change license to Apache 2.0 2016-01-03 23:58:51 -04:00
Juan Cruz Viotti
abc8399260 Explain why we need the computer password on device init 2015-12-02 11:15:20 -04:00
Juan Cruz Viotti
e08c3752f9 Show device types when selecting applications
Some CLI commans prompt to select an existing application, presending a
dropdown with all the application names, however it's hard to remember
which application belon to which device type, which makes it easier to
select the wrong application.
2015-11-23 09:23:08 -04:00
Juan Cruz Viotti
c3b5a768e1 Handle Windows permissions elevation automatically 2015-11-12 13:30:48 -04:00
Juan Cruz Viotti
ba318f2939 Implement device move command
This command allows to user to move a device to another application he
owns.
2015-11-12 07:47:16 -04:00
Juan Cruz Viotti
c866f6e46c Use president to provide sudo functionality 2015-10-26 09:47:49 -04:00
Juan Cruz Viotti
de83a06db8 Clarify the need of computer password during sudo
Since we only prompt "Password:", it might be confusing for some users
that think they have to enter their Resin.io password instead.

Fixes: https://github.com/resin-io/resin-cli/issues/239
2015-10-26 08:49:41 -04:00
Juan Cruz Viotti
363f12f81b Refer to the correct waiting stream function
We recently changed to using `rindle`, however looks like we forgot
to replace this particular instance.
2015-10-26 08:34:07 -04:00
Juan Cruz Viotti
fc5fe6cf68 Fix validation module require typo 2015-10-21 13:28:51 -04:00
Juan Cruz Viotti
8fe08642f5 Merge pull request #245 from resin-io/jviotti/feature/simplify-quickstart
Remove project directory creation in quickstart
2015-10-21 13:20:35 -04:00
Juan Cruz Viotti
822632718f Merge pull request #247 from resin-io/jvioti/refactor/os
Remove unused getOperatingSystem function
2015-10-21 11:43:19 -04:00
Juan Cruz Viotti
f66cd00646 Remove project directory creation in quickstart
The last part of `quickstart` feels weird. By consensus, we remove the
part that attempts to create a project directory and leave that step to
the user.
2015-10-21 11:18:29 -04:00
Juan Cruz Viotti
965fd8fc19 Remove unused getOperatingSystem function 2015-10-21 10:20:38 -04:00
Juan Cruz Viotti
7a4f551a47 Use rindle instead of custom waitStream 2015-10-21 10:17:10 -04:00
Juan Cruz Viotti
c1e6a28640 Refactor validation to a single place 2015-10-21 09:37:25 -04:00
Juan Cruz Viotti
8913fb515b Implement user/password login with 2FA support 2015-10-21 08:28:20 -04:00
Juan Cruz Viotti
ff81c1e514 Merge pull request #234 from resin-io/jviotti/feature/advanced-options
Ignore advanced configuration questions by default
2015-10-20 09:12:38 -04:00
Juan Cruz Viotti
ec28bd9c9e Ignore advanced configuration questions by default
The advanced questions can be enabled by passing `--advanced` in `os
configure`.
2015-10-19 14:02:57 -04:00
Juan Cruz Viotti
0b7e2a2c8c Require application name to have at least 4 characters
We get a weird error message from pine otherwise:

	ResinRequestError: Request error: It is necessary that each app name
	that is of a user (Auth), has a Length (Type) that is greater than or
	equal to 4.
2015-10-19 10:56:02 -04:00
Juan Cruz Viotti
1cfbd4197d Improve the way the update notifier is shown
Current has the following problems:

- Our custom message gets printed even if the notifier doesn't contain
an update.

- The notifier box is deferred, therefore it's printed at the end of the
command. Since our custom message is printed at the beginning, it makes
no sense at all.
2015-10-15 09:18:45 -04:00
Juan Cruz Viotti
adf4aef517 Clarify the need for admin privileges on update
Fixes: https://github.com/resin-io/resin-cli/issues/223
2015-10-14 13:45:08 -04:00
Juan Cruz Viotti
3149464c7a Shorten the length of await device message
If the spinner message doesn't fit in your terminal, each spinner
position will be printed in different lines.

We mitigate this by dramatically shortenning the message.
2015-10-07 11:38:59 -04:00
Juan Cruz Viotti
97d9b7816f Merge pull request #214 from resin-io/jviotti/feature/plugin-warn-red
Print plugin warnings in red as other errors
2015-10-06 19:18:33 -04:00
Juan Cruz Viotti
ec77437080 Print plugin warnings in red as other errors
For the sake of consistency.
2015-10-06 18:51:17 -04:00
Juan Cruz Viotti
f8470287c1 Separate general help per topic relevance
Only list primary commands by default, unless a `--verbose` option is
passed to list the additional ones.

Fixes: https://github.com/resin-io/resin-cli/issues/101
2015-10-02 08:50:32 -04:00
Juan Cruz Viotti
445e37ccaf Call os initialize as an elevated process
Currently, the fact that `os initialize` requires elevated permissions
forced us to require calling commands that reuse it, such as `device
init` and `quickstart` with administrator permissions as well.

This ended up causing issues like saving images in the cache that belong
to root, or initializing git repositories that requires `sudo` to
commit.

The solution is to call `os initialize` as a child process preppending
`sudo` within `device init`.

Fixes: https://github.com/resin-io/resin-cli/issues/109
2015-10-01 13:07:53 -04:00
Juan Cruz Viotti
f17e9c97b8 Prompt for select application if running device init with no arguments
Currently, if `device init` was ran without an application argument, we
attempted to get the application name from the current directory, given
it was a git repository.

This approach led to confusions from time to time, so now we prompt the
user to select one of it's own applications from a dropdown instead of
checking the current directory in this edge case.

Fixes: https://github.com/resin-io/resin-cli/issues/197
2015-09-29 15:10:59 -04:00
Juan Cruz Viotti
42256384be Implement os configure
This command, given a path to an image and a device uuid, perform
configuration based on the resin-device-type manifests.
2015-09-29 13:47:10 -04:00
Juan Cruz Viotti
f6d8f12ba2 Implement os download command
This command download an unconfigured image to both the cache and to the
specified location by the `--output` option.
2015-09-29 13:03:14 -04:00
Juan Cruz Viotti
adc0b183cd Improve device awaiting message
Current message sounds too robotic.
2015-09-11 19:13:30 +03:00
Juan Cruz Viotti
64c8420c9d Implement device specs. Fix #99
Support for all devices. Tested in the following ones:

- Intel Edison.
- Raspberry Pi 2.
- Parallella.
2015-09-11 13:02:59 +03:00
Juan Cruz Viotti
a090e6c21d Refactor quickstart
- Use promises.
- Move some logic to `helpers`.
- Inline `device await` command.
2015-08-27 10:01:33 -04:00
Juan Cruz Viotti
d10d4ce185 Merge pull request #174 from resin-io/jviotti/feature/confirm-abortion
Add `Aborted` error message when not accepting a confirmation
2015-08-24 08:47:29 -04:00
Juan Cruz Viotti
5de0f66d7a Don't check for available updates when running as root
`update-notifier` persist its update check results in a file, which is
then read when running again the application.

If this file gets written when the application is being run as root, we
get ugly EPERM issues.
2015-08-20 16:54:22 -04:00
Juan Cruz Viotti
354921ca92 Add Aborted error message when not accepting a confirmation
This prevents a lot of duplicate code to check for confirmation status
and exit from the current action.
2015-08-20 16:16:20 -04:00
Juan Cruz Viotti
7f4863da86 Upgrade Nplugm to v3.0.0
This new version supports promises and contains speed improvements.
2015-08-19 11:27:28 -04:00
Juan Cruz Viotti
f19588032f Notify the user if there is an available update
For this we use the `update-notifier` module with its default settings.

This module will print a nice banner prompting the user to run the
corresponding npm command to update.
2015-08-18 08:53:06 -04:00
Juan Cruz Viotti
4647aa70c0 Implement utils/helpers to abstract common app patterns
- Add helpers.confirm() to abstract the process of asking for
confirmation.
- Add helpers.selectDeviceType() to abstract the form needed to ask for
device types.

The functions on this module are reused by app actions.
2015-08-13 14:04:47 -04:00