sonic-screwdriver 2.1.0 → 2.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c57f41a4fe34d84ef5b27b1a02119d4f44ebabfc7cb4a4c5b16eee2674d4a17
4
- data.tar.gz: 95a874ce5035de37d982a7e305c1da4fe264c12fa6caf4b25e789cf311c8ddf5
3
+ metadata.gz: 2ac8a33e325657ad0ee4fab9c2d7a4a1d8c3fafbaf0017fed20446983869c39b
4
+ data.tar.gz: 4b8bcf43b60ae33936f07b4d800173b2c1df27d091f1fac3e8f2f082501a8823
5
5
  SHA512:
6
- metadata.gz: d5945bde37e07a2bca384f1ed60b35aa03933adf6ce67fae1c3149c25df8debe564fe0b0ee1c266faafba48d7e3f815d8720b0f38eb40329884c7a795b17b099
7
- data.tar.gz: 3cacc002fd1f7926ec97a32534c62ed4c7081aee660173b93db3df2711c2dbeb61d33ae140c94eea336cb7f007715e964d418c817a7eff2ffeaffcd36139a05a
6
+ metadata.gz: 97d9a1992af8d4e2dbede1ae0f8f965b773b94cde16bc06493fc99932cdbc3205c63ebef16c649e95e2f6f9d539775c45ed36db01897f7e33fcc80fe5509f9bb
7
+ data.tar.gz: dd12a4015571ef144a3a793f9cae38c09ab4f55f8353aea07fbe8c5d598057167b5111988d1a12c595a3d044213bf126deca1fc5c8901fa21b23b3742c28cc94
data/.circleci/config.yml CHANGED
@@ -7,7 +7,7 @@ jobs:
7
7
  build:
8
8
  docker:
9
9
  # specify the version you desire here
10
- - image: circleci/ruby:2.5.1-node-browsers
10
+ - image: circleci/ruby:2.6.5-node-browsers
11
11
 
12
12
  # Specify service dependencies here if necessary
13
13
  # CircleCI maintains a library of pre-built images
@@ -35,6 +35,8 @@ jobs:
35
35
  - run:
36
36
  name: install dependencies
37
37
  command: |
38
+ gem install bundler
39
+ gem update --system
38
40
  bundle install --jobs=4 --retry=3 --path vendor/bundle
39
41
 
40
42
  - save_cache:
data/.gitignore CHANGED
@@ -14,3 +14,4 @@ spec/reports
14
14
  test/tmp
15
15
  test/version_tmp
16
16
  tmp
