sonic-screwdriver 2.1.1 → 2.2.4

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: '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