a2 0.1.1 → 0.2.0

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: 23a07949036888c04e62fc52f79128f2dcadc32c3774c13677ea127f4492ba71
4
- data.tar.gz: e74e45e471da6be643120a0c38a83ece3dc02f5b9e28d6fdd08651e98d058ead
3
+ metadata.gz: 5ab4e4782cc17d7bdd25d29feda56c81d4dbff2e911f19e9d723f5ecf66801f7
4
+ data.tar.gz: 4993432169fd2305698ee7f1106b0b2a83576eef287ac7065d2543ed38b1cae4
5
5
  SHA512:
6
- metadata.gz: 9f3b5a94eea60a22bf4617725e828569cfa5223482f441982159585438080a63f0d5f4b50ebe500b50c42fcd2c5c4b723afeaa170a69e9e81a069c3b297a1d97
7
- data.tar.gz: 75b703e75a824ccfaa4736679b999653ad3397ccd0c84d050830a5ff6acf4c5d9b8874283b74808c095c6416441dd2d9b23c9a64dc6a9a28d0e4608106ab794c
6
+ metadata.gz: 5cdab720df6fc757d7392598e2ddefed1dfe0883013aca3eb63c95b9b8644ea02de60967b751758c73b312da36d2280ee758a1ae6cbbd92ba9a109ae9d1086ed
7
+ data.tar.gz: e61c4e157f94ff5aca7f69808967cafa12c487bb0978af6726b6772e71d69774791e04c4b04c512ab31857faa15fcca510e645cfc8f3b1d81f6a33b2f2894e3b
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- a2 (0.1.1)
4
+ a2 (0.2.0)
5
5
  cmdparse
6
6
  httparty
7
7
 
data/README.md CHANGED
@@ -27,15 +27,11 @@ SSL_NO_VERIFY=true
27
27
  List the available commands:
28
28
 
29
29
  $ a2 --help
30
- Usage: a2 [options] {cfgmgmt | help | iam | node | version}
30
+ Usage: a2 [options] {compliance | help | iam | infra | nodemgmt | version}
31
31
 
32
32
  Available commands:
33
- cfgmgmt Chef Infra config management commands
34
- list-missing-nodes
35
- list-node-status-counts
36
- list-nodes
37
- list-orgs
38
- show-attributes
33
+ compliance Compliance management commands
34
+ export-node-reports
39
35
  help Provide help for individual commands
40
36
  iam Identity access management commands
41
37
  add-membership
@@ -52,7 +48,15 @@ List the available commands:
52
48
  remove-membership
53
49
  update-team
54
50
  update-user
55
- node Node commands
51
+ infra Chef Infra config management commands
52
+ list-missing-nodes
53
+ list-node-runs
54
+ list-node-status-counts
55
+ list-nodes
56
+ list-orgs
57
+ show-attributes
58
+ show-node-run
59
+ nodemgmt Node management commands
56
60
  bulk-delete-by-filter
57
61
  bulk-delete-by-ids
58
62
  delete
data/lib/a2/client.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require_relative 'client/config_mgmt'
2
2
  require_relative 'client/nodes'
3
+ require_relative 'client/reporting'
3
4
  require_relative 'client/teams'
4
5
  require_relative 'client/users'
5
6
 
@@ -7,6 +8,7 @@ module A2
7
8
  class Client
8
9
  include A2::Client::ConfigMgmt
9
10
  include A2::Client::Nodes
11
+ include A2::Client::Reporting
10
12
  include A2::Client::Teams
11
13
  include A2::Client::Users
12
14
 
@@ -45,6 +47,18 @@ module A2
45
47
  JSON.parse(response.body)
46
48
  end
47
49
 
50
+ def download_report(path, json, output_file)
51
+ File.open(output_file, "w") do |file|
52
+ HTTParty.post(File.join(@automate_url, path).to_s, {
53
+ verify: !@ssl_no_verify,
54
+ headers: {"api-token" => @automate_token},
55
+ body: json
56
+ }) do |fragment|
57
+ file.write(fragment)
58
+ end
59
+ end
60
+ end
61
+
48
62
  def delete(path)
