knife-bulk 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b21db83b5357f2dc64be44ec418fd3139c57a768771218fac890817023a083e4
4
+ data.tar.gz: 0cd26dc6e2e61d1714ed46cd7a0a5a35f0e1f1586c9bf9d255875235adcd4994
5
+ SHA512:
6
+ metadata.gz: ac90dac8fdb710cffd35952a443256814f3e941b1c1718fc80244655d10969818046f28cc7c94e46a4991b6aceec43afe0f78393aded40b89fc268d5bae9bdb6
7
+ data.tar.gz: b2be7b3e5276655f0601a6e6d01b95413f12b92e58738cb537f0a26112eae01b7d8abbecf34686901ac031da2036fc6e6709ac7f6f1e424f297f098a2396dd22
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2022 joshuariojas
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,95 @@
1
+ require 'chef/knife'
2
+ require_relative 'helpers/bulk_node_base.rb'
3
+
4
+ class Chef
5
+ class Knife
6
+ class BulkNodeCheck < Chef::Knife
7
+
8
+ include Chef::Knife::BulkNodeBase
9
+
10
+ deps do
11
+ require 'chef/json_compat' unless defined?(Chef::JSONCompat)
12
+ require 'chef/server_api' unless defined?(Chef::ServerAPI)
13
+ end
14
+
15
+ banner 'knife bulk node check [NODE_NAME [NODE_NAME]] (options)'
16
+ category 'bulk'
17
+
18
+ def run
19
+ STDOUT.sync = STDERR.sync = true
20
+
21
+ config[:format] = 'json'
22
+
23
+ api = Chef::ServerAPI.new
24
+ nodes = bulk_args
25
+ resp = {
26
+ :errors => false,
27
+ :items => {
28
+ :nodes => [],
29
+ :clients => []
30
+ }
31
+ }
32
+
33
+ nodes.each do |node_name|
34
+ begin
35
+ api.head("nodes/#{node_name}")
36
+
37
+ resp[:items][:nodes] << {
38
+ :node_name => node_name,
39
+ :method => 'head',
40
+ :successful => true
41
+ }
42
+ rescue StandardError => e
43
+ resp[:errors] ||= true
44
+ message, code = parse_exception(e)
45
+
46
+ ui.error("Encountered #{e.class} when checking node '#{node_name}'\n#{e}")
47
+
48
+ resp[:items][:nodes] << {
49
+ :node_name => node_name,
50
+ :method => 'head',
51
+ :successful => false,
52
+ :error => {
53
+ :code => code,
54
+ :message => message
55
+ }
56
+ }
57
+ end
58
+
59
+ unless config[:include_clients]
60
+ ui.output(resp)
61
+ return
62
+ end
63
+
64
+ begin
65
+ _ = api.get("clients/#{node_name}")
66
+
67
+ resp[:items][:clients] << {
68
+ :client_name => node_name,
69
+ :method => 'head',
70
+ :successful => true
71
+ }
72
+ rescue StandardError => e
73
+ resp[:errors] ||= true
74
+ message, code = parse_exception(e)
75
+
76
+ ui.error("Encountered #{e.class} when checking client '#{node_name}'\n#{e}")
77
+
78
+ resp[:items][:clients] << {
79
+ :client_name => node_name,
80
+ :method => 'head',
81
+ :successful => false,
82
+ :error => {
83
+ :code => code,
84
+ :message => message
85
+ }
86
+ }
87
+ end
88
+ end
89
+
90
+ ui.output(resp)
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,106 @@
1
+ require 'chef/knife'
2
+ require_relative 'helpers/bulk_node_base'
3
+
4
+ class Chef
5
+ class Knife
6
+ class BulkNodeDelete < Chef::Knife
7
+
8
+ include Chef::Knife::BulkNodeBase
9
+
10
+ banner 'knife bulk node delete [NODE_NAME [NODE_NAME]] (options)'
11
+ category 'bulk'
12
+
13
+ def run
14
+ STDOUT.sync = STDERR.sync = true
15
+
16
+ config[:format] = 'json'
17
+
18
+ api = Chef::ServerAPI.new
19
+ nodes = bulk_args
20
+ resp = {
21
+ :errors => false,
22
+ :items => {
23
+ :nodes => [],
24
+ :clients => []
25
+ }
26
+ }
27
+
28
+ nodes.each do |node_name|
29
+ begin
30
+ api.delete("nodes/#{node_name}")
31
+
32
+ resp[:items][:nodes] << {
33
+ :node_name => node_name,
34
+ :method => 'delete',
35
+ :successful => true
36
+ }
37
+ rescue StandardError => e
38
+ message, code = parse_exception(e)
39
+
40
+ if code == 404
41
+ resp[:items][:nodes] << {
42
+ :node_name => node_name,
43
+ :method => 'delete',
44
+ :successful => true
45
+ }
46
+ else
47
+ resp[:items][:nodes] << {
48
+ :node_name => node_name,
49
+ :method => 'delete',
50
+ :successful => false,
51
+ :error => {
52
+ :code => code,
53
+ :message => message
54
+ }
55
+ }
56
+
57
+ resp[:errors] ||= true
58
+ ui.error("Encountered #{e.class} when checking node '#{node_name}'\n#{e}")
59
+ end
60
+ end
61
+
62
+ unless config[:include_clients]
63
+ ui.output(resp)
64
+ return
65
+ end
66
+
67
+ begin
68
+ api.delete("clients/#{node_name}")
69
+
70
+ resp[:items][:clients] << {
71
+ :client_name => node_name,
72
+ :method => 'delete',
73
+ :successful => true
74
+ }
75
+ rescue StandardError => e
76
+ message, code = parse_exception(e)
77
+
78
+ if code == 404
79
+ resp[:items][:clients] << {
80
+ :client_name => node_name,
81
+ :method => 'delete',
82
+ :successful => true
83
+ }
84
+ else
85
+ resp[:errors] ||= true
86
+ ui.error("Encountered #{e.class} when checking node '#{node_name}'\n#{e}")
87
+
88
+ resp[:items][:clients] << {
89
+ :client_name => node_name,
90
+ :method => 'delete',
91
+ :successful => false,
92
+ :error => {
93
+ :code => code,
94
+ :message => message
95
+ }
96
+ }
97
+ end
98
+ end
99
+ end
100
+
101
+ ui.output(resp)
102
+ end
103
+
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,89 @@
1
+ require 'chef/knife'
2
+ require_relative 'bulk_shared_options'
3
+
4
+ class Chef
5
+ class Knife
6
+ module BulkNodeBase
7
+
8
+ def self.included(includer)
9
+ includer.class_eval do
10
+
11
+ include Chef::Knife::BulkSharedOptions
12
+
13
+ deps do
14
+ require 'chef/json_compat' unless defined?(Chef::JSONCompat)
15
+ require 'chef/server_api' unless defined?(Chef::ServerAPI)
16
+ end
17
+
18
+ option :append_domain,
19
+ long: '--append-domain DOMAIN',
20
+ description: 'Domain that will be appended to each node during HTTP request'
21
+
22
+ option :include_clients,
23
+ long: '--[no-]include-clients',
24
+ description: 'Include operations against client objects',
25
+ boolean: true,
26
+ default: true
27
+
28
+ def append_domain(nodes)
29
+ if config.has_key?(:append_domain)
30
+ return nodes.map { |line| "#{line}.#{config[:append_domain]}" }
31
+ else
32
+ return nodes
33
+ end
34
+ end
35
+
36
+ def file_exists_and_readable?(path)
37
+ File.exist?(path) && File.readable?(path)
38
+ end
39
+
40
+ def bulk_args
41
+ unless config.has_key?(:from_file)
42
+ if @name_args.size == 0
43
+ ui.fatal('You must provide at least one node name')
44
+ exit 1
45
+ end
46
+
47
+ return append_domain(@name_args)
48
+ end
49
+
50
+ if file_exists_and_readable?(config[:from_file])
51
+ nodes = File.readlines(config[:from_file], chomp: true).map(&:strip).reject(&:empty?)
52
+
53
+ if nodes.size == 0
54
+ ui.fatal("Invalid value provided to option '--from-file'. File '#{config[:from_file]} was empty'")
55
+ exit 1
56
+ end
57
+
58
+ return append_domain(nodes)
59
+ else
60
+ show_usage
61
+ ui.fatal("Invalid value provided to option '--from-file'. Could not find or open file '#{config[:from_file]}'")
62
+ exit 1
63
+ end
64
+ end
65
+
66
+ def parse_exception(exception)
67
+ # TODO
68
+ # Extend this to handling different exception categories.
69
+ # exception.class.name.include? 'HTTP' is for handing the family of errors under net/http, but it is barely best effort
70
+ # Undecided on how to handle returns. Currently, the else case intends that code will be set to nil, and a caller may need to
71
+ # check for an exception category that is not yet support below.
72
+ #
73
+ # message, code = parse_exception(exception)
74
+ # if code.nil? then do the things
75
+
76
+ if exception.class.name.include?('HTTP')
77
+ code, message = exception.message.split(' ', 2)
78
+ return message.delete_suffix('"').delete_prefix('"'), code
79
+ else
80
+ return exception.message, nil
81
+ end
82
+ end
83
+
84
+ end
85
+ end
86
+
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,19 @@
1
+ require 'chef/knife'
2
+
3
+ class Chef
4
+ class Knife
5
+ module BulkSharedOptions
6
+
7
+ def self.included(includer)
8
+ includer.class_eval do
9
+
10
+ option :from_file,
11
+ long: '--from-file FILE',
12
+ description: 'File containing list of objects to pass to subcommand in place of expected argument(s)'
13
+
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ module Knife
2
+ module Bulk
3
+ VERSION = '0.1.0'.freeze
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: knife-bulk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Joshua Riojas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-06-29 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Plugin that adds functionality of running bulk requests against Chef
14
+ Infra Server.
15
+ email:
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - LICENSE
21
+ - lib/chef/knife/bulk_node_check.rb
22
+ - lib/chef/knife/bulk_node_delete.rb
23
+ - lib/chef/knife/helpers/bulk_node_base.rb
24
+ - lib/chef/knife/helpers/bulk_shared_options.rb
25
+ - lib/knife-bulk/version.rb
26
+ homepage: https://github.com/joshuariojas/knife-bulk
27
+ licenses:
28
+ - MIT
29
+ metadata: {}
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubyforge_project:
46
+ rubygems_version: 2.7.6.2
47
+ signing_key:
48
+ specification_version: 4
49
+ summary: Plugin that adds functionality of running bulk requests against Chef Infra
50
+ Server.
51
+ test_files: []