17
+ Gemfile.lock
data/CHANGELOG.md CHANGED
@@ -1,7 +1,25 @@
1
1
  # Change Log
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
- This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
4
+ This project *loosely* adheres to [Semantic Versioning](http://semver.org/), even before v1.0.
5
+
6
+ ## [2.2.3] - 2021-04-12
7
+ - [#12](https://github.com/boltops-tools/sonic/pull/12) fix cli check
8
+
9
+ ## [2.2.2] - 2021-04-12
10
+ - [#11](https://github.com/boltops-tools/sonic/pull/11) cli check
11
+
12
+ ## [2.2.1] - 2021-04-12
13
+ - [#9](https://github.com/boltops-tools/sonic/pull/9) improve command array handling
14
+
15
+ ## [2.2.0]
16
+ - #7 sonic execute command: `--tags` and `--instance-id` options instead of polymorphic list. Breaking behavior.
17
+ - display output even if tags used
18
+ - configure default log group
19
+ - correct exit status
20
+
21
+ ## [2.1.1]
22
+ - use rainbow gem for terminal colors
5
23
 
6
24
  ## [2.1.0]
7
25
  - change the setting format to ssh.user instead of bastion.user
data/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
  [![Gitter](https://badges.gitter.im/boltopslabs/sonic.svg)](https://gitter.im/boltopslabs/sonic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
5
5
  [![Support](https://img.shields.io/badge/get-support-blue.svg)](https://boltops.com?utm_source=badge&utm_medium=badge&utm_campaign=sonic)
6
6
 
7
+ [![BoltOps Badge](https://img.boltops.com/boltops/badges/boltops-badge.png)](https://www.boltops.com)
8
+
7
9
  Sonic is a multi-functional tool that helps you manage AWS resources. Sonic contains a group of commands that help debug EC2 instances and ECS containers quickly.
8
10
 
9
11
  See [sonic-screwdriver.cloud](http://sonic-screwdriver.cloud) for full documentation.
@@ -32,15 +34,7 @@ By the time I get into the container, I need to remind my brain of what the orig
32
34
 
33
35
  You can install sonic with RubyGems
34
36
 
35
- ```sh
36
- gem install sonic
37
- ```
38
-
39
- If you want to quickly install sonic without having to worry about sonic's dependencies you can also install the Bolts Toolbelt which has sonic included.
40
-
41
- ```sh
42
- brew cask install boltopslabs/software/bolts
43
- ```
37
+ gem install sonic
44
38
 
45
39
  Full installation instructions are at [Install Sonic Screwdriver](http://sonic-screwdriver.cloud/docs/install/). There are some server side dependencies for some of the sonic commands, so it is important to read through the full installation guide.
46
40
 
@@ -48,30 +42,33 @@ Full installation instructions are at [Install Sonic Screwdriver](http://sonic-s
48
42
 
49
43
  Here is a quick overview of sonic abilities:
50
44
 
51
- ```sh
52
- # ssh into an instance
53
- sonic ssh i-0f7f833131a51ce35
54
- sonic ssh hi-web # ec2 tag
55
- sonic ssh hi-web --cluster staging # ecs service name
56
- sonic ssh hi-web --cluster staging # ecs service name
57
- sonic ssh 7fbc8c75-4675-4d39-a5a4-0395ff8cd474 --cluster staging # ECS container id
58
- sonic ssh 1ed12abd-645c-4a05-9acf-739b9d790170 --cluster staging # ECS task id
45
+ # ssh into an instance
46
+ sonic ssh i-0f7f833131a51ce35
47
+ sonic ssh demo-web # ec2 tag
48
+ sonic ssh demo-web --cluster staging # ecs service name
49
+ sonic ssh demo-web --cluster staging # ecs service name
50
+ sonic ssh 7fbc8c75-4675-4d39-a5a4-0395ff8cd474 --cluster staging # ECS container id
51
+ sonic ssh 1ed12abd-645c-4a05-9acf-739b9d790170 --cluster staging # ECS task id
52
+
53
+ # docker exec to a running ECS docker container
54
+ sonic ecs exec demo-web
59
55
 
60
- # docker exec to a running ECS docker container
61
- sonic ecs exec hi-web
56
+ # docker run with the same environment as the ECS docker running containers
57
+ sonic ecs sh demo-web
62
58
 
63
- # docker run with the same environment as the ECS docker running containers
64
- sonic ecs sh hi-web
59
+ # run command with instance ids
60
+ sonic execute --instance-ids i-111 uptime
61
+ sonic execute --instance-ids i-111,i-222 uptime
65
62
 
66
- # run command on 1 instance
67
- sonic execute i-0f7f833131a51ce35 uptime
63
+ # run command on all instances tagged with Name demo-web and worker
64
+ sonic execute --tags Name=demo-web,demo-worker uptime
68
65
 
69
- # run command on all instances tagged with hi-web and worker
70
- sonic execute hi-web,hi-worker uptime
66
+ # run command on all instances with multiple tags
67
+ # Quotes are important due to semi-colon
68
+ sonic execute --tags "Name=demo-web,demo-worker;Owner=test" uptime
71
69
 
72
- # list ec2 instances
73
- sonic list hi-web
74
- ```
70
+ # list ec2 instances
71
+ sonic list demo-web
75
72
 
76
73
  ## Contributing
77
74
 
@@ -16,16 +16,6 @@ You can also add sonic to your Gemfile in your project if you are working with a
16
16
  gem "sonic-screwdriver"
17
17
  ```
18
18
 
19
- ### Install with Bolts Toolbelt
20
-
21
- If you want to install sonic without having to worry about sonic's ruby dependency you can simply install the Bolts Toolbelt which has sonic included.
22
-
23
- ```sh
24
- brew cask install boltopslabs/software/bolts
25
- ```
26
-
27
- For more information about the Bolts Toolbelt or to get an installer for another operating system visit: [https://boltops.com/toolbelt](https://boltops.com/toolbelt)
28
-
29
19
  ### Server Side Dependencies
30
20
 
31
21
  For a small set of the commands there are server side dependencies.
@@ -6,56 +6,50 @@ title: Sonic Execute
6
6
 
7
7
  Sonic provides a way to execute commands remotely and securely across a list of AWS servers. It does this by leveraging [Amazon EC2 Run Command](https://aws.amazon.com/ec2/execute/). Sonic a simple interface and some conveniences for you. The command is called `sonic execute`:
8
8
 
9
- ```sh
10
- sonic execute [FILTER] [COMMAND]
11
- ```
9
+ sonic execute [FILTER] [COMMAND]
12
10
 
13
11
  ## Examples Summary
14
12
 
15
- ```sh
16
- sonic execute hi-web uptime
17
- sonic execute hi-web-prod uptime
18
- sonic execute i-030033c20c54bf149,i-030033c20c54bf150 uname -a
19
- sonic execute i-030033c20c54bf149 file://hello.sh
20
- ```
13
+ sonic execute --tags Name=demo-web uptime
14
+ sonic execute --tags Name=demo-web,demo-worker uptime # multiple tag values
15
+ sonic execute --instance-ids i-030033c20c54bf149,i-030033c20c54bf150 uname -a
16
+ sonic execute --instance-ids i-030033c20c54bf149 file://hello.sh
21
17
 
22
18
  ## Example Detailed
23
19
 
24
20
  Here's a command example output in detailed:
25
21
 
26
- ```sh
27
- $ sonic execute i-0bf51a000ab4e73a8 uptime
28
- Sending command to SSM with options:
29
- ---
30
- instance_ids:
31
- - i-0bf51a000ab4e73a8
32
- document_name: AWS-RunShellScript
33
- comment: sonic execute i-0bf51a000ab4e73a8 uptime
34
- parameters:
35
- commands:
36
- - uptime
37
- output_s3_region: us-east-1
38
- output_s3_bucket_name: [reacted]
39
- output_s3_key_prefix: ssm/commands/sonic
40
-
41
- Command sent to AWS SSM. To check the details of the command:
42
- aws ssm list-commands --command-id 0bb18d58-6436-49fd-9bfd-0c4b6c51c7a2
43
- aws ssm get-command-invocation --command-id 0bb18d58-6436-49fd-9bfd-0c4b6c51c7a2 --instance-id i-0bf51a000ab4e73a8
44
-
45
- Waiting for ssm command to finish.....
46
- Command finished.
47
-
48
- Displaying output for i-0bf51a000ab4e73a8.
49
- Command status: Success
50
- Command standard output:
51
- 01:08:10 up 8 days, 6:41, 0 users, load average: 0.00, 0.00, 0.00
52
-
53
- To see the more output details visit:
54
- https://us-west-2.console.aws.amazon.com/systems-manager/run-command/0bb18d58-6436-49fd-9bfd-0c4b6c51c7a2
55
-
56
- Pro tip: the console url is already in your copy/paste clipboard.
57
- $
58
- ```
22
+ $ sonic execute --instance-ids i-0bf51a000ab4e73a8 uptime
23
+ Sending command to SSM with options:
24
+ ---
25
+ instance_ids:
26
+ - i-0bf51a000ab4e73a8
27
+ document_name: AWS-RunShellScript
28
+ comment: sonic execute --instance-ids i-0bf51a000ab4e73a8 uptime
29
+ parameters:
30
+ commands:
31
+ - uptime
32
+ output_s3_region: us-east-1
33
+ output_s3_bucket_name: [reacted]
34
+ output_s3_key_prefix: ssm/commands/sonic
35
+
36
+ Command sent to AWS SSM. To check the details of the command:
37
+ aws ssm list-commands --command-id 0bb18d58-6436-49fd-9bfd-0c4b6c51c7a2
38
+ aws ssm get-command-invocation --command-id 0bb18d58-6436-49fd-9bfd-0c4b6c51c7a2 --instance-id i-0bf51a000ab4e73a8
39
+
40
+ Waiting for ssm command to finish.....
41
+ Command finished.
42
+
43
+ Displaying output for i-0bf51a000ab4e73a8.
44
+ Command status: Success
45
+ Command standard output:
46
+ 01:08:10 up 8 days, 6:41, 0 users, load average: 0.00, 0.00, 0.00
47
+
48
+ To see the more output details visit:
49
+ https://us-west-2.console.aws.amazon.com/systems-manager/run-command/0bb18d58-6436-49fd-9bfd-0c4b6c51c7a2
50
+
51
+ Pro tip: the console url is already in your copy/paste clipboard.
52
+ $
59
53
 
60
54
  Notice the conveniences of `sonic execute`, it:
61
55
 
@@ -69,28 +63,30 @@ The AWS SSM console looks like this:
69
63
 
70
64
  <img src="/img/tutorials/ec2-console-run-command.png" class="doc-photo" />
71
65
 
72
- ### Polymorphic Filter
66
+ ### Filter Options
73
67
 
74
- The `sonic execute` command can understand a variety of different filters. The filters can be a list of instances ids or one EC2 tag value. Note, ECS service names are *not* supported for the filter.
68
+ The `sonic execute` command can understand a variety of different filters: `--tags` and `--instance-ids`. Note, ECS service names are *not* supported for the filter.
75
69
 
76
70
  Here is an example, where the uptime command will run on both `i-030033c20c54bf149` and `i-030033c20c54bf150` instances.
77
71
 
78
- ```sh
79
- sonic execute i-066b140d9479e9681,i-09482b1a6e330fbf7 uptime
80
- ```
72
+ sonic execute --instance-ids i-066b140d9479e9681,i-09482b1a6e330fbf7 uptime
73
+
74
+ Here is an example, where the uptime command will run on instances tagged with `Name=demo-web`
75
+
76
+ sonic execute --tags Name=demo-web uptime
81
77
 
82
78
  ## Windows Support
83
79
 
84
80
  Windows is also supported. When running a command sonic will first attempt to use the `AWS-RunShellScript` run command, and if it detects that the instance's platform does not support `AWS-RunShellScript`, it will run the command with the `AWS-RunPowerShellScript` run command. Here's an example:
85
81
 
86
82
  ```
87
- $ sonic execute i-0917ad61b10fa1059 pwd
83
+ $ sonic execute --instance-ids i-0917ad61b10fa1059 pwd
88
84
  Sending command to SSM with options:
89
85
  ---
90
86
  instance_ids:
91
87
  - i-0917ad61b10fa1059
92
88
  document_name: AWS-RunShellScript
93
- comment: sonic execute i-0917ad61b10fa1059 pwd
89
+ comment: sonic execute --instance-ids i-0917ad61b10fa1059 pwd
94
90
  parameters:
95
91
  commands:
96
92
  - pwd
@@ -129,16 +125,12 @@ $
129
125
 
130
126
  Sometimes you might want to run more than just a one-liner command. If you need to run a full script, you can provide the file path to the script by designating it with `file://`. For example, here's a file called `hi.sh`:
131
127
 
132
- ```bash
133
- #!/bin/bash
134
- echo "hello world"
135
- ```
128
+ #!/bin/bash
129
+ echo "hello world"
136
130
 
137
131
  Here's how you run that file:
138
132
 
139
- ```sh
140
- sonic execute hi-web file://hi.sh
141
- ```
133
+ sonic execute demo-web file://hi.sh
142
134
 
143
135
  The file gets read by `sonic execute` and sent to EC2 Run Command to be executed.
144
136
 
@@ -6,10 +6,12 @@
6
6
  <div class="footer-col col-md-4">
7
7
  <h3>More Tools</h3>
8
8
  <ul class="list-unstyled tools">
9
- <li><a href="http://jack-eb.com">Jack</a></li>
10
- <li><a href="http://lono.cloud">Lono</a></li>
11
- <li><a href="http://ufoships.com">Ufo</a></li>
12
- <li><a href="https://boltops.com/toolbelt">Toolbelt</a></li>
9
+ <li><a href="https://terraspace.cloud">Terraspace</a></li>
10
+ <li><a href="https://kubes.guru">Kubes</a></li>
11
+ <li><a href="https://rubyonjets.com">Jets</a></li>
12
+ <li><a href="https://ufoships.com">Ufo</a></li>
13
+ <li><a href="https://lono.cloud">Lono</a></li>
14
+ <li><a href="https://jack-eb.com">Jack</a></li>
13
15
  </ul>
14
16
  </div>
15
17
  <div class="footer-col col-md-4">
@@ -16,10 +16,10 @@ Runs command across fleet of servers via AWS Run Command.
16
16
 
17
17
  ## Examples Summary
18
18
 
19
- $ sonic execute hi-web-prod uptime
20
- $ sonic execute hi-web-prod,hi-worker-prod,hi-clock-prod uptime
21
- $ sonic execute i-030033c20c54bf149,i-030033c20c54bf150 uname -a
22
- $ sonic execute i-030033c20c54bf149 file://hello.sh
19
+ sonic execute --tags Name=demo-web uptime
20
+ sonic execute --tags Name=demo-web,demo-worker uptime # multiple values
21
+ sonic execute --instance-ids i-030033c20c54bf149,i-030033c20c54bf150 uname -a
22
+ sonic execute --instance-ids i-030033c20c54bf149 file://hello.sh # script from file
23
23
 
24
24
  You cannot mix instance ids and tag names in the filter.
25
25
 
@@ -27,13 +27,13 @@ You cannot mix instance ids and tag names in the filter.
27
27
 
28
28
  Here's a command example output in detailed:
29
29
 
30
- $ sonic execute i-0bf51a000ab4e73a8 uptime
30
+ $ sonic execute --instance-ids i-0bf51a000ab4e73a8 uptime
31
31
  Sending command to SSM with options:
32
32
  ---
33
33
  instance_ids:
34
34
  - i-0bf51a000ab4e73a8
35
35
  document_name: AWS-RunShellScript
36
- comment: sonic execute i-0bf51a000ab4e73a8 uptime
36
+ comment: sonic execute --instance-ids i-0bf51a000ab4e73a8 uptime
37
37
  parameters:
38
38
  commands:
39
39
  - uptime
@@ -77,6 +77,8 @@ The AWS SSM console looks like this:
77
77
  ```
78
78
  [--zero-warn], [--no-zero-warn] # Warns user when no instances found
79
79
  # Default: true
80
+ [--instance-ids=INSTANCE_IDS] # Instance ids to execute command on. Format: --instance-ids "i-111,i-222"
81
+ [--tags=TAGS] # Tags used to determine what instances to execute command on. Format: --tags "Key1=v1,v2;Key2=v3"
80
82
  [--verbose], [--no-verbose]
81
83
  [--noop], [--no-noop]
82
84
  ```
data/docs/bin/web CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/bin/bash -ex
2
2
 
3
3
  bundle exec jekyll clean
4
- exec bundle exec jekyll serve
4
+ exec bundle exec jekyll serve --host 0.0.0.0 "$@"
data/docs/quick-start.md CHANGED
@@ -6,35 +6,31 @@ In a hurry? No sweat! Here's a quick overview of how to use sonic.
6
6
 
7
7
  ### Install
8
8
 
9
- ```sh
10
- gem install sonic-screwdriver
11
- ```
9
+ gem install sonic-screwdriver
12
10
 
13
11
  ### Usage
14
12
 
15
- ```sh
16
- # ssh into an instance
17
- sonic ssh i-0f7f833131a51ce35
18
- sonic ssh hi-web # ec2 tag
19
- sonic ssh hi-web --cluster staging # ecs service name
20
- sonic ssh 7fbc8c75-4675-4d39-a5a4-0395ff8cd474 --cluster staging # ECS container id
21
- sonic ssh 1ed12abd-645c-4a05-9acf-739b9d790170 --cluster staging # ECS task id
13
+ # ssh into an instance
14
+ sonic ssh i-0f7f833131a51ce35
15
+ sonic ssh demo-web # ec2 tag
16
+ sonic ssh demo-web --cluster staging # ecs service name
17
+ sonic ssh 7fbc8c75-4675-4d39-a5a4-0395ff8cd474 --cluster staging # ECS container id
18
+ sonic ssh 1ed12abd-645c-4a05-9acf-739b9d790170 --cluster staging # ECS task id
22
19
 
23
- # docker exec to a running ECS docker container
24
- sonic ecs exec hi-web
20
+ # docker exec to a running ECS docker container
21
+ sonic ecs exec demo-web
25
22
 
26
- # docker run with same environment as the ECS docker running containers
27
- sonic ecs sh hi-web
23
+ # docker run with same environment as the ECS docker running containers
24
+ sonic ecs sh demo-web
28
25
 
29
- # run command on 1 instance
30
- sonic execute i-0f7f833131a51ce35 uptime
26
+ # run command on 1 instance
27
+ sonic execute --instance-ids i-0f7f833131a51ce35 uptime
31
28
 
32
- # run command on all instances tagged with hi-web and worker
33
- sonic execute hi-web,hi-worker uptime
29
+ # run command on all instances tagged with demo-web and worker
30
+ sonic execute --tags Name=demo-web,demo-worker uptime
34
31
 
35
- # list ec2 instances
36
- sonic list hi-web
37
- ```
32
+ # list ec2 instances
33
+ sonic list demo-web
38
34
 
39
35
  Congratulations! You now know the basic sonic screwdriver commands now.
40
36
 
data/lib/sonic.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  $:.unshift(File.expand_path("../", __FILE__))
2
+ require "rainbow/ext/string"
2
3
  require "sonic/version"
3
- require "colorize"
4
4
 
5
5
  module Sonic
6
6
  autoload :Core, 'sonic/core'
data/lib/sonic/checks.rb CHANGED
@@ -3,7 +3,7 @@ module Sonic
3
3
  def check_cluster_exists!
4
4
  cluster = ecs.describe_clusters(clusters: [@cluster]).clusters.first
5
5
  unless cluster
6
- UI.error "The #{@cluster.green} cluster does not exist. Are you sure you specified the right cluster?"
6
+ UI.error "The #{@cluster.color(:green)} cluster does not exist. Are you sure you specified the right cluster?"
7
7
  exit 1
8
8
  end
9
9
  end
@@ -20,7 +20,7 @@ module Sonic
20
20
 
21
21
  service = resp.services.first
22
22
  unless service
23
- UI.error "The #{@service.green} service does not exist in #{@cluster.green} cluster. Are you sure you specified the right service and cluster?"
23
+ UI.error "The #{@service.color(:green)} service does not exist in #{@cluster.color(:green)} cluster. Are you sure you specified the right service and cluster?"
24
24
  exit 1
25
25
  end
26
26
  end
data/lib/sonic/cli.rb CHANGED
@@ -27,8 +27,10 @@ module Sonic
27
27
  long_desc Help.text("execute")
28
28
  option :zero_warn, type: :boolean, default: true, desc: "Warns user when no instances found"
29
29
  # filter - Filter ec2 instances by tag name or instance_ids separated by commas
30
- def execute(filter, *command)
31
- Execute.new(command, options.merge(filter: filter)).execute
30
+ option :instance_ids, desc: %Q|Instance ids to execute command on. Format: --instance-ids "i-111,i-222"|
31
+ option :tags, desc: %Q|Tags used to determine what instances to execute command on. Format: --tags "Key1=v1,v2;Key2=v3"|
32
+ def execute(*command)
33
+ Execute.new(command, options).execute
32
34
  end
33
35
 
34
36
  desc "list [FILTER]", "Lists ec2 instances."
data/lib/sonic/docker.rb CHANGED
@@ -30,7 +30,7 @@ module Sonic
30
30
 
31
31
  # command is an Array
32
32
  def execute(*command)
33
- UI.say "=> #{command.join(' ')}".colorize(:green)
33
+ UI.say "=> #{command.join(' ')}".color(:green)
34
34
  success = system(*command)
35
35
  unless success
36
36
  UI.error(command.join(' '))
@@ -59,7 +59,7 @@ module Sonic
59
59
 
60
60
  ssh = ["ssh", ssh_options, "-At", host, "uptime", "2>&1"]
61
61
  command = ssh.join(' ')
62
- puts "=> #{command}".colorize(:green)
62
+ puts "=> #{command}".color(:green)
63
63
  output = `#{command}`
64
64
  if output.include?("Permission denied")
65
65
  puts output
data/lib/sonic/execute.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'colorize'
2
1
  require 'yaml'
3
2
  require 'active_support/core_ext/hash'
4
3
 
@@ -9,7 +8,8 @@ module Sonic
9
8
  def initialize(command, options)
10
9
  @command = command
11
10
  @options = options
12
- @filter = @options[:filter].split(',').map{|s| s.strip}
11
+ @tags = @options[:tags]
12
+ @instance_ids = @options[:instance_ids]
13
13
  end
14
14
 
15
15
  # aws ssm send-command \
@@ -19,6 +19,7 @@ module Sonic
19
19
  # --parameters '{"commands":["#!/usr/bin/python","print \"Hello world from python\""]}' \
20
20
  # --query "Command.CommandId"
21
21
  def execute
22
+ check_filter_options!
22
23
  ssm_options = build_ssm_options
23
24
  if @options[:noop]
24
25
  UI.noop = true
@@ -34,6 +35,7 @@ module Sonic
34
35
  puts
35
36
  begin
36
37
  resp = send_command(ssm_options)
38
+
37
39
  command_id = resp.command.command_id
38
40
  success = true
39
41
  rescue Aws::SSM::Errors::InvalidInstanceId => e
@@ -50,9 +52,31 @@ module Sonic
50
52
  display_ssm_commands(command_id, ssm_options)
51
53
  puts
52
54
  return if @options[:noop]
53
- wait(command_id)
54
- display_ssm_output(command_id, ssm_options)
55
+ status = wait(command_id)
56
+ display_ssm_output(command_id)
55
57
  display_console_url(command_id)
58
+
59
+ if status == "Success"
60
+ puts "Command successful: #{status}".color(:green)
61
+ exit_status(0)
62
+ else
63
+ puts "Command unsuccessful: #{status}".color(:red)
64
+ exit_status(1)
65
+ end
66
+ end
67
+
68
+ def exit_status(code)
69
+ exit(code) if cli?
70
+
71
+ if code == 0
72
+ true
73
+ else
74
+ raise "Error running command"
75
+ end
76
+ end
77
+
78
+ def cli?
79
+ $0.include?('sonic')
56
80
  end
57
81
 
58
82
  def wait(command_id)
@@ -69,15 +93,21 @@ module Sonic
69
93
  end
70
94
  puts "\nCommand finished."
71
95
  puts
96
+ status
72
97
  end
73
98
 
74
- def display_ssm_output(command_id, ssm_options)
75
- instance_ids = ssm_options[:instance_ids]
76
- return unless instance_ids && instance_ids.size > 0
99
+ def display_ssm_output(command_id)
100
+ resp = ssm.list_command_invocations(command_id: command_id)
101
+ command_invocations = resp.command_invocations
102
+ command_invocation = command_invocations.first
103
+ unless command_invocation
104
+ puts "WARN: No instances found that matches the --tags or --instance-ids option".color(:yellow)
105
+ return false # instances_found
106
+ end
107
+ instance_id = command_invocation.instance_id
77
108
 
78
- instance_id = instance_ids.first
79
- if ssm_options[:instance_ids].size > 1
80
- puts "Multiple instance targets. Only displaying output for #{instance_id}."
109
+ if command_invocations.size > 1
110
+ puts "Multiple instance targets. Total targets: #{command_invocations.size}. Only displaying output for #{instance_id}."
81
111
  else
82
112
  puts "Displaying output for #{instance_id}."
83
113
  end
@@ -89,6 +119,7 @@ module Sonic
89
119
  ssm_output(resp, "output")
90
120
  ssm_output(resp, "error")
91
121
  puts
122
+ true # instances_found
92
123
  end
93
124
 
94
125
  def display_console_url(command_id)
@@ -97,16 +128,15 @@ module Sonic
97
128
  puts "To see the more output details visit:"
98
129
  puts " #{console_url}"
99
130
  puts
100
- copy_paste_clipboard(console_url)
101
- UI.say "Pro tip: the console url is already in your copy/paste clipboard."
131
+ copy_paste_clipboard(console_url, "Pro tip: the console url is already in your copy/paste clipboard.")
102
132
  end
103
133
 
104
134
  def colorized_status(status)
105
135
  case status
106
136
  when "Success"
107
- status.colorize(:green)
137
+ status.color(:green)
108
138
  when "Failed"
109
- status.colorize(:red)
139
+ status.color(:red)
110
140
  else
111
141
  status
112
142
  end
@@ -121,7 +151,7 @@ module Sonic
121
151
  return if content.empty?
122
152
 
123
153
  puts "Command standard #{type}:"
124
- # "https://s3.amazonaws.com/lr-infrastructure-prod/ssm/commands/sonic/0a4f4bef-8f63-4235-8b30-ae296477261a/i-0b2e6e187a3f9ada9/awsrunPowerShellScript/0.awsrunPowerShellScript/stderr">
154
+ # "https://s3.amazonaws.com/infra-prod/ssm/commands/sonic/0a4f4bef-8f63-4235-8b30-ae296477261a/i-0b2e6e187a3f9ada9/awsrunPowerShellScript/0.awsrunPowerShellScript/stderr">
125
155
  if content.include?("--output truncated--") && !resp[s3_key].empty?
126
156
  s3_url = resp[s3_key]
127
157
  info = s3_url.sub('https://s3.amazonaws.com/', '').split('/')
@@ -147,7 +177,6 @@ module Sonic
147
177
 
148
178
  begin
149
179
  resp = ssm.send_command(options)
150
- # puts "NOOP FOR NOW"
151
180
  rescue Aws::SSM::Errors::UnsupportedPlatformType
152
181
  retries += 1
153
182
  # toggle AWS-RunShellScript / AWS-RunPowerShellScript
@@ -166,12 +195,18 @@ module Sonic
166
195
  end
167
196
 
168
197
  def build_ssm_options
169
- criteria = transform_filter(@filter)
198
+ criteria = transform_filter_option
170
199
  command = build_command(@command)
171
200
  options = criteria.merge(
172
201
  document_name: "AWS-RunShellScript", # default
173
202
  comment: "sonic #{ARGV.join(' ')}"[0..99], # comment has a max of 100 chars
174
- parameters: { "commands" => command }
203
+ parameters: { "commands" => command },
204
+ # Default CloudWatchLog settings. Can be overwritten with settings.yml send_command
205
+ # IMPORTANT: make sure the EC2 instance the command runs on has access to write to CloudWatch Logs.
206
+ cloud_watch_output_config: {
207
+ # cloud_watch_log_group_name: "ssm", # Defaults to /aws/ssm/AWS-RunShellScript (aws/ssm/SystemsManagerDocumentName https://amzn.to/38TKVse)
208
+ cloud_watch_output_enabled: true,
209
+ },
175
210
  )
176
211
  settings_options = settings["send_command"] || {}
177
212
  options.merge(settings_options.deep_symbolize_keys)
@@ -181,6 +216,12 @@ module Sonic
181
216
  @settings ||= Setting.new.data
182
217
  end
183
218
 
219
+ def check_filter_options!
220
+ return if @tags || @instance_ids
221
+ puts "ERROR: Please provide --tags or --instance-ids option".color(:red)
222
+ exit 1
223
+ end
224
+
184
225
  #
185
226
  # Public: Transform the filter to the ssm send_command equivalent options
186
227
  #
@@ -188,41 +229,31 @@ module Sonic
188
229
  #
189
230
  # Examples
190
231
  #
191
- # transform_filter(["hi-web-prod", "hi-worker-prod", "i-006a097bb10643e20"])
232
+ # transform_filter_option
192
233
  # # => {
193
234
  # instance_ids: ["i-006a097bb10643e20"],
194
235
  # targets: [{key: "Name", values: "hi-web-prod,hi-worker-prod"}]
195
236
  # }
196
237
  #
197
238
  # Returns the duplicated String.
198
- def transform_filter(filter)
199
- valid = validate_filter(filter)
200
- unless valid
201
- UI.error("The filter you provided '#{filter.join(',')}' is not valid.")
202
- UI.say("The filter must either be all instance ids or just a list of tag names.")
203
- exit 1
204
- end
205
-
206
- if filter.detect { |i| instance_id?(i) }
207
- instance_ids = filter
208
- {instance_ids: instance_ids}
209
- else
210
- tags = filter
211
- targets = [{
212
- key: "tag:#{tag_name}",
213
- values: tags
214
- }]
239
+ def transform_filter_option
240
+ if @tags
241
+ list = @tags.split(';')
242
+ targets = list.inject([]) do |final,item|
243
+ tag_name,value_list = item.split('=')
244
+ values = value_list.split(',').map(&:strip)
245
+ # structure expected by ssm send_command
246
+ option = {
247
+ key: "tag:#{tag_name}",
248
+ values: values
249
+ }
250
+ final << option
251
+ final
252
+ end
215
253
  {targets: targets}
216
- end
217
- end
218
-
219
- # Either all instance ids are no instance ids is a valid filter
220
- def validate_filter(filter)
221
- if filter.detect { |i| instance_id?(i) }
222
- instance_ids = filter.select { |i| instance_id?(i) }
223
- instance_ids.size == filter.size
224
- else
225
- true
254
+ else # @instance_ids
255
+ instance_ids = @instance_ids.split(',')
256
+ {instance_ids: instance_ids}
226
257
  end
227
258
  end
228
259
 
@@ -239,7 +270,7 @@ module Sonic
239
270
  # The script is being feed inline so just join the command together into one script.
240
271
  # Still keep in an array form because that's how ssn.send_command works with AWS-RunShellScript
241
272
  # usually reads the command.
242
- [command.join(" ")]
273
+ command.is_a?(Array) ? command : [command]
243
274
  end
244
275
  end
245
276
 
@@ -254,8 +285,7 @@ You can use the following command to check registered instances to SSM.
254
285
  #{ssm_describe_command}
255
286
  EOS
256
287
  UI.warn(message)
257
- copy_paste_clipboard(ssm_describe_command)
258
- UI.say "Pro tip: ssm describe-instance-information already in your copy/paste clipboard."
288
+ copy_paste_clipboard(ssm_describe_command, "Pro tip: ssm describe-instance-information already in your copy/paste clipboard.")
259
289
  end
260
290
 
261
291
  def file_path?(command)
@@ -312,9 +342,10 @@ EOL
312
342
  end
313
343
  end
314
344
 
315
- def copy_paste_clipboard(command)
345
+ def copy_paste_clipboard(command, text)
316
346
  return unless RUBY_PLATFORM =~ /darwin/
317
347
  system("echo '#{command}' | pbcopy")
348
+ UI.say text
318
349
  end
319
350
  end
320
351
  end
@@ -3,10 +3,10 @@
3
3
 
4
4
  ## Examples Summary
5
5
 
6
- $ sonic execute hi-web-prod uptime
7
- $ sonic execute hi-web-prod,hi-worker-prod,hi-clock-prod uptime
8
- $ sonic execute i-030033c20c54bf149,i-030033c20c54bf150 uname -a
9
- $ sonic execute i-030033c20c54bf149 file://hello.sh
6
+ sonic execute --tags Name=demo-web uptime
7
+ sonic execute --tags Name=demo-web,demo-worker uptime # multiple values
8
+ sonic execute --instance-ids i-030033c20c54bf149,i-030033c20c54bf150 uname -a
9
+ sonic execute --instance-ids i-030033c20c54bf149 file://hello.sh # script from file
10
10
 
11
11
  You cannot mix instance ids and tag names in the filter.
12
12
 
@@ -14,13 +14,13 @@ You cannot mix instance ids and tag names in the filter.
14
14
 
15
15
  Here's a command example output in detailed:
16
16
 
17
- $ sonic execute i-0bf51a000ab4e73a8 uptime
17
+ $ sonic execute --instance-ids i-0bf51a000ab4e73a8 uptime
18
18
  Sending command to SSM with options:
19
19
  ---
20
20
  instance_ids:
21
21
  - i-0bf51a000ab4e73a8
22
22
  document_name: AWS-RunShellScript
23
- comment: sonic execute i-0bf51a000ab4e73a8 uptime
23
+ comment: sonic execute --instance-ids i-0bf51a000ab4e73a8 uptime
24
24
  parameters:
25
25
  commands:
26
26
  - uptime
data/lib/sonic/list.rb CHANGED
@@ -35,7 +35,7 @@ module Sonic
35
35
 
36
36
  if @options[:header] && !zero_instances
37
37
  header = ["Instance Id", "Name", "Public IP", "Private IP", "Type"]
38
- UI.say header.join("\t").colorize(:green)
38
+ UI.say header.join("\t").color(:green)
39
39
  end
40
40
 
41
41
  instances.each do |i|
data/lib/sonic/ssh.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'colorize'
2
-
3
1
  module Sonic
4
2
  class Ssh
5
3
  autoload :IdentifierDetector, 'sonic/ssh/identifier_detector'
@@ -82,7 +80,7 @@ module Sonic
82
80
  def kernel_exec(*args)
83
81
  # append the optional command that can be provided to the ssh command
84
82
  full_command = args + @options[:command]
85
- puts "=> #{full_command.join(' ')}".colorize(:green)
83
+ puts "=> #{full_command.join(' ')}".color(:green)
86
84
  # https://ruby-doc.org/core-2.3.1/Kernel.html#method-i-exec
87
85
  # Using 2nd form
88
86
  Kernel.exec(*full_command) unless @options[:noop]
@@ -73,7 +73,7 @@ class Ssh
73
73
 
74
74
  task = response.tasks.first
75
75
  unless task
76
- puts "Unable to find a #{task_arn.green} container instance or task in the #{@cluster.green} cluster."
76
+ puts "Unable to find a #{task_arn.color(:green)} container instance or task in the #{@cluster.color(:green)} cluster."
77
77
  exit 1
78
78
  end
79
79
 
data/lib/sonic/ui.rb CHANGED
@@ -19,10 +19,10 @@ module Sonic
19
19
  puts msg unless mute
20
20
  end
21
21
  def error(msg='')
22
- say "ERROR: #{msg}".colorize(:red)
22
+ say "ERROR: #{msg}".color(:red)
23
23
  end
24
24
  def warn(msg='')
25
- say "WARN: #{msg}".colorize(:yellow)
25
+ say "WARN: #{msg}".color(:yellow)
26
26
  end
27
27
  end
28
28
  end
data/lib/sonic/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sonic
2
- VERSION = "2.1.0"
2
+ VERSION = "2.2.3"
3
3
  end
data/sonic.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.homepage = "http://sonic-screwdriver.cloud/"
13
13
  spec.license = "MIT"
14
14
 
15
- spec.files = `git ls-files`.split($/)
15
+ spec.files = File.directory?('.git') ? `git ls-files`.split($/) : Dir.glob("**/*")
16
16
  spec.bindir = "exe"
17
17
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
@@ -23,9 +23,9 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency "aws-sdk-ecs"
24
24
  spec.add_dependency "aws-sdk-s3"
25
25
  spec.add_dependency "aws-sdk-ssm"
26
- spec.add_dependency "colorize"
27
26
  spec.add_dependency "hashie"
28
27
  spec.add_dependency "memoist"
28
+ spec.add_dependency "rainbow"
29
29
  spec.add_dependency "thor"
30
30
  spec.add_dependency "tty-prompt"
31
31
 
data/spec/lib/cli_spec.rb CHANGED
@@ -11,8 +11,13 @@ describe Sonic::CLI do
11
11
  expect(out).to include("=> ssh")
12
12
  end
13
13
 
14
- it "execute should print that command has been sent" do
15
- out = execute("exe/sonic execute #{@args} 1,2,3 uptime")
14
+ it "execute should print that command has been sent --instance-ids" do
15
+ out = execute("exe/sonic execute #{@args} --instance-ids i-1,i-2,i-3 uptime")
16
+ expect(out).to include("Command sent")
17
+ end
18
+
19
+ it "execute should print that command has been sent --tags" do
20
+ out = execute("exe/sonic execute #{@args} --tags Name=value uptime")
16
21
  expect(out).to include("Command sent")
17
22
  end
18
23
 
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Sonic::Execute do
4
4
  before(:each) do
5
5
  @options = {
6
- filter: "i-066b140d9479e9681,i-09482b1a6e330fbf7"
6
+ instance_ids: "i-066b140d9479e9681,i-09482b1a6e330fbf7"
7
7
  }
8
8
  end
9
9
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sonic-screwdriver
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-01 00:00:00.000000000 Z
11
+ date: 2021-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: colorize
84
+ name: hashie
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: hashie
98
+ name: memoist
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -109,7 +109,7 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: memoist
112
+ name: rainbow
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - ">="
@@ -260,11 +260,9 @@ files:
260
260
  - ".circleci/config.yml"
261
261
  - ".gitignore"
262
262
  - ".rspec"
263
- - ".ruby-version"
264
263
  - CHANGELOG.md
265
264
  - CONTRIBUTING.md
266
265
  - Gemfile
267
- - Gemfile.lock
268
266
  - Guardfile
269
267
  - LICENSE.txt
270
268
  - README.md
@@ -421,8 +419,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
421
419
  - !ruby/object:Gem::Version
422
420
  version: '0'
423
421
  requirements: []
424
- rubyforge_project:
425
- rubygems_version: 2.7.6
422
+ rubygems_version: 3.2.5
426
423
  signing_key:
427
424
  specification_version: 4
428
425
  summary: Multi-functional tool to manage AWS infrastructure
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 2.5.1
data/Gemfile.lock DELETED
@@ -1,163 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- sonic-screwdriver (2.0.0)
5
- activesupport
6
- aws-sdk-ec2
7
- aws-sdk-ecs
8
- aws-sdk-s3
9
- aws-sdk-ssm
10
- colorize
11
- hashie
12
- memoist
13
- thor
14
- tty-prompt
15
-
16
- GEM
17
- remote: https://rubygems.org/
18
- specs:
19
- activesupport (5.2.0)
20
- concurrent-ruby (~> 1.0, >= 1.0.2)
21
- i18n (>= 0.7, < 2)
22
- minitest (~> 5.1)
23
- tzinfo (~> 1.1)
24
- aws-eventstream (1.0.0)
25
- aws-partitions (1.89.1)
26
- aws-sdk-core (3.21.2)
27
- aws-eventstream (~> 1.0)
28
- aws-partitions (~> 1.0)
29
- aws-sigv4 (~> 1.0)
30
- jmespath (~> 1.0)
31
- aws-sdk-ec2 (1.34.0)
32
- aws-sdk-core (~> 3)
33
- aws-sigv4 (~> 1.0)
34
- aws-sdk-ecs (1.13.0)
35
- aws-sdk-core (~> 3)
36
- aws-sigv4 (~> 1.0)
37
- aws-sdk-kms (1.5.0)
38
- aws-sdk-core (~> 3)
39
- aws-sigv4 (~> 1.0)
40
- aws-sdk-s3 (1.13.0)
41
- aws-sdk-core (~> 3, >= 3.21.2)
42
- aws-sdk-kms (~> 1)
43
- aws-sigv4 (~> 1.0)
44
- aws-sdk-ssm (1.13.0)
45
- aws-sdk-core (~> 3)
46
- aws-sigv4 (~> 1.0)
47
- aws-sigv4 (1.0.2)
48
- byebug (10.0.2)
49
- cli_markdown (0.1.0)
50
- codeclimate-test-reporter (1.0.8)
51
- simplecov (<= 0.13)
52
- coderay (1.1.2)
53
- colorize (0.8.1)
54
- concurrent-ruby (1.0.5)
55
- diff-lcs (1.3)
56
- docile (1.1.5)
57
- equatable (0.5.0)
58
- ffi (1.9.23)
59
- formatador (0.2.5)
60
- guard (2.14.2)
61
- formatador (>= 0.2.4)
62
- listen (>= 2.7, < 4.0)
63
- lumberjack (>= 1.0.12, < 2.0)
64
- nenv (~> 0.1)
65
- notiffany (~> 0.0)
66
- pry (>= 0.9.12)
67
- shellany (~> 0.0)
68
- thor (>= 0.18.1)
69
- guard-bundler (2.1.0)
70
- bundler (~> 1.0)
71
- guard (~> 2.2)
72
- guard-compat (~> 1.1)
73
- guard-compat (1.2.1)
74
- guard-rspec (4.7.3)
75
- guard (~> 2.1)
76
- guard-compat (~> 1.1)
77
- rspec (>= 2.99.0, < 4.0)
78
- hashie (3.5.7)
79
- hitimes (1.2.6)
80
- i18n (1.0.1)
81
- concurrent-ruby (~> 1.0)
82
- jmespath (1.4.0)
83
- json (2.1.0)
84
- listen (3.1.5)
85
- rb-fsevent (~> 0.9, >= 0.9.4)
86
- rb-inotify (~> 0.9, >= 0.9.7)
87
- ruby_dep (~> 1.2)
88
- lumberjack (1.0.13)
89
- memoist (0.16.0)
90
- method_source (0.9.0)
91
- minitest (5.11.3)
92
- necromancer (0.4.0)
93
- nenv (0.3.0)
94
- notiffany (0.1.1)
95
- nenv (~> 0.1)
96
- shellany (~> 0.0)
97
- pastel (0.7.2)
98
- equatable (~> 0.5.0)
99
- tty-color (~> 0.4.0)
100
- pry (0.11.3)
101
- coderay (~> 1.1.0)
102
- method_source (~> 0.9.0)
103
- rake (12.3.1)
104
- rb-fsevent (0.10.3)
105
- rb-inotify (0.9.10)
106
- ffi (>= 0.5.0, < 2)
107
- rspec (3.7.0)
108
- rspec-core (~> 3.7.0)
109
- rspec-expectations (~> 3.7.0)
110
- rspec-mocks (~> 3.7.0)
111
- rspec-core (3.7.1)
112
- rspec-support (~> 3.7.0)
113
- rspec-expectations (3.7.0)
114
- diff-lcs (>= 1.2.0, < 2.0)
115
- rspec-support (~> 3.7.0)
116
- rspec-mocks (3.7.0)
117
- diff-lcs (>= 1.2.0, < 2.0)
118
- rspec-support (~> 3.7.0)
119
- rspec-support (3.7.1)
120
- ruby_dep (1.5.0)
121
- shellany (0.0.1)
122
- simplecov (0.13.0)
123
- docile (~> 1.1.0)
124
- json (>= 1.8, < 3)
125
- simplecov-html (~> 0.10.0)
126
- simplecov-html (0.10.2)
127
- thor (0.20.0)
128
- thread_safe (0.3.6)
129
- timers (4.1.2)
130
- hitimes
131
- tty-color (0.4.2)
132
- tty-cursor (0.5.0)
133
- tty-prompt (0.16.1)
134
- necromancer (~> 0.4.0)
135
- pastel (~> 0.7.0)
136
- timers (~> 4.0)
137
- tty-cursor (~> 0.5.0)
138
- tty-reader (~> 0.3.0)
139
- tty-reader (0.3.0)
140
- tty-cursor (~> 0.5.0)
141
- tty-screen (~> 0.6.4)
142
- wisper (~> 2.0.0)
143
- tty-screen (0.6.4)
144
- tzinfo (1.2.5)
145
- thread_safe (~> 0.1)
146
- wisper (2.0.0)
147
-
148
- PLATFORMS
149
- ruby
150
-
151
- DEPENDENCIES
152
- bundler
153
- byebug
154
- cli_markdown
155
- codeclimate-test-reporter
156
- guard
157
- guard-bundler
158
- guard-rspec
159
- rake
160
- sonic-screwdriver!
161
-
162
- BUNDLED WITH
163
- 1.16.1