knife-butler 0.0.1

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
+ SHA1:
3
+ metadata.gz: 6cc04e9386149e034f6668aa9a1a451128e887e9
4
+ data.tar.gz: d1e1ebd8d7479011af8ba3c39408e2b28a8899c1
5
+ SHA512:
6
+ metadata.gz: 65597e30106b2570dbfb1ee62565abe91a70d2ad50fc7c4f6deb15b5fb0aed9b5af41c62fc9a7d81664bc67bb94289b96d54e68ca6591a3cd1555f0f08deb007
7
+ data.tar.gz: 5abd3122ea1949896554a3cc2c8acef5d99e90400ade7fd07f88c7114cc41602b40eb2949b95480b24ddce320788015153edbb83ebb3dc53faf71170ef621c7b
data/CHANGES.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ == 2018-04-07 (0.0.1)
2
+
3
+ * Initial release
data/README.rdoc ADDED
@@ -0,0 +1,26 @@
1
+ = knife-butler
2
+
3
+ == DESCRIPTION:
4
+
5
+ Knife plugin for cookbook testing.
6
+
7
+ == INSTALLATION:
8
+ This plugin is distributed as a Ruby Gem. To install it, run:
9
+
10
+ gem install knife-butler (with specific-install for now; not published)
11
+
12
+ Depending on your system's configuration, you may need to run this command with root privileges.
13
+
14
+ == CONFIGURATION:
15
+
16
+ ..
17
+
18
+ == SUBCOMMANDS:
19
+
20
+ ...
21
+
22
+ == LICENSE:
23
+
24
+ Author:: Robbert-Jan Sperna Weiland
25
+
26
+ Copyright:: Copyright (c) 2018
@@ -0,0 +1,69 @@
1
+ #
2
+ # Author:: Robbert-Jan Sperna Weiland (<rspernaweiland@schubergphilis.com>)
3
+ #
4
+
5
+ require 'chef/knife'
6
+ require 'json'
7
+
8
+ module KnifeButler
9
+ class ButlerClean < Chef::Knife
10
+
11
+ deps do
12
+ require 'chef/knife/bootstrap'
13
+ # Depend on knife-cosmic:
14
+ require 'chef/knife/cosmic_server_delete'
15
+ Knifecosmic::CosmicServerDelete.load_deps
16
+ require 'yaml'
17
+ require "erb"
18
+ end
19
+
20
+ banner "knife butler clean"
21
+
22
+ def run
23
+ test_config = config_fetch
24
+ butler_data = butler_data_fetch
25
+
26
+ puts butler_data
27
+
28
+ # Destroy VM
29
+ server_delete = Knifecosmic::CosmicServerDelete.new
30
+
31
+ server_delete.name_args = [butler_data['server_name']]
32
+ server_delete.config[:cosmic_url] = "https://#{test_config['driver']['customize']['host']}/client/api"
33
+ server_delete.config[:cosmic_api_key] = test_config['driver']['customize']['api_key']
34
+ server_delete.config[:cosmic_secret_key] = test_config['driver']['customize']['secret_key']
35
+ server_delete.config[:yes] = true
36
+ puts "Deleting VM..."
37
+ begin
38
+ vm_delete_details = server_delete.run
39
+ rescue
40
+ nil
41
+ end
42
+ puts "Done!"
43
+
44
+ # Wait for the VM do be deleted
45
+ sleep(10)
46
+
47
+ # Expunge!
48
+ begin
49
+ vm_delete_details = server_delete.run
50
+ rescue
51
+ nil
52
+ end
53
+ puts "Done!"
54
+ end
55
+
56
+ def butler_data_fetch
57
+ # Get config
58
+ butler_data_raw = File.read('.butler.yml')
59
+ YAML.load(butler_data_raw)
60
+ end
61
+
62
+ def config_fetch
63
+ # Get config
64
+ test_config_raw = File.read('.kitchen.yml')
65
+ test_config_evaluated = ERB.new(test_config_raw).result( binding )
66
+ YAML.load(test_config_evaluated)
67
+ end
68
+ end # class
69
+ end
@@ -0,0 +1,165 @@
1
+ #
2
+ # Author:: Robbert-Jan Sperna Weiland (<rspernaweiland@schubergphilis.com>)
3
+ #
4
+
5
+ require 'chef/knife'
6
+ require 'json'
7
+
8
+ module KnifeButler
9
+ class ButlerPrepare < Chef::Knife
10
+
11
+ deps do
12
+ require 'chef/knife/bootstrap'
13
+ Chef::Knife::Bootstrap.load_deps
14
+ # Depend on knife-cosmic:
15
+ require 'chef/knife/cosmic_server_create'
16
+ Knifecosmic::CosmicServerCreate.load_deps
17
+ Knifecosmic::CosmicForwardruleCreate.load_deps
18
+ require 'yaml'
19
+ require "erb"
20
+ require 'socket'
21
+ require 'timeout'
22
+ end
23
+
24
+ banner "knife butler prepare"
25
+
26
+ def run
27
+ test_config = config_fetch
28
+ Chef::Log.debug("cosmic HOST: #{test_config['driver']['customize']['host']}")
29
+ Chef::Log.debug("cosmic NETWORK_NAME: #{test_config['driver']['customize']['network_name']}")
30
+
31
+ # Create unique data for this test environment:
32
+ o = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten
33
+ str_random = (0...8).map { o[rand(o.length)] }.join
34
+ butler_data = {}
35
+ butler_data['server_name'] = "butler-#{str_random}"
36
+ str_random = (0...4).map { [rand(10)] }.join
37
+ butler_data['port_exposed_winrm'] = str_random
38
+ str_random = (0...4).map { [rand(10)] }.join
39
+ butler_data['port_exposed_zipdata'] = str_random
40
+ File.open('.butler.yml', 'w') {|f| f.write butler_data.to_yaml } #Store
41
+
42
+ # Create VM
43
+ server_create = Knifecosmic::CosmicServerCreate.new
44
+
45
+ server_create.name_args = [butler_data['server_name']]
46
+ server_create.config[:cosmic_networks] = [test_config['driver']['customize']['network_name']]
47
+ server_create.config[:cosmic_template] = test_config['platforms'].first['driver_config']['box']
48
+ server_create.config[:bootstrap] = false
49
+ server_create.config[:public_ip] = false
50
+ server_create.config[:cosmic_service] = test_config['driver']['customize']['service_offering_name']
51
+ #server_create.config[:ipfwd_rules] = "#{butler_data['port_exposed_winrm']}:5985:TCP"
52
+ server_create.config[:cosmic_password] = true
53
+ server_create.config[:cosmic_url] = "https://#{test_config['driver']['customize']['host']}/client/api"
54
+ server_create.config[:cosmic_api_key] = test_config['driver']['customize']['api_key']
55
+ server_create.config[:cosmic_secret_key] = test_config['driver']['customize']['secret_key']
56
+ puts "Creating VM..."
57
+ server_create.run
58
+ server_details = server_create.server
59
+ puts "Done!...details:"
60
+ puts server_details
61
+ puts "IP OF SERVER: #{server_details['public_ip']}"
62
+ puts "End of detalis"
63
+ butler_data['server_ip'] = server_details['public_ip']
64
+ butler_data['server_password'] = server_details['passwordenabled'] ? server_details['password'] : test_config['driver']['customize']['vm_password']
65
+ File.open('.butler.yml', 'w') {|f| f.write butler_data.to_yaml } #Store
66
+
67
+ # Wait for the VM to settle into existance
68
+ sleep(5)
69
+
70
+ # Create WinRM forwardrule
71
+ forwardingrule_create = Knifecosmic::CosmicForwardruleCreate.new
72
+
73
+ forwardingrule_create.name_args = [butler_data['server_name'], "#{butler_data['port_exposed_winrm']}:5985:TCP"]
74
+ forwardingrule_create.config[:vrip] = test_config['driver']['customize']['pf_ip_address']
75
+ forwardingrule_create.config[:cosmic_url] = "https://#{test_config['driver']['customize']['host']}/client/api"
76
+ forwardingrule_create.config[:cosmic_api_key] = test_config['driver']['customize']['api_key']
77
+ forwardingrule_create.config[:cosmic_secret_key] = test_config['driver']['customize']['secret_key']
78
+ puts "Creating forwarding rule..."
79
+ forwardingrule_details = forwardingrule_create.run
80
+ puts "Done!"
81
+
82
+ # Create Payload forwardrule
83
+ forwardingrule_create = Knifecosmic::CosmicForwardruleCreate.new
84
+
85
+ forwardingrule_create.name_args = [butler_data['server_name'], "#{butler_data['port_exposed_zipdata']}:5999:TCP"]
86
+ forwardingrule_create.config[:vrip] = test_config['driver']['customize']['pf_ip_address']
87
+ forwardingrule_create.config[:cosmic_url] = "https://#{test_config['driver']['customize']['host']}/client/api"
88
+ forwardingrule_create.config[:cosmic_api_key] = test_config['driver']['customize']['api_key']
89
+ forwardingrule_create.config[:cosmic_secret_key] = test_config['driver']['customize']['secret_key']
90
+ puts "Creating forwarding rule..."
91
+ forwardingrule_details = forwardingrule_create.run
92
+ puts "Done!"
93
+
94
+ # Firewall rule for WinRM
95
+ firewall_rule = Knifecosmic::CosmicFirewallruleCreate.new
96
+ firewall_rule.config[:cosmic_url] = "https://#{test_config['driver']['customize']['host']}/client/api"
97
+ firewall_rule.config[:cosmic_api_key] = test_config['driver']['customize']['api_key']
98
+ firewall_rule.config[:cosmic_secret_key] = test_config['driver']['customize']['secret_key']
99
+ firewall_rule.name_args = [butler_data['server_name']]
100
+ test_config['driver']['customize']['pf_trusted_networks'].split(",").each do |cidr|
101
+ firewall_rule.name_args.push("5985:5985:TCP:#{cidr}")
102
+ end
103
+ firewall_rule.config[:public_ip] = test_config['driver']['customize']['pf_ip_address']
104
+ firewall_rule.run
105
+
106
+ # Firewall rule for zipdata
107
+ firewall_rule = Knifecosmic::CosmicFirewallruleCreate.new
108
+ firewall_rule.config[:cosmic_url] = "https://#{test_config['driver']['customize']['host']}/client/api"
109
+ firewall_rule.config[:cosmic_api_key] = test_config['driver']['customize']['api_key']
110
+ firewall_rule.config[:cosmic_secret_key] = test_config['driver']['customize']['secret_key']
111
+ firewall_rule.name_args = [butler_data['server_name']]
112
+ test_config['driver']['customize']['pf_trusted_networks'].split(",").each do |cidr|
113
+ firewall_rule.name_args.push("5999:5999:TCP:#{cidr}")
114
+ end
115
+ firewall_rule.config[:public_ip] = test_config['driver']['customize']['pf_ip_address']
116
+ firewall_rule.run
117
+
118
+ # Wait for WinRM to become responsive:
119
+ puts "Waiting for WinRM......"
120
+ wait_for_port_open(test_config['driver']['customize']['pf_ip_address'], butler_data['port_exposed_winrm'])
121
+ puts "WinRM available!"
122
+ sleep(2)
123
+ end
124
+
125
+ def config_fetch
126
+ # Get config
127
+ test_config_raw = File.read('.kitchen.yml')
128
+ test_config_evaluated = ERB.new(test_config_raw).result( binding )
129
+ YAML.load(test_config_evaluated)
130
+ end
131
+ def wait_for_port_open(ip, port)
132
+ port_open = false
133
+ while !port_open
134
+ begin
135
+ puts "TRYING PORT....."
136
+ thr = Thread.new {
137
+ begin
138
+ s=TCPSocket.open(ip, port)
139
+ s.close
140
+ rescue
141
+ sleep(3)
142
+ end
143
+ Thread.exit
144
+ }
145
+ sleep(2)
146
+ rescue
147
+ nil
148
+ end
149
+ if !thr.alive?
150
+ puts "PORT IS OPEN!"
151
+ port_open = true
152
+ begin
153
+ thr.exit
154
+ while thr.status
155
+ thr.exit
156
+ end
157
+ rescue
158
+ nil
159
+ end
160
+ end
161
+ thr.join
162
+ end
163
+ end
164
+ end # class
165
+ end
@@ -0,0 +1,170 @@
1
+ #
2
+ # Author:: Robbert-Jan Sperna Weiland (<rspernaweiland@schubergphilis.com>)
3
+ #
4
+
5
+ require 'chef/knife'
6
+ require 'json'
7
+ require 'rubygems'
8
+
9
+ module KnifeButler
10
+ class ButlerRun < Chef::Knife
11
+
12
+ deps do
13
+ require 'chef/knife/bootstrap_windows_winrm'
14
+ Chef::Knife::BootstrapWindowsWinrm.load_deps
15
+ require 'yaml'
16
+ require 'erb'
17
+ require 'socket'
18
+ require 'winrm-fs'
19
+ end
20
+
21
+ banner "knife butler run"
22
+
23
+ def run
24
+ test_config = config_fetch
25
+ butler_data = butler_data_fetch
26
+
27
+ # Prepare chef-solo files
28
+ #
29
+ # exec ( "mkdir .\butler_bootstrap_data" )
30
+ # exec ( "echo dbskjhdbskj > .\butler_bootstrap_data\testfile" )
31
+
32
+
33
+ puts "Fetching windows butler runner file from gem path..."
34
+ butler_runner_windows = Gem.find_files(File.join('chef', 'knife', 'resources', 'butler_runner_windows.ps1')).first
35
+ butler_runner_windows_path = File.dirname(butler_runner_windows)
36
+ puts "Done. Path: #{butler_runner_windows_path}"
37
+
38
+ # Re-run bootstrap with new command (simply tailing butler run wrapper script logfile)
39
+ # until that file is deleted, and then check exit_status of .butler exit status reporting file
40
+
41
+ # Prepare ZIP with chef-solo run:
42
+ puts "Building ZIP with cookbook data"
43
+ berks_result = `bundle exec berks package`
44
+ berks_zip = berks_result.split(' to ').last.chomp("\n")
45
+ puts "ZIPFILE: #{berks_zip}"
46
+
47
+ `tar -xvzf #{berks_zip}`
48
+
49
+ `mkdir ./butler`
50
+ `mv ./cookbooks ./butler/`
51
+ `mkdir ./butler/checksums`
52
+ `echo >> ./butler/checksums/dummy`
53
+ `mkdir ./butler/cache`
54
+ `echo >> ./butler/cache/dummy`
55
+ `mkdir ./butler/backup`
56
+ `echo >> ./butler/backup/dummy`
57
+ `mkdir ./butler/data_bags`
58
+ `echo >> ./butler/data_bags/dummy`
59
+ `mkdir ./butler/environments`
60
+ `echo >> ./butler/environments/dummy`
61
+ `mkdir ./butler/nodes`
62
+ `echo >> ./butler/nodes/dummy`
63
+ `mkdir ./butler/roles`
64
+ `echo >> ./butler/roles/dummy`
65
+
66
+ # Push chef-solo.rb into the butler folder
67
+ chef_solo_rb_path = Gem.find_files(File.join('chef', 'knife', 'resources', 'templates', 'chef-solo.rb')).first
68
+ `cp #{chef_solo_rb_path} ./butler`
69
+
70
+ # Push client.pem into the zip folder
71
+ chef_client_pem = Gem.find_files(File.join('chef', 'knife', 'resources', 'client.pem')).first
72
+ `cp #{chef_client_pem} ./butler`
73
+
74
+ # Push cookbook folder to test VM
75
+ sleep(1)
76
+ puts "PUSHING FILES TO VM"
77
+ opts = {
78
+ endpoint: "http://#{test_config['driver']['customize']['pf_ip_address']}:#{butler_data['port_exposed_winrm']}/wsman",
79
+ user: 'Administrator',
80
+ password: butler_data['server_password']
81
+ }
82
+ connection = WinRM::Connection.new(opts)
83
+ file_manager = WinRM::FS::FileManager.new(connection)
84
+ file_manager.upload('butler', "C:\\Programdata\\")
85
+
86
+ sleep(1)
87
+
88
+ # Bootstrap our VM with the desired runlist
89
+ puts "Configuring bootstrap call"
90
+ bootstrap = Chef::Knife::BootstrapWindowsWinrm.new
91
+
92
+ bootstrap.name_args = [test_config['driver']['customize']['pf_ip_address']]
93
+ bootstrap.config[:winrm_port] = butler_data['port_exposed_winrm']
94
+ bootstrap.config[:winrm_password] = butler_data['server_password']
95
+ bootstrap.config[:winrm_user] = 'Administrator'
96
+ bootstrap.config[:bootstrap_version] = test_config['provisioner']['require_chef_omnibus']
97
+ bootstrap.config[:chef_node_name] = butler_data['server_name']
98
+ bootstrap.config[:chef_server] = false
99
+ bootstrap.config[:payload_folder] = butler_runner_windows_path
100
+ repo_name=File.basename(Dir.pwd)
101
+
102
+ runlist = test_config['suites'][0]['run_list'].join(",")
103
+ bootstrap.config[:bootstrap_run_command] = "C:\\chef\\extra_files\\butler_runner_windows.ps1 #{repo_name} #{test_config['suites'][0]['attributes']['chef_environment']} \"#{runlist}\""
104
+ bootstrap.config[:bootstrap_tail_file] = 'C:\chef\client.log'
105
+ # bootstrap.config[:bootstrap_run_command] = 'get-childitem C:\chef\extra_files'
106
+
107
+ puts "Starting bootstrap.."
108
+ bootstrap.run
109
+ puts "Done!"
110
+ end
111
+
112
+ def folder_zip_recursive(zipfile, folder, subpath=nil)
113
+ folder_list = subpath.nil? ? folder : File.join(folder, subpath)
114
+ Dir.foreach(folder_list) do |item|
115
+ next if item == '.' or item == '..'
116
+ if File.file?(File.join(folder_list,item))
117
+ internal_path = subpath.nil? ? item : File.join(subpath, item)
118
+ zipfile.get_output_stream(internal_path) do |f|
119
+ f.write(File.open(File.join(folder_list,item), 'rb').read)
120
+ end
121
+ # zipfile.add(internal_path, File.join(folder,item))
122
+ #puts File.join(prefix,item)
123
+ else
124
+ forward_subpath = subpath.nil? ? item : File.join(subpath, item)
125
+ folder_zip_recursive(zipfile, folder, forward_subpath)
126
+ end
127
+ end
128
+ end
129
+
130
+ def config_fetch
131
+ # Get config
132
+ test_config_raw = File.read('.kitchen.yml')
133
+ test_config_evaluated = ERB.new(test_config_raw).result( binding )
134
+ YAML.load(test_config_evaluated)
135
+ end
136
+ def butler_data_fetch
137
+ # Get config
138
+ butler_data_raw = File.read('.butler.yml')
139
+ YAML.load(butler_data_raw)
140
+ end
141
+ def wait_for_port_open(ip, port)
142
+ port_open = false
143
+ while !port_open
144
+ begin
145
+ puts "TRYING PORT....."
146
+ thr = Thread.new {
147
+ s=TCPSocket.open(ip, port)
148
+ s.close
149
+ }
150
+ sleep(2)
151
+ rescue
152
+ nil
153
+ end
154
+ if !thr.alive?
155
+ puts "PORT IS OPEN!"
156
+ port_open = true
157
+ begin
158
+ thr.exit
159
+ while thr.status
160
+ thr.exit
161
+ end
162
+ rescue
163
+ nil
164
+ end
165
+ end
166
+ thr.join
167
+ end
168
+ end
169
+ end # class
170
+ end
@@ -0,0 +1,26 @@
1
+ $repo_name = $args[0]
2
+ $environment = $args[1]
3
+ $runlist = $args[2]
4
+
5
+ $repo = $test_data.repository
6
+
7
+ # Copy data bags from repo to databags path
8
+ mkdir -f C:\Programdata\Butler\data_bags
9
+ mkdir -f C:\Users\ADMINI~1\AppData\Local\Temp\kitchen\cache
10
+ copy-item -Recurse "C:\ProgramData\butler\cookbooks\$($repo_name)\test\fixtures\data_bags\*.*" "C:\ProgramData\butler\data_bags"
11
+ copy-item -Recurse "C:\ProgramData\butler\cookbooks\$($repo_name)\test\fixtures\data_bags\*" "C:\ProgramData\butler\data_bags"
12
+ copy-item "C:\ProgramData\butler\cookbooks\$($repo_name)\test\integration\default\encrypted_data_bag_secret" "C:\Chef"
13
+ New-Item C:\Programdata\butler\validation_key -ItemType file
14
+ copy-item "C:\ProgramData\butler\cookbooks\$($repo_name)\test\environments\*.*" "C:\Programdata\butler\environments"
15
+
16
+
17
+ c:\opscode\chef\bin\chef-client.bat -z -E $environment -c C:\ProgramData\butler\chef-solo.rb -o "$runlist" -L C:\chef\client.log
18
+ # Chef manages to exit with return code 0, even when failing and creating a stacktrace file. So lets check for that:
19
+ $resultcode = $LASTEXITCODE
20
+ if (($resultcode -eq 0) -And (Test-Path C:\Users\Administrator\AppData\Local\Temp\kitchen\cache\chef-stacktrace.out)) {
21
+ $resultcode = 7382
22
+ }
23
+ # Remove log to trigger continuation of bootstrap console script
24
+ while (Test-Path 'C:\chef\client.log') { Remove-Item 'C:\chef\client.log' -Force -ErrorAction SilentlyContinue }
25
+ # Throw error code back upstream in case of unsuccessful run
26
+ if ($resultcode -ne 0) { throw $resultcode }
File without changes
@@ -0,0 +1,16 @@
1
+ node_name 'tsttst101'
2
+ checksum_path 'C:\Programdata\butler\checksums'
3
+ file_cache_path 'C:\Users\ADMINI~1\AppData\Local\Temp\kitchen\cache'
4
+ file_backup_path 'C:\Programdata\butler\backup'
5
+ cookbook_path 'C:\Programdata\butler\cookbooks'
6
+ data_bag_path 'C:\Programdata\butler\data_bags'
7
+ environment_path 'C:\Programdata\butler\environments'
8
+ node_path 'C:\Programdata\butler\nodes'
9
+ role_path 'C:\Programdata\butler\roles'
10
+ client_path
11
+ user_path
12
+ validation_key 'C:\Programdata\butler\validation_key'
13
+ client_key 'C:\bogus_key'
14
+ encrypted_data_bag_secret
15
+ treat_deprecation_warnings_as_errors false
16
+ solo 'true'
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: knife-butler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Robbert-Jan Sperna Weiland
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: chef
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "<"
18
+ - !ruby/object:Gem::Version
19
+ version: '14'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "<"
25
+ - !ruby/object:Gem::Version
26
+ version: '14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: knife-cosmic
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: knife-winops
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 2.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 2.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: winrm-fs
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rb-readline
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 0.5.5
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 0.5.5
83
+ - !ruby/object:Gem::Dependency
84
+ name: berkshelf
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "<"
88
+ - !ruby/object:Gem::Version
89
+ version: '7'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "<"
95
+ - !ruby/object:Gem::Version
96
+ version: '7'
97
+ - !ruby/object:Gem::Dependency
98
+ name: dep_selector
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">"
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">"
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: knife-solo
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">"
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">"
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: A Knife plugin to test Chef cookbooks
126
+ email:
127
+ - rspernaweiland@schubergphilis.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files:
131
+ - README.rdoc
132
+ - CHANGES.rdoc
133
+ files:
134
+ - CHANGES.rdoc
135
+ - README.rdoc
136
+ - lib/chef/knife/butler_clean.rb
137
+ - lib/chef/knife/butler_prepare.rb
138
+ - lib/chef/knife/butler_run.rb
139
+ - lib/chef/knife/resources/butler_runner_windows.ps1
140
+ - lib/chef/knife/resources/client.pem
141
+ - lib/chef/knife/resources/templates/chef-solo.rb
142
+ homepage: https://www.schubergphilis.com/
143
+ licenses: []
144
+ metadata: {}
145
+ post_install_message:
146
+ rdoc_options: []
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ required_rubygems_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ requirements: []
160
+ rubyforge_project:
161
+ rubygems_version: 2.6.13
162
+ signing_key:
163
+ specification_version: 4
164
+ summary: A knife plugin for testing Chef cookbooks
165
+ test_files: []