49
63
  response = HTTParty.delete(File.join(@automate_url, path).to_s, {
50
64
  verify: !@ssl_no_verify,
@@ -9,6 +9,10 @@ module A2
9
9
  get "/api/v0/cfgmgmt/stats/missing_node_duration_counts#{query_string}"
10
10
  end
11
11
 
12
+ def list_all_node_runs(node_id, query_string = '')
13
+ get "/api/v0/cfgmgmt/nodes/#{node_id}/runs#{query_string}"
14
+ end
15
+
12
16
  def list_all_node_status_counts(query_string = '')
13
17
  get "/api/v0/cfgmgmt/stats/node_counts#{query_string}"
14
18
  end
@@ -20,6 +24,10 @@ module A2
20
24
  def show_attributes(node_id)
21
25
  get "/api/v0/cfgmgmt/nodes/#{node_id}/attribute"
22
26
  end
27
+
28
+ def show_node_run(node_id, run_id, query_string = '')
29
+ get "/api/v0/cfgmgmt/nodes/#{node_id}/runs/#{run_id}#{query_string}"
30
+ end
23
31
  end
24
32
  end
25
33
  end
@@ -0,0 +1,9 @@
1
+ module A2
2
+ class Client
3
+ module Reporting
4
+ def export_node_reports(json, output_file)
5
+ download_report '/api/v0/compliance/reporting/node/export', json, output_file
6
+ end
7
+ end
8
+ end
9
+ end
data/lib/a2/command.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require_relative 'commands/compliance'
1
2
  require_relative 'commands/iam'
2
3
  require_relative 'commands/infra'
3
4
  require_relative 'commands/node_mgmt'
@@ -0,0 +1,14 @@
1
+ require_relative '../subcommands/reporting'
2
+
3
+ module A2
4
+ module Command
5
+ class Compliance < CmdParse::Command
6
+ def initialize
7
+ super('compliance')
8
+ short_desc('Compliance management commands')
9
+ long_desc('Compliance management commands')
10
+ add_command(A2::Subcommand::Reporting::ExportNodeReports.new)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -9,9 +9,11 @@ module A2
9
9
  long_desc('Chef Infra config management commands')
10
10
  add_command(A2::Subcommand::Infra::ListAllCheckedInNodes.new)
11
11
  add_command(A2::Subcommand::Infra::ListMissingNodesCount.new)
12
+ add_command(A2::Subcommand::Infra::ListNodeRuns.new)
12
13
  add_command(A2::Subcommand::Infra::ListNodeStatusCounts.new)
13
14
  add_command(A2::Subcommand::Infra::ListOrganizations.new)
14
15
  add_command(A2::Subcommand::Infra::ShowAttributes.new)
16
+ add_command(A2::Subcommand::Infra::ShowNodeRun.new)
15
17
  end
16
18
  end
17
19
  end
@@ -1,44 +1,44 @@
1
1
  module A2
2
- module Filtered
2
+ class Filtered < CmdParse::Command
3
3
  def initialize(name, opts = {})
4
4
  set_custom_opts!(opts)
5
5
  super(name, opts)
6
- set_filter_optparse_options!(options)
6
+ set_filter_optparse_options!(options, @query_filter)
7
7
  end
8
8
 
9
9
  def set_custom_opts!(opts)
10
10
  @opt ||= {}
11
- @opt[:query_filter] = opts.delete(:query_filter) || false
11
+ @query_filter = opts.delete(:query_filter) || false
12
+ @filter_key = opts.delete(:filter_key) || 'key'
12
13
  end
13
14
 
14
- def set_filter_optparse_options!(options)
15
+ def set_filter_optparse_options!(options, query_filter)
15
16
  options.on('-f', '--filters FILTERS', 'A comma-separated list of filters.') do |filters|
16
17
  @opt[:filters] = filters
17
18
  end
18
- # Only available for POST body filters
19
- options.on('-j', '--json-file FILE', 'Path to a json file containing a filter payload.') do |file|
20
- @opt[:json_file] = file
21
- end unless query_filter?
22
- # Only available for query parameter filters
23
- options.on('-S', '--start START', 'Earliest most recent check-in node information to return. Formatted iso8601 (YYYY-MM-DD\'T\'HH:mm:ssZ)') do |start|
24
- @opt[:start] = start
25
- end if query_filter?
26
- options.on('-E', '--end END', 'Latest most recent check-in node information to return. Formatted iso8601 (YYYY-MM-DD\'T\'HH:mm:ssZ)') do |end_arg|
27
- @opt[:end] = end_arg
28
- end if query_filter?
29
- end
30
-
31
- def query_filter?
32
- @opt[:query_filter]
19
+ if query_filter
20
+ # Only available for query parameter filters
21
+ options.on('-S', '--start-time START', 'Earliest most recent check-in node information to return. Formatted iso8601 (YYYY-MM-DD\'T\'HH:mm:ssZ)') do |start_time|
22
+ @opt[:start] = start_time
23
+ end
24
+ options.on('-E', '--end-time END', 'Latest most recent check-in node information to return. Formatted iso8601 (YYYY-MM-DD\'T\'HH:mm:ssZ)') do |end_time|
25
+ @opt[:end] = end_time
26
+ end
27
+ else
28
+ # Only available for POST body filters
29
+ options.on('-j', '--json-file FILE', 'Path to a json file containing a filter payload.') do |file|
30
+ @opt[:json_file] = file
31
+ end
32
+ end
33
33
  end
34
34
 
35
35
  def parse_filters(filters)
36
36
  parsed_filters = []
37
37
  filters.split(',').each do |f|
38
- k,v = f.split(':')
38
+ k,*v = f.split(':')
39
39
  parsed_filters << {
40
- 'key' => k,
41
- 'values' => [v]
40
+ @filter_key => k,
41
+ 'values' => [v.join(':')]
42
42
  }
43
43
  end
44
44
  parsed_filters
@@ -1,33 +1,26 @@
1
1
  module A2
2
- module Paginated
3
- include A2::Filtered
2
+ class Paginated < Filtered
4
3
  def initialize(name, opts = {})
5
- set_custom_opts!(opts)
4
+ disable_sort_opts = opts.delete(:disable_sort_opts) || false
6
5
  super(name, opts)
7
- @opt = {
8
- order: 'ASC'
9
- }
6
+ @opt[:order] = 'ASC' unless disable_sort_opts
10
7
  options.on('-o', '--order ORDER', 'Return the results in ascending or descending order. Default is "ASC".') do |order|
11
8
  @opt[:order] = order
12
- end
9
+ end unless disable_sort_opts
10
+ options.on('-s', '--sort SORT', 'Sort the results on a specific field.') do |sort|
11
+ @opt[:sort] = sort
12
+ end unless disable_sort_opts
13
13
  options.on('-p', '--page PAGE', Integer, 'Starting page for the results. Default is 0') do |page|
14
14
  @opt[:page] = page
15
15
  end
16
16
  options.on('-P', '--per-page PER_PAGE', Integer, 'The number of results on each page. Default is 100') do |per_page|
17
17
  @opt[:per_page] = per_page
18
18
  end
19
- options.on('-s', '--sort SORT', 'Sort the results on a specific field.') do |sort|
20
- @opt[:sort] = sort
21
- end
22
- set_filter_optparse_options!(options)
23
- end
24
-
25
- def generate_paginated_json_filters
26
- generate_json_filters
19
+ set_filter_optparse_options!(options, @query_filter)
27
20
  end
28
21
 
29
22
  def with_paginated_filter_json(&block)
30
- json = generate_paginated_json_filters
23
+ json = generate_json_filters
31
24
  yield(json)
32
25
  end
33
26
 
data/lib/a2/parser.rb CHANGED
@@ -5,6 +5,7 @@ module A2
5
5
  parser.main_options.version = A2::VERSION
6
6
  parser.add_command(CmdParse::HelpCommand.new)
7
7
  parser.add_command(CmdParse::VersionCommand.new)
8
+ parser.add_command(A2::Command::Compliance.new)
8
9
  parser.add_command(A2::Command::IAM.new)
9
10
  parser.add_command(A2::Command::Infra.new)
10
11
  parser.add_command(A2::Command::NodeMgmt.new)
@@ -1,14 +1,13 @@
1
1
  module A2
2
2
  module Subcommand
3
3
  module Infra
4
- class ListAllCheckedInNodes < CmdParse::Command
5
- include A2::Paginated
4
+ class ListAllCheckedInNodes < Paginated
6
5
  def initialize
7
6
  super('list-nodes', takes_commands: false, query_filter: true)
8
7
  end
9
8
 
10
9
  def execute
11
- with_filter_query do |query_string|
10
+ with_paginated_filter_query do |query_string|
12
11
  puts JSON.pretty_generate(A2::Client.new(command_parser.data).list_all_checked_in_nodes(query_string))
13
12
  end
14
13
  end
@@ -26,8 +25,18 @@ module A2
26
25
  puts JSON.pretty_generate(A2::Client.new(command_parser.data).list_all_missing_nodes_count(@opt[:durations]))
27
26
  end
28
27
  end
29
- class ListNodeStatusCounts < CmdParse::Command
30
- include A2::Filtered
28
+ class ListNodeRuns < Paginated
29
+ def initialize
30
+ super('list-node-runs', takes_commands: false, query_filter: true, disable_sort_opts: true)
31
+ end
32
+
33
+ def execute(node_id)
34
+ with_paginated_filter_query do |query_string|
35
+ puts JSON.pretty_generate(A2::Client.new(command_parser.data).list_all_node_runs(node_id, query_string))
36
+ end
37
+ end
38
+ end
39
+ class ListNodeStatusCounts < Filtered
31
40
  def initialize
32
41
  super('list-node-status-counts', takes_commands: false, query_filter: true)
33
42
  end
@@ -56,6 +65,22 @@ module A2
56
65
  puts JSON.pretty_generate(A2::Client.new(command_parser.data).show_attributes(node_id))
57
66
  end
58
67
  end
68
+ class ShowNodeRun < CmdParse::Command
69
+ def initialize
70
+ super('show-node-run', takes_commands: false)
71
+ @opt = {}
72
+ options.on('-E', '--end-time END', "End time on the node's run. Formatted iso8601 (YYYY-MM-DD\'T\'HH:mm:ssZ)") do |end_time|
73
+ @opt[:end_time] = end_time
74
+ end
75
+ end
76
+
77
+ def execute(node_id, run_id)
78
+ query_string = ''
79
+ query_string = "?end_time=#{@opt[:end_time]}" if @opt[:end_time]
80
+
81
+ puts JSON.pretty_generate(A2::Client.new(command_parser.data).show_node_run(node_id, run_id, query_string))
82
+ end
83
+ end
59
84
  end
60
85
  end
61
86
  end
@@ -10,8 +10,7 @@ module A2
10
10
  puts JSON.pretty_generate(A2::Client.new(command_parser.data).get_managed_node(id))
11
11
  end
12
12
  end
13
- class Search < CmdParse::Command
14
- include A2::Paginated
13
+ class Search < Paginated
15
14
 
16
15
  def initialize
17
16
  super('search', takes_commands: false)
@@ -25,7 +24,6 @@ module A2
25
24
  end
26
25
  class Delete < CmdParse::Command
27
26
  include A2::Approved
28
-
29
27
  def initialize
30
28
  super('delete', takes_commands: false)
31
29
  end
@@ -38,7 +36,6 @@ module A2
38
36
  end
39
37
  class BulkDeleteById < CmdParse::Command
40
38
  include A2::Approved
41
-
42
39
  def initialize
43
40
  super('bulk-delete-by-ids', takes_commands: false)
44
41
  end
@@ -49,10 +46,8 @@ module A2
49
46
  end
50
47
  end
51
48
  end
52
- class BulkDeleteByFilter < CmdParse::Command
49
+ class BulkDeleteByFilter < Paginated
53
50
  include A2::Approved
54
- include A2::Paginated
55
-
56
51
  def initialize
57
52
  super('bulk-delete-by-filter', takes_commands: false)
58
53
  end
@@ -0,0 +1,30 @@
1
+ module A2
2
+ module Subcommand
3
+ module Reporting
4
+ class ExportNodeReports < Paginated
5
+ def initialize
6
+ super('export-node-reports', takes_commands: false, filter_key: 'type')
7
+ @opt[:type] = 'csv'
8
+ options.on('-n', '--name NAME', 'Name of the profile (as defined in inspec.yml).') do |name|
9
+ @opt[:name] = name
10
+ end
11
+ options.on('-O', '--owner OWNER', 'Automate user associated with the profile.') do |owner|
12
+ @opt[:owner] = owner
13
+ end
14
+ options.on('-o', '--output OUTPUT_TYPE', 'Desired report data format (either "csv" or "json"). Default value is "csv".') do |output_type|
15
+ @opt[:type] = output_type
16
+ end
17
+ end
18
+
19
+ def execute(filename = nil, output_type = 'csv')
20
+ # Workaround for bug: https://github.com/chef/automate/issues/4926
21
+ @opt[:order] = @opt[:order].downcase.eql?('asc') ? 0 : 1
22
+ with_paginated_filter_json do |json|
23
+ filename ||= "report-#{Time.now.strftime('%Y%m%d%H%M%S')}.#{@opt[:type]}"
24
+ response = A2::Client.new(command_parser.data).export_node_reports(json, filename)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -48,7 +48,6 @@ module A2
48
48
  end
49
49
  class Delete < CmdParse::Command
50
50
  include A2::Approved
51
-
52
51
  def initialize
53
52
  super('delete-team', takes_commands: false)
54
53
  end
data/lib/a2/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module A2
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: a2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gscho
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-24 00:00:00.000000000 Z
11
+ date: 2021-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -106,9 +106,11 @@ files:
106
106
  - lib/a2/client.rb
107
107
  - lib/a2/client/config_mgmt.rb
108
108
  - lib/a2/client/nodes.rb
109
+ - lib/a2/client/reporting.rb
109
110
  - lib/a2/client/teams.rb
110
111
  - lib/a2/client/users.rb
111
112
  - lib/a2/command.rb
113
+ - lib/a2/commands/compliance.rb
112
114
  - lib/a2/commands/iam.rb
113
115
  - lib/a2/commands/infra.rb
114
116
  - lib/a2/commands/node_mgmt.rb
@@ -118,6 +120,7 @@ files:
118
120
  - lib/a2/parser.rb
119
121
  - lib/a2/subcommands/infra.rb
120
122
  - lib/a2/subcommands/node_mgmt.rb
123
+ - lib/a2/subcommands/reporting.rb
121
124
  - lib/a2/subcommands/team.rb
122
125
  - lib/a2/subcommands/user.rb
123
126
  - lib/a2/version.rb