sonic-screwdriver 2.1.1 → 2.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '04708ff866e88a9752050a4928b3109948086ee0fe24594fffbc6ee04de03b8a'
4
- data.tar.gz: 4f09a1cce6b42c121205b002da04dbe9d56292514ae597ed5ba2921e38ecba86
3
+ metadata.gz: 7012e35108a2515bf2ad5abe18cbe39502a4dc58e64732199334414cfb7b0808
4
+ data.tar.gz: 9cb1113b9bb23ce2605b01594d54d477e3f10f6322f0d97c8ebbd8a6fae5aa0b
5
5
  SHA512:
6
- metadata.gz: 33433f9fa8025cff559255beb2ec9f107ca7dc1a11643fd3d145f5cc96d2dcc1c7dadbef74d3c4ca689590f3300d200f6c480e75b48dab271c046f751aaa2d19
7
- data.tar.gz: 1d58617e51a1383af495d763270a79fddaa25f2c28fceb97940bdff5fae3f22cfe94e0eac6cf2ec6cbc25c3af3d0f9a5e16dd5738b91a5d28700000569098515
6
+ metadata.gz: 99ccd14a805e3bb635bd41c65565d35a6afed559ecf0bd781b36ddc61bfd05e8c3dff926018b2605385647fb55c3eb0e1bc322bec609a56c0e274143c2bc5bb1
7
+ data.tar.gz: c27388fc985c3ac35e02189ccdd748b28fe3f3d1399aa36cc2f601b6fe5fa54cf9634f9984230d9067c3d8060c7c34a052782abf8e889a6695e1a9391b753e13
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.4] - 2021-04-13
7
+ - [#13](https://github.com/boltops-tools/sonic/pull/13) execute --comment option
8
+
9
+ ## [2.2.3] - 2021-04-12
10
+ - [#12](https://github.com/boltops-tools/sonic/pull/12) fix cli check
11
+
12
+ ## [2.2.2] - 2021-04-12
13
+ - [#11](https://github.com/boltops-tools/sonic/pull/11) cli check
14
+
15
+ ## [2.2.1] - 2021-04-12
16
+ - [#9](https://github.com/boltops-tools/sonic/pull/9) improve command array handling
17
+
18
+ ## [2.2.0]
19
+ - #7 sonic execute command: `--tags` and `--instance-id` options instead of polymorphic list. Breaking behavior.
20
+ - display output even if tags used
21
+ - configure default log group
22
+ - correct exit status
5
23
 
6
24
  ## [2.1.1]
7
25
  - use rainbow gem for terminal colors
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,11 +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://rubyonjets.com">Jets</a></li>
10
- <li><a href="http://ufoships.com">Ufo</a></li>
11
- <li><a href="http://lono.cloud">Lono</a></li>
12
- <li><a href="http://jack-eb.com">Jack</a></li>
13
- <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>
14
15
  </ul>
15
16
  </div>
16
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/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,11 @@ 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
+ option :comment, desc: "comment. defaults to the sonic command used"
33
+ def execute(*command)
34
+ Execute.new(command, options).execute
32
35
  end
33
36
 
34
37
  desc "list [FILTER]", "Lists ec2 instances."
data/lib/sonic/execute.rb CHANGED
@@ -8,7 +8,8 @@ module Sonic
8
8
  def initialize(command, options)
9
9
  @command = command
10
10
  @options = options
11
- @filter = @options[:filter].split(',').map{|s| s.strip}
11
+ @tags = @options[:tags]
12
+ @instance_ids = @options[:instance_ids]
12
13
  end
13
14
 
14
15
  # aws ssm send-command \
@@ -18,6 +19,7 @@ module Sonic
18
19
  # --parameters '{"commands":["#!/usr/bin/python","print \"Hello world from python\""]}' \
19
20
  # --query "Command.CommandId"
20
21
  def execute
22
+ check_filter_options!
21
23
  ssm_options = build_ssm_options
22
24
  if @options[:noop]
23
25
  UI.noop = true
@@ -33,6 +35,7 @@ module Sonic
33
35
  puts
34
36
  begin
35
37
  resp = send_command(ssm_options)
38
+
36
39
  command_id = resp.command.command_id
37
40
  success = true
38
41
  rescue Aws::SSM::Errors::InvalidInstanceId => e
@@ -49,9 +52,31 @@ module Sonic
49
52
  display_ssm_commands(command_id, ssm_options)
50
53
  puts
51
54
  return if @options[:noop]
52
- wait(command_id)
53
- display_ssm_output(command_id, ssm_options)
55
+ status = wait(command_id)
56
+ display_ssm_output(command_id)
54
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')
55
80
  end
56
81
 
57
82
  def wait(command_id)
@@ -68,15 +93,21 @@ module Sonic
68
93
  end
69
94
  puts "\nCommand finished."
70
95
  puts
96
+ status
71
97
  end
72
98
 
73
- def display_ssm_output(command_id, ssm_options)
74
- instance_ids = ssm_options[:instance_ids]
75
- 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
76
108
 
77
- instance_id = instance_ids.first
78
- if ssm_options[:instance_ids].size > 1
79
- 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}."
80
111
  else
81
112
  puts "Displaying output for #{instance_id}."
82
113
  end
@@ -88,6 +119,7 @@ module Sonic
88
119
  ssm_output(resp, "output")
89
120
  ssm_output(resp, "error")
90
121
  puts
122
+ true # instances_found
91
123
  end
92
124
 
93
125
  def display_console_url(command_id)
@@ -96,8 +128,7 @@ module Sonic
96
128
  puts "To see the more output details visit:"
97
129
  puts " #{console_url}"
98
130
  puts
99
- copy_paste_clipboard(console_url)
100
- 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.")
101
132
  end
102
133
 
103
134
  def colorized_status(status)
@@ -120,7 +151,7 @@ module Sonic
120
151
  return if content.empty?
121
152
 
122
153
  puts "Command standard #{type}:"
123
- # "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">
124
155
  if content.include?("--output truncated--") && !resp[s3_key].empty?
125
156
  s3_url = resp[s3_key]
126
157
  info = s3_url.sub('https://s3.amazonaws.com/', '').split('/')
@@ -146,7 +177,6 @@ module Sonic
146
177
 
147
178
  begin
148
179
  resp = ssm.send_command(options)
149
- # puts "NOOP FOR NOW"
150
180
  rescue Aws::SSM::Errors::UnsupportedPlatformType
151
181
  retries += 1
152
182
  # toggle AWS-RunShellScript / AWS-RunPowerShellScript
@@ -165,12 +195,20 @@ module Sonic
165
195
  end
166
196
 
167
197
  def build_ssm_options
168
- criteria = transform_filter(@filter)
198
+ criteria = transform_filter_option
169
199
  command = build_command(@command)
200
+ comment = @options[:comment] || "sonic #{ARGV.join(' ')}"
201
+ comment = comment[0..99] # comment has a max of 100 chars
170
202
  options = criteria.merge(
171
203
  document_name: "AWS-RunShellScript", # default
172
- comment: "sonic #{ARGV.join(' ')}"[0..99], # comment has a max of 100 chars
173
- parameters: { "commands" => command }
204
+ comment: comment,
205
+ parameters: { "commands" => command },
206
+ # Default CloudWatchLog settings. Can be overwritten with settings.yml send_command
207
+ # IMPORTANT: make sure the EC2 instance the command runs on has access to write to CloudWatch Logs.
208
+ cloud_watch_output_config: {
209
+ # cloud_watch_log_group_name: "ssm", # Defaults to /aws/ssm/AWS-RunShellScript (aws/ssm/SystemsManagerDocumentName https://amzn.to/38TKVse)
210
+ cloud_watch_output_enabled: true,
211
+ },
174
212
  )
175
213
  settings_options = settings["send_command"] || {}
176
214
  options.merge(settings_options.deep_symbolize_keys)
@@ -180,6 +218,12 @@ module Sonic
180
218
  @settings ||= Setting.new.data
181
219
  end
182
220
 
221
+ def check_filter_options!
222
+ return if @tags || @instance_ids
223
+ puts "ERROR: Please provide --tags or --instance-ids option".color(:red)
224
+ exit 1
225
+ end
226
+
183
227
  #
184
228
  # Public: Transform the filter to the ssm send_command equivalent options
185
229
  #
@@ -187,41 +231,31 @@ module Sonic
187
231
  #
188
232
  # Examples
189
233
  #
190
- # transform_filter(["hi-web-prod", "hi-worker-prod", "i-006a097bb10643e20"])
234
+ # transform_filter_option
191
235
  # # => {
192
236
  # instance_ids: ["i-006a097bb10643e20"],
193
237
  # targets: [{key: "Name", values: "hi-web-prod,hi-worker-prod"}]
194
238
  # }
195
239
  #
196
240
  # Returns the duplicated String.
197
- def transform_filter(filter)
198
- valid = validate_filter(filter)
199
- unless valid
200
- UI.error("The filter you provided '#{filter.join(',')}' is not valid.")
201
- UI.say("The filter must either be all instance ids or just a list of tag names.")
202
- exit 1
203
- end
204
-
205
- if filter.detect { |i| instance_id?(i) }
206
- instance_ids = filter
207
- {instance_ids: instance_ids}
208
- else
209
- tags = filter
210
- targets = [{
211
- key: "tag:#{tag_name}",
212
- values: tags
213
- }]
241
+ def transform_filter_option
242
+ if @tags
243
+ list = @tags.split(';')
244
+ targets = list.inject([]) do |final,item|
245
+ tag_name,value_list = item.split('=')
246
+ values = value_list.split(',').map(&:strip)
247
+ # structure expected by ssm send_command
248
+ option = {
249
+ key: "tag:#{tag_name}",
250
+ values: values
251
+ }
252
+ final << option
253
+ final
254
+ end
214
255
  {targets: targets}
215
- end
216
- end
217
-
218
- # Either all instance ids are no instance ids is a valid filter
219
- def validate_filter(filter)
220
- if filter.detect { |i| instance_id?(i) }
221
- instance_ids = filter.select { |i| instance_id?(i) }
222
- instance_ids.size == filter.size
223
- else
224
- true
256
+ else # @instance_ids
257
+ instance_ids = @instance_ids.split(',')
258
+ {instance_ids: instance_ids}
225
259
  end
226
260
  end
227
261
 
@@ -238,7 +272,7 @@ module Sonic
238
272
  # The script is being feed inline so just join the command together into one script.
239
273
  # Still keep in an array form because that's how ssn.send_command works with AWS-RunShellScript
240
274
  # usually reads the command.
241
- [command.join(" ")]
275
+ command.is_a?(Array) ? command : [command]
242
276
  end
243
277
  end
244
278
 
@@ -253,8 +287,7 @@ You can use the following command to check registered instances to SSM.
253
287
  #{ssm_describe_command}
254
288
  EOS
255
289
  UI.warn(message)
256
- copy_paste_clipboard(ssm_describe_command)
257
- UI.say "Pro tip: ssm describe-instance-information already in your copy/paste clipboard."
290
+ copy_paste_clipboard(ssm_describe_command, "Pro tip: ssm describe-instance-information already in your copy/paste clipboard.")
258
291
  end
259
292
 
260
293
  def file_path?(command)
@@ -311,9 +344,10 @@ EOL
311
344
  end
312
345
  end
313
346
 
314
- def copy_paste_clipboard(command)
347
+ def copy_paste_clipboard(command, text)
315
348
  return unless RUBY_PLATFORM =~ /darwin/
316
349
  system("echo '#{command}' | pbcopy")
350
+ UI.say text
317
351
  end
318
352
  end
319
353
  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
@@ -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/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sonic
2
- VERSION = "2.1.1"
2
+ VERSION = "2.2.4"
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)/})
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.1
4
+ version: 2.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-25 00:00:00.000000000 Z
11
+ date: 2021-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -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,161 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- sonic-screwdriver (2.1.1)
5
- activesupport
6
- aws-sdk-ec2
7
- aws-sdk-ecs
8
- aws-sdk-s3
9
- aws-sdk-ssm
10
- hashie
11
- memoist
12
- rainbow
13
- thor
14
- tty-prompt
15
-
16
- GEM
17
- remote: https://rubygems.org/
18
- specs:
19
- activesupport (5.2.2)
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.1)
25
- aws-partitions (1.135.0)
26
- aws-sdk-core (3.46.0)
27
- aws-eventstream (~> 1.0)
28
- aws-partitions (~> 1.0)
29
- aws-sigv4 (~> 1.0)
30
- jmespath (~> 1.0)
31
- aws-sdk-ec2 (1.67.0)
32
- aws-sdk-core (~> 3, >= 3.39.0)
33
- aws-sigv4 (~> 1.0)
34
- aws-sdk-ecs (1.28.0)
35
- aws-sdk-core (~> 3, >= 3.39.0)
36
- aws-sigv4 (~> 1.0)
37
- aws-sdk-kms (1.13.0)
38
- aws-sdk-core (~> 3, >= 3.39.0)
39
- aws-sigv4 (~> 1.0)
40
- aws-sdk-s3 (1.30.1)
41
- aws-sdk-core (~> 3, >= 3.39.0)
42
- aws-sdk-kms (~> 1)
43
- aws-sigv4 (~> 1.0)
44
- aws-sdk-ssm (1.35.0)
45
- aws-sdk-core (~> 3, >= 3.39.0)
46
- aws-sigv4 (~> 1.0)
47
- aws-sigv4 (1.0.3)
48
- byebug (10.0.2)
49
- cli_markdown (0.1.0)
50
- codeclimate-test-reporter (1.0.9)
51
- simplecov (<= 0.13)
52
- coderay (1.1.2)
53
- concurrent-ruby (1.1.4)
54
- diff-lcs (1.3)
55
- docile (1.1.5)
56
- equatable (0.5.0)
57
- ffi (1.10.0)
58
- formatador (0.2.5)
59
- guard (2.15.0)
60
- formatador (>= 0.2.4)
61
- listen (>= 2.7, < 4.0)
62
- lumberjack (>= 1.0.12, < 2.0)
63
- nenv (~> 0.1)
64
- notiffany (~> 0.0)
65
- pry (>= 0.9.12)
66
- shellany (~> 0.0)
67
- thor (>= 0.18.1)
68
- guard-bundler (2.2.1)
69
- bundler (>= 1.3.0, < 3)
70
- guard (~> 2.2)
71
- guard-compat (~> 1.1)
72
- guard-compat (1.2.1)
73
- guard-rspec (4.7.3)
74
- guard (~> 2.1)
75
- guard-compat (~> 1.1)
76
- rspec (>= 2.99.0, < 4.0)
77
- hashie (3.6.0)
78
- i18n (1.5.3)
79
- concurrent-ruby (~> 1.0)
80
- jmespath (1.4.0)
81
- json (2.1.0)
82
- listen (3.1.5)
83
- rb-fsevent (~> 0.9, >= 0.9.4)
84
- rb-inotify (~> 0.9, >= 0.9.7)
85
- ruby_dep (~> 1.2)
86
- lumberjack (1.0.13)
87
- memoist (0.16.0)
88
- method_source (0.9.2)
89
- minitest (5.11.3)
90
- necromancer (0.4.0)
91
- nenv (0.3.0)
92
- notiffany (0.1.1)
93
- nenv (~> 0.1)
94
- shellany (~> 0.0)
95
- pastel (0.7.2)
96
- equatable (~> 0.5.0)
97
- tty-color (~> 0.4.0)
98
- pry (0.12.2)
99
- coderay (~> 1.1.0)
100
- method_source (~> 0.9.0)
101
- rainbow (3.0.0)
102
- rake (12.3.2)
103
- rb-fsevent (0.10.3)
104
- rb-inotify (0.10.0)
105
- ffi (~> 1.0)
106
- rspec (3.8.0)
107
- rspec-core (~> 3.8.0)
108
- rspec-expectations (~> 3.8.0)
109
- rspec-mocks (~> 3.8.0)
110
- rspec-core (3.8.0)
111
- rspec-support (~> 3.8.0)
112
- rspec-expectations (3.8.2)
113
- diff-lcs (>= 1.2.0, < 2.0)
114
- rspec-support (~> 3.8.0)
115
- rspec-mocks (3.8.0)
116
- diff-lcs (>= 1.2.0, < 2.0)
117
- rspec-support (~> 3.8.0)
118
- rspec-support (3.8.0)
119
- ruby_dep (1.5.0)
120
- shellany (0.0.1)
121
- simplecov (0.13.0)
122
- docile (~> 1.1.0)
123
- json (>= 1.8, < 3)
124
- simplecov-html (~> 0.10.0)
125
- simplecov-html (0.10.2)
126
- thor (0.20.3)
127
- thread_safe (0.3.6)
128
- timers (4.3.0)
129
- tty-color (0.4.3)
130
- tty-cursor (0.6.0)
131
- tty-prompt (0.18.1)
132
- necromancer (~> 0.4.0)
133
- pastel (~> 0.7.0)
134
- timers (~> 4.0)
135
- tty-cursor (~> 0.6.0)
136
- tty-reader (~> 0.5.0)
137
- tty-reader (0.5.0)
138
- tty-cursor (~> 0.6.0)
139
- tty-screen (~> 0.6.4)
140
- wisper (~> 2.0.0)
141
- tty-screen (0.6.5)
142
- tzinfo (1.2.5)
143
- thread_safe (~> 0.1)
144
- wisper (2.0.0)
145
-
146
- PLATFORMS
147
- ruby
148
-
149
- DEPENDENCIES
150
- bundler
151
- byebug
152
- cli_markdown
153
- codeclimate-test-reporter
154
- guard
155
- guard-bundler
156
- guard-rspec
157
- rake
158
- sonic-screwdriver!
159
-
160
- BUNDLED WITH
161
- 1.17